c# - HMC SHA1 哈希 - C# 生成与 Ruby 不同的哈希输出

标签 c# ruby encryption sha1 hmac

我正在尝试为我正在使用的第三方服务快速获取有问题的 .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 之前分别对 key 进行哈希处理(这在密码学上不是必需的,因为 HMAC 会在必要时自行对长 key 进行哈希处理),并将散列 key 与原始消息一起提供给 HMAC。

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

我无法想象 Ruby 和 C# 库会如此不同地对待 HMAC,以至于这是正确的做法。

关于c# - HMC SHA1 哈希 - C# 生成与 Ruby 不同的哈希输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7175067/

相关文章:

css - 如何更改 Bootstrap 链接的颜色

c# - 如何在 C# 中使用教科书 RSA 加密 ASCII 字符?

c# - Controller 上的 "CA2000 Dispose objects before losing scope"

c# - 如何将 HttpRequestMessage 转发到另一台服务器

c# - 在 Entity Framework 中为大型列表使用 IList.Contains(item.Id) 的替代方案?

java - 如何使用java将字节数组 append 到文件而不覆盖它

php - MySQL有时无效的查询语法

c# - 为什么在 oauth2 中缓存访问 token 被认为是不好的?

Ruby:捕获 system() 的输出并在终端中打印

ruby - 检查对象中是否存在属性