本文介绍了HMC SHA1哈希 - C#产生不同于Ruby的哈希输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

我正在尝试快速获得一个bug,用于我正在使用的第三方服务的.Net客户端库。原始库(其工作原理)是用Ruby编写的,但是它们的DotNet等效库为Ruby库生成不同的哈希输出。

I'm trying to quickly get a buggy .Net client library for a third party service I'm using to work. The original library (which works) is written in Ruby, but their equivalent library for DotNet produces differing hash output to the Ruby library.

Ruby加密代码如下:

The Ruby encryption code is as follows:

def self.encrypt_string(input_string)
  raise Recurly::ConfigurationError.new("Recurly gem not configured") unless Recurly.private_key.present?
  digest_key = ::Digest::SHA1.digest(Recurly.private_key)
  sha1_hash = ::OpenSSL::Digest::Digest.new("sha1")
  ::OpenSSL::HMAC.hexdigest(sha1_hash, digest_key, input_string.to_s)
end

(据称)等价的C#代码是:

The (supposedly) equivalent C# code is:

private static string ComputePrivateHash(string dataToProtect)
{
    if(String.IsNullOrEmpty(Configuration.RecurlySection.Current.PrivateKey))
        throw new RecurlyException("A Private Key must be configured to use the Recurly Transparent Post API.");

    byte[] salt_binary = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(dataToProtect));
    string salt_hex = BitConverter.ToString(salt_binary).Replace("-", "").ToLower();
    string salt = salt_hex.Substring(0, 20);

    HMACSHA1 hmac_sha1 = new HMACSHA1(Encoding.ASCII.GetBytes(Configuration.RecurlySection.Current.PrivateKey));
    hmac_sha1.Initialize();

    byte[] private_key_binary = Encoding.ASCII.GetBytes(salt);
    byte[] passkey_binary = hmac_sha1.ComputeHash(private_key_binary, 0, private_key_binary.Length);

    return BitConverter.ToString(passkey_binary).Replace("-", "").ToLower();
}

实际的哈希输出不同,给定相同的输入和私钥。 C#方法有什么问题导致错误的哈希输出?

The actual hash output differs though, given the same input and private key. What is wrong with the C# method that causes it to produce the wrong hash output?

编辑

这是方式 I 将编写代码,尽管仍然会产生错误的输出:

EDIT
This is the way I would have written the code, though it still produces the wrong output:

private static string ComputePrivateHash(string dataToProtect)
{
    if(String.IsNullOrEmpty(Configuration.RecurlySection.Current.PrivateKey))
        throw new RecurlyException("A Private Key must be configured to use the Recurly Transparent Post API.");

    var privateKey = Configuration.RecurlySection.Current.PrivateKey;
    var hashedData = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(dataToProtect));
    var hmac = new HMACSHA1(Encoding.UTF8.GetBytes(privateKey));
    var hash = hmac.ComputeHash(hashedData);
    return BitConverter.ToString(hash).Replace("-", "").ToLower();
}

正确答案

感谢Henning在下面的回答,我能够确定正确的代码是:

Thanks to Henning's answer below, I was able to determine that the correct code is:

var privateKey = Configuration.RecurlySection.Current.PrivateKey;
var hashedKey = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(privateKey));
var hmac = new HMACSHA1(hashedKey);
var hash = hmac.ComputeHash(Encoding.ASCII.GetBytes(dataToProtect));
return BitConverter.ToString(hash).Replace("-", "").ToLower();


推荐答案

如果我理解代码,似乎是Ruby代码在将其提供给HMAC之前,单独散列(这不需要加密的必要,因为HMAC会在必要时将哈希长键本身),并将哈希值与原始消息一起馈送给HMAC

If I understand the code, it seems the Ruby code is hashing the key separately before feeding it to HMAC (which shoudln't be cryptographically necessary, as HMAC will hash a long key itself if necessary), and feeds the hashed key to HMAC together with the original message.

另一方面,您的C#代码使用原始键和哈希来计算HMAC信息。 (不可思议的是,存储散列消息的变量称为 salt private_key_binary ,尽管内容既不是盐也不是一个关键...)

On the other hand, your C# code computes a HMAC with the original key and a hash of the message. (Inexplicably, the variables where you store the hashed message are called salt and private_key_binary, though the content is neither a salt nor a key...)

我无法想象Ruby和C#库将以不同的方式处理HMAC,这是正确的事情。

I cannot imagine that the Ruby and C# libraries would treat HMAC so differently that this is the right thing to do.

这篇关于HMC SHA1哈希 - C#产生不同于Ruby的哈希输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-06 17:29