2011-08-24 79 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

非常好,你是對的,我沒有解釋我正在讀的東西。謝謝你通過它說話。我已更新我的問題以包含正確的答案。 –