私は 2 つの異なるライブラリを使用して、ファイル検証で使用する SHA-1 ハッシュを生成しています。Crypto++ライブラリの古いバージョンと、Ruby によって実装された Digest::SHA1 クラスです。エンコーディングの違いが原因でハッシュが一致しない例を他にも見たことがありますが、2 つのライブラリはほぼ同一のハッシュを出力しています。
たとえば、各プロセスでファイルを渡すと、次の結果が生成されます。
暗号++ 01c15e4f46d8181b984fa2a2c740f8f67130acac
ルビー: eac15e4f46d8181b984fa2a2c740f8f67130acac
ご覧のとおり、ハッシュ文字列の最初の 2 文字だけが異なっており、この動作は多くのファイルで繰り返されます。各実装のソース コードを調べましたが、一見しただけでわかった唯一の違いは、160 ビット ハッシュに使用されている 16 進数のデータです。その 16 進数がアルゴリズムでどのように使用されているのかわかりません。以前にこの問題に遭遇したことがある場合に備えて、質問する方がおそらく早いと思いました。
以下のそれぞれのライブラリからのデータを含めました。3 つのライブラリの値はそれぞれわずかに異なるため、OpenSSL の値も含めました。
暗号++:
digest[0] = 0x67452301L;
digest[1] = 0xEFCDAB89L;
digest[2] = 0x98BADCFEL;
digest[3] = 0x10325476L;
digest[4] = 0xC3D2E1F0L;
ルビー:
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
OpenSSL:
#define INIT_DATA_h0 0x67452301UL
#define INIT_DATA_h1 0xefcdab89UL
#define INIT_DATA_h2 0x98badcfeUL
#define INIT_DATA_h3 0x10325476UL
#define INIT_DATA_h4 0xc3d2e1f0UL
ちなみに、Ruby でハッシュを生成するために使用されているコードは次のとおりです。Crypto++ 実装のソース コードにアクセスできません。
File.class_eval do
def self.hash_digest filename, options = {}
opts = {:buffer_length => 1024, :method => :sha1}.update(options)
hash_func = (opts[:method].to_s == 'sha1') ? Digest::SHA1.new : Digest::MD5.new
open(filename, "r") do |f|
while !f.eof
b = f.read
hash_func.update(b)
end
end
hash_func.hexdigest
end
end