无法复制字符串的散列

Can't replicate hashing of string

我需要在 r.
中重现一个用 SHA-256 散列字符串的 JS 函数 上述函数为:

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 上,因为在这两种情况下,我猜测变量都是作为原始变量传递的。

非常感谢任何帮助。

因为您创建了一个 Uint16Array,所以每个字符使用两个字节,并且这些值可能以小端字节顺序存储。默认情况下,在 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="

所以真的只是确保你在两种语言中以完全相同的方式将你的字符串编码成字节。