2010-04-29 40 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

相關問題