2010-04-29 52 views
0

嘿,朋友,我试图在ruby中实现一个Java“哈希”函数。把一个字符串的MD5散列的最重要的8个字节作为一个长(在红宝石)

这里的Java方面:

import java.nio.charset.Charset; 
import java.security.MessageDigest; 

/** 
* @return most significant 8 bytes of the MD5 hash of the string, as a long 
*/ 
protected long hash(String value) { 
    byte[] md5hash; 
    md5hash = md5Digest.digest(value.getBytes(Charset.forName("UTF8"))); 
    long hash = 0L; 
    for (int i = 0; i < 8; i++) { 
    hash = hash << 8 | md5hash[i] & 0x00000000000000FFL; 
    } 
    return hash; 
} 

到目前为止,红宝石我最好的猜测是:

# WRONG - doesn't work properly. 
#!/usr/bin/env ruby -wKU 

require 'digest/md5' 
require 'pp' 

md5hash = Digest::MD5.hexdigest("0").unpack("U*") 
pp md5hash 
hash = 0 
0.upto(7) do |i| 
    hash = hash << 8 | md5hash[i] & 0x00000000000000FF 
end 
pp hash 

问题是,这个Ruby代码不匹配的java输出。

作为参考,给出这些字符串上面的Java代码返回相应的长:

"00038c53790ecedfeb2f83102e9115a522475d73" => -2059313900129568948 
"0" => -3473083983811222033 
"001211e8befc8ac22dd265ecaa77f8c227d0007f" => 3234260774580957018 

思想:

  • 我有从红宝石串获得UTF8字节问题
  • 在红宝石我使用hexdigest,我怀疑我应该只使用digest而不是
  • Java代码是采取md 5的UTF8字节,而我的红宝石代码是采取md5的字节(如十六进制)

任何建议如何获得完全相同的输出在红宝石?

回答

1
require 'digest/md5' 

class String 
    def my_hash 
    hi1, hi2, mid, lo = *Digest::MD5.digest(self).unpack('cCnN') 
    hi1 << 56 | hi2 << 48 | mid << 32 | lo 
    end 
end 

require 'test/unit' 
class TestMyHash < Test::Unit::TestCase 
    def test_that_my_hash_hashes_the_string_0_to_negative_3473083983811222033 
    assert_equal -3473083983811222033, '0'.my_hash 
    end 
end 
+0

不,测试用例是正确的。 Java long类型是64位_signed_整数类型,因此具有最高有效位集的值将产生负数。如上所述,0xcfcd208495d565ef的值为14973660089898329583 - 2^64 = -3473083983811222033。 – 2010-04-29 19:47:27

+0

@Thomas Pornin:是的,你是对的。我想我只是不习惯破碎算术的语言。 – 2010-04-29 21:43:28

相关问题