HMC SHA1哈希 – C#产生与Ruby不同的哈希输出

我正在努力为我正在使用的第三方服务快速获取一个bug .Net客户端库。 原始库(可以工作)是用Ruby编写的,但它们等效的DotNet库为Ruby库产生了不同的哈希输出。

Ruby加密代码如下:

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#代码是:

 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#方法有什么问题?

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

 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的回答,我能够确定正确的代码是:

 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与原始消息。

另一方面,您的C#代码使用原始密钥和消息的散列计算HMAC。 (令人费解的是,存储散列消息的变量称为saltprivate_key_binary ,尽管内容既不是盐也不是密钥……)

我无法想象Ruby和C#库会如此区别对待HMAC,这是正确的做法。