2010-04-29 12 views
0

Salut les amis, J'essaie d'implémenter une fonction java "hash" dans ruby.Prenez les 8 octets les plus significatifs du hachage MD5 d'une chaîne comme un long (en Ruby)

est ici le côté 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; 
} 

Jusqu'à présent, ma meilleure estimation en Ruby est:

# 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 

Le problème est, ce code Ruby ne correspond pas à la sortie de java.

Pour référence, le code java ci-dessus étant donné ces chaînes renvoie les correspondants à long:

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

Pensées:

  • Je vais avoir des problèmes pour obtenir les octets UTF8 de la chaîne rubis
  • En ruby ​​j'utilise hexdigest, je suppose que je devrais utiliser seulement digest à la place
  • Le code java prend le md 5 des octets UTF8 tandis que mon code ruby ​​prend les octets de la md5 (comme hex)

Des suggestions sur la façon d'obtenir exactement la même sortie en ruby?

Répondre

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

Non, le boîtier de test est correct. Un type Java 'long' est un type _signed_ integer 64 bits, donc une valeur avec l'ensemble de bits le plus significatif donnera un nombre négatif. Ici, 0xcfcd208495d565ef a la valeur 14973660089898329583 - 2^64 = -3473083983811222033, comme indiqué. –

+0

@Thomas Pornin: Oui, vous avez raison. Je suppose que je ne suis pas habitué aux langues avec l'arithmétique cassée. –