将字符串的 MD5 哈希值的最高 8 个字节视为 long(在 Ruby 中)

发布于 2024-08-30 09:09:50 字数 1317 浏览 5 评论 0原文

嘿朋友们,我正在尝试在 ruby​​ 中实现 java“哈希”函数。

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

到目前为止,我对ruby的最佳猜测是:

# 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代码返回相应的long:

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

想法:

  • 我在从ruby字符串获取UTF8字节时遇到问题
  • 在ruby中我使用hexdigest,我怀疑我应该是仅使用 digest 代替
  • Java 代码采用 UTF8 字节的 md5,而我的 ruby​​ 代码采用 md5 的字节(十六进制)

关于如何在 ruby​​ 中获得完全相同的输出有什么建议吗?

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

Here's the java side:

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

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

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

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

Thoughts:

  • 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

紅太極 2024-09-06 09:09:50
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
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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文