将字符串的MD5哈希值的最高8个字节取为长整数(在Ruby中) [英] Take most significant 8 bytes of the MD5 hash of a string as a long (in Ruby)

查看:347
本文介绍了将字符串的MD5哈希值的最高8个字节取为长整数(在Ruby中)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

朋友们,我正在尝试在ruby中实现一个Java"hash"功能.

Hey Friends, I'm trying to implement a java "hash" function in ruby.

这是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;
}

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

So far, my best guess in ruby is:

# 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输出不匹配.

Problem is, this ruby code doesn't match the java output.

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

For reference, the above java code given these strings returns the corresponding long:

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

想法:

  • 我在从红宝石字符串获取UTF8字节时遇到问题
  • 在红宝石中,我使用的是hexdigest,我怀疑我应该只使用digest
  • Java代码使用UTF8字节的md5,而我的ruby代码使用md5的字节(以十六进制表示)
  • I'm having problems getting the UTF8 bytes from the ruby string
  • In ruby I'm using hexdigest, I suspect I should be using just digest instead
  • The java code is taking the md5 of the UTF8 bytes whereas my ruby code is taking the bytes of the md5 (as hex)

关于如何获得与红宝石完全相同的输出的任何建议吗?

Any suggestions on how to get the exact same output in ruby?

推荐答案

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

这篇关于将字符串的MD5哈希值的最高8个字节取为长整数(在Ruby中)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆