【问题标题】:Can't replicate hashing of string无法复制字符串的散列
【发布时间】:2021-09-29 06:47:47
【问题描述】:

我需要重现一个 JS 函数,该函数在 r 中使用 SHA-256 对字符串进行哈希处理。
上述功能是:

function hashPhrase (phrase) {
  const buf = new ArrayBuffer(phrase.length * 2)
  const bufView = new Uint16Array(buf)
  const strLen = phrase.length
  for (let i = 0; i < strLen; i++) {
    bufView[i] = phrase.charCodeAt(i)
  }
  return window.crypto.subtle.digest('SHA-256', buf)
    .then(hashArrayBuffer => {
      let binary = ''
      const bytes = new Uint8Array(hashArrayBuffer)
      const len = bytes.byteLength
      for (let i = 0; i < len; i++) {
        binary += String.fromCharCode(bytes[i])
      }
      return Promise.resolve(window.btoa(binary))
    })
}

调用函数:

hashPhrase('test').then(x => { console.log(x) })

给我:

/lIGdrGh2T2rqyMZ7qA2dPNjLq7rFj0eiCRPXrHeEOs=

作为输出。

我加载 openssl 并尝试使用 sha256 作为函数来散列字符串。

library(openssl)

phrase = "test"
phraseraw = charToRaw(phrase)
base64_encode(sha256(phraseraw))

输出是:

[1] "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="

不知道问题是否出在 uint16 上,因为在这两种情况下,我都猜想变量是作为原始参数传递的。

我将非常感谢任何帮助。

【问题讨论】:

    标签: r hash uint16


    【解决方案1】:

    因为您创建了一个 Uint16Array,所以每个字符使用两个字节,并且这些值可能以 little-endian 字节顺序存储。默认情况下,在 R 中,由于您只有 ASCII 字符,因此每个字符仅使用一个字节。所以使用 javascript 你正在消化字节

    [116, 0, 101, 0, 115, 0, 116, 0]
    

    但是使用 R 代码,您正在消化字节。

    [116, 101, 115, 116]
    

    如果您真的想像在 javascript 中一样在 R 中包含这些填充值,您可以在摘要之前转换为 UTF16-LE

    phrase = "test"
    phraseraw = iconv(phrase,from="ASCII", to="UTF-16LE",toRaw = TRUE)[[1]]
    base64_encode(sha256(phraseraw))
    # [1] "/lIGdrGh2T2rqyMZ7qA2dPNjLq7rFj0eiCRPXrHeEOs="
    

    因此,请确保您在两种语言中以完全相同的方式将字符串编码为字节。

    【讨论】:

    • 这太棒了!!
    • 非常感谢。是的,我每个字符使用两个字节,但不知道如何在 R 中做到这一点。我真的很接近但使用 iconv() 不正确。
    猜你喜欢
    • 2014-03-25
    • 2015-05-31
    • 2011-09-30
    • 2020-03-17
    • 2015-05-02
    • 2011-12-25
    • 1970-01-01
    • 1970-01-01
    • 2011-12-22
    相关资源
    最近更新 更多