2011-08-24 77 views
5

我想快速获得一个错误.Net客户端库的第三方服务,我正在使用的工作。原始库(其工作原理)是用Ruby编写的,但它们的DotNet等价库产生与Ruby库不同的哈希输出。HMC SHA1哈希 - C#产生不同的哈希输出比红宝石

红宝石加密代码如下:

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(); 
} 

正确答案

由于孔翰宁博士的答案如下,我能够确定正确的代码是:

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(); 
+0

也许http://stackoverflow.com/questions/3393790/how-to-do-it-in-ruby-on-rails可以提供帮助吗? –

+1

你会想,但是没有:( –

+0

)你自己做了什么来调试这个问题?至少可以预料到的是,你会调查HMAC原语的二进制输入是否相同,你的C#版本是用十六进制编码和子字符串提取做一些奇怪的东西,但是你的Ruby代码似乎并不存在。那么你确定Ruby版本实际上是在你背后做这些吗? –

回答

4

如果我理解代码,Ruby代码似乎在将它提供给HMAC之前分别对密钥进行散列处理(它不需要加密密钥,因为HMAC会在必要时自己散列长密钥),并且将HMAC的散列密钥与原始消息一起使用。

在另一方面,你的C#代码计算一个HMAC与键码和消息的哈希。 (令人费解的是,存储散列消息的变量被称为saltprivate_key_binary,虽然内容既不是盐也不是键......)

我无法想象Ruby和C#库会如此不同地处理HMAC这是正确的做法。

+0

非常好,你是对的,我没有解释我正在读的东西。谢谢你通过它说话。我已更新我的问题以包含正确的答案。 –