5

仕事に使用しているサード パーティ サービス用のバグのある .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# メソッドの何が問題になっていますか?

EDIT
これはがコードを書いた方法ですが、それでも間違った出力を生成します:

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

1 に答える 1

4

私がコードを理解している場合、RubyコードはキーをHMACに供給する前に個別にハッシュしているようです(HMACは必要に応じて長いキー自体をハッシュするため、暗号的に必要ではありません)、ハッシュされたキーを一緒にHMACに供給しますオリジナルメッセージ付き。

一方、C# コードは、元のキーとメッセージのハッシュを使用して HMAC を計算します。(不可解なことに、ハッシュ化されたメッセージを格納する変数は and と呼ばれますがsaltprivate_key_binary内容はソルトでもキーでもありません...)

Ruby と C# のライブラリが HMAC を異なる方法で扱うため、これが正しいことだとは想像できません。

于 2011-08-24T12:26:14.630 に答える