【发布时间】:2011-11-02 18:07:30
【问题描述】:
我正在尝试为我用来工作的第三方服务快速获取一个有缺陷的 .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();
【问题讨论】:
-
你会想,但不是:(
-
您为自己调试问题做了哪些工作?至少可以期望您调查 HMAC 原语的二进制输入是否相同。您的 C# 版本正在使用 Ruby 代码中似乎不存在的十六进制编码和子字符串提取做一些奇怪的事情。那么你确定 Ruby 版本实际上是在背后做这一切吗?
-
嘿,是的,我已经做了很多尝试和调试问题。我已经以几种不同的方式重写了该方法,对每种方法运行单元测试以检查输出,但是我的尝试都没有奏效。我同意子字符串代码看起来不合适,尽管我对加密有点粗略而且我没有编写此代码;这是图书馆里的东西。
-
您能否向我们展示一下示例输入和键的输出?
标签: c# ruby encryption sha1 hmac