4

私は 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
4

2 に答える 2

2

SHA-1ハッシュを出力する際に​​、1バイトずれていると思います。それらを印刷しているコードを見ることができますか? そうでない場合は、役立つ可能性があるいくつかの診断を次に示します。

  1. 非常に短いファイル (たとえば、1 語) を作成し、その内容をhttp://www.fileformat.info/tool/hash.htmに 16 進文字列として配置します。ただし、ファイルの 16 進数の内容を正確に知る必要があります。Unix では xxd を使用できますが、エンディアンの問題に注意する必要があります。他のOSでどうすればよいかわかりません。

  2. 同じ SHA-1 実装で同じファイルを数回実行すると、常に最初のバイトに同じ値が出力されますか? もしそうなら、ファイルを変更するとその値は変わりますか?

于 2010-08-19T01:11:57.290 に答える
2

これはあまり意味がありません。これらの数値など、SHA1 の実装に問題がある場合、1 バイトだけではなく、実際の SHA1 ハッシュとは完全に異なるハッシュが生成される可能性があります。ファイルの読み取りループに何か問題があったとしても、改行などを削除したとしても、ストリーム内の 1 バイトを変更することで完全に異なるハッシュを取得できます。実際の SHA1 ハッシュから 1 バイトずれることはありません。 .

次のプログラムであなたの方法を使用すると、正しい結果が得られます。

#!/usr/bin/env ruby
require 'digest/sha1'
require 'digest/md5'

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

puts File.hash_digest(ARGV[0])

その出力は、OpenSSL の出力と比較されます。

tmp$ dd if=/dev/urandom of=random.bin bs=1MB count=1
1+0 records in
1+0 records out
1000000 bytes (1.0 MB) copied, 0.287903 s, 3.5 MB/s
tmp$ ./digest.rb random.bin
a511d8153426ebea4e4694cde78db4e3a9e413d1
tmp$ openssl sha1 random.bin
SHA1(random.bin)= a511d8153426ebea4e4694cde78db4e3a9e413d1

したがって、ハッシュ方法に問題はありません。戻り値と出力の間で何か問題が発生しています。

于 2010-08-22T04:41:24.993 に答える