如何在浏览器中复制Node的Crypto.createHmac('sha256',buffer)?

时间:2019-05-24 15:08:53

标签: javascript node.js base64

如何获得Node的Crypto.createHmac( 'sha256', buffer)CryptoJS.HmacSHA256(..., secret)之间的“特征奇偶性”?

我有一个第三方代码,可以完成此处的方法node1。我需要在浏览器中实现相同的结果。看来,区别在于secret在节点侧被base64解码。但是我仍然无法获得相同的输出。

const CryptoJS = require('crypto-js')
const Crypto = require('crypto')

const message = "Message"
const secret = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="

function node1() {
  return Crypto.createHmac("sha256", Buffer.from(secret, 'base64'))
      .update(message, "utf8")
      .digest("base64");
}

function node2() {
  return Crypto.createHmac("sha256", Buffer.from(secret, 'base64').toString('base64'))
      .update(message, "utf8")
      .digest("base64");
}

function browser() {
  const crypted = CryptoJS.HmacSHA256(message, secret)
  return CryptoJS.enc.Base64.stringify(crypted)
}

console.log('node1', node1())
console.log('node2', node2())
console.log('browser-like', browser())

// node1 agitai8frSJpJuXwd4HMJC/t2tluUJPMZy8CeYsEHTE=
// node2 fxJQFWs5W3A4otaAlnlV0kh4yfQPb4Y1ChSVZsUAAXA=
// browser-like fxJQFWs5W3A4otaAlnlV0kh4yfQPb4Y1ChSVZsUAAXA=

因此,我可以在节点中重现幼稚的类似浏览器的行为。这使我有了在浏览器中使用atob来重现节点行为的想法。在浏览器方面,以下sign方法是我最好的猜测。

function sign(message) {
  const crypted = CryptoJS.HmacSHA256(message, atob(secret));
  return CryptoJS.enc.Base64.stringify(crypted)
}

function signNotDecoded(message) {
  const crypted = CryptoJS.HmacSHA256(message, secret);
  return CryptoJS.enc.Base64.stringify(crypted)
}

console.log('browser', sign('Message'))
console.log('browser-like', signNotDecoded('Message'))

// browser dnVm5jBgIBNV6pFd4J9BJTjx3BFsm7K32SCcEQX7RHA= 
// browser-like fxJQFWs5W3A4otaAlnlV0kh4yfQPb4Y1ChSVZsUAAXA=

因此,在浏览器中运行signDecoded()并在node中运行browser()会得到相同的输出。再次在节点中运行node2()browser()都提供相同的输出,但是sign()node1()仍然不同。

基于上述内容,我很确定问题出在我使用atob的问题上,但是我想念在那里吗?

1 个答案:

答案 0 :(得分:1)

更改

#!/bin/sh
enter=$( printf '\015' )
ctrl_c=$( printf '\003' )
ctrl_x=$( printf '\030' )
ctrl_z=$( printf '\032' )

yesno () {
    printf '%b [Y/N] ' "$1"
    old_stty_cfg=$( stty -g )
    stty raw -echo
    while true ; do
        answer=$( head -c 1 )
        case $answer in *"$ctrl_c"*|"$ctrl_x"*|"$ctrl_z"*)
            stty "$old_stty_cfg"
            exit 1
            ;;
            *"y"*|"Y"*)
            stty "$old_stty_cfg"
            return 0
            ;;
            *"n"*|"N"*)
            stty "$old_stty_cfg"
            return 1
            ;;
        esac
    done
}

if yesno "Question?" ; then
    printf "yes\n"
    exit 0
else
    printf "no\n"
    exit 1
fi

收件人

atob(secret)

因为如果将原始字符串作为键传递给该函数,它将被重新解析为UTF-8。