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 seulementdigest
à 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?
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é. –
@Thomas Pornin: Oui, vous avez raison. Je suppose que je ne suis pas habitué aux langues avec l'arithmétique cassée. –