我正在使用两个不同的库来生成用于文件验证的SHA-1哈希 - 较早版本的Crypto++库和由Ruby实现的Digest :: SHA1类。虽然我已经看到了编码差异导致的其他不匹配哈希实例,但这两个库正在输出几乎相同的哈希值。
例如,通过每个进程传递文件会产生以下结果:
加密++ 01c15e4f46d8181b984fa2a2c740f8f67130acac
红宝石: eac15e4f46d8181b984fa2a2c740f8f67130acac
如您所见,只有哈希字符串的前两个字符不同,并且此行为会在许多文件中重复出现。我已经看了每个实现的源代码,我乍一看的唯一区别是用于160位散列的数据十六进制。我不知道算法中是如何使用该十六进制的,我认为如果有人之前遇到过这个问题,我可能会更快地提出这个问题。
我已经包含了以下相应图书馆的数据。我还包括了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
答案 0 :(得分:2)
我猜你在打印出SHA-1哈希值时已经关闭了一个字节。我们能看到打印它们的代码吗?如果没有,这里有几个可能有用的诊断:
制作一个非常短的文件(例如,一个单词),并将其内容放在http://www.fileformat.info/tool/hash.htm的十六进制字符串中。但是,您需要确切地知道文件的十六进制内容。您可以在Unix上使用xxd,但是您必须注意字节序问题。我不确定如何在其他操作系统上执行此操作。
多次通过相同的SHA-1实现运行相同的文件总是在第一个字节中打印出相同的值?如果是这样,更改文件时该值是否会发生变化?
答案 1 :(得分:2)
这没有多大意义。如果SHA1实现有问题,例如使用这些数字,它可能会产生与真实SHA1哈希值完全不同的哈希值,而不仅仅是一个字节关闭。即使文件读取循环出现问题,它会丢弃换行符,你仍然可以通过改变流中的一个字节来获得完全不同的散列,它不会是真正的SHA1散列的一个字节
如果我在以下程序中使用您的方法,我会得到正确的结果。
#!/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
因此,您的散列方法没有任何问题。它的返回值和打印值之间出现了问题。