将Go语言的HMAC转换为Node.js版本。

huangapple go评论106阅读模式
英文:

Convert go lang hmac into nodejs version

问题

我尝试将一个Go HMAC用例转换为Node.js,对于普通的HMAC,我知道如何将其转换为Node.js。但是我有以下Go代码。

注意:Go中的hmac.New的第一个参数是自定义哈希,即HMAC。但是我在Node.js版本中没有找到任何替代方法。

Node.js的createHmac只支持字符串哈希算法,不支持自定义哈希算法。有人知道如何在Node.js中实现相同的功能吗?

package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"hash"
)

func main() {
	hmacf := hmac.New(func() hash.Hash {
		return hmac.New(sha256.New, []byte("inner-key1"))
	}, []byte("inner-key2"))

	hmacf.Write([]byte("message"))
	fmt.Println(hex.EncodeToString(hmacf.Sum(nil)))
}

<details>
<summary>英文:</summary>

I try to convert one go hmac usecase into nodejs, for normal hmac I know how to convert it into nodejs. But I have the below go code.

&gt; Note: go `hmac.New` first arg is a custom hash which is HMAC. But I didn&#39;t find any alternative in nodejs version. 

Nodejs [createHmac][1] only support string hash algorithm, and can&#39;t support custom hash algorithm. Does anyone know how to implement the same feature in nodejs?

```go
package main

import (
	&quot;crypto/hmac&quot;
	&quot;crypto/sha256&quot;
	&quot;encoding/hex&quot;
	&quot;fmt&quot;
	&quot;hash&quot;
)
func main() {
	hmacf := hmac.New(func() hash.Hash {
		return hmac.New(sha256.New, []byte(&quot;inner-key1&quot;))
	}, []byte(&quot;inner-key2&quot;));

	hmacf.Write([]byte(&quot;message&quot;))
	fmt.Println(hex.EncodeToString(hmacf.Sum(nil)))
}

|
1: https://nodejs.org/api/crypto.html#cryptocreatehmacalgorithm-key-options

答案1

得分: 0

HMAC by definition uses a digest internally and not an HMAC. Therefore, the Go implementation is actually a generalization of the HMAC definition and it is not surprising that most libraries do not support this, just as it is not supported out-of-the-box by NodeJS. However, because of the comparatively simple definition of HMAC, it is easy to implement the required functionality.

The following is a recursive implementation that uses the crypto library:

const crypto = require('crypto')

function hmac_rec(data, keyList) {
    const digest = 'sha256', blockSizeOfDigest = 64
    var key = keyList.pop()
    if (keyList.length > 0) {
        // adjust key (according to HMAC specification)
        if (key.length > blockSizeOfDigest) {k = Buffer.allocUnsafe(blockSizeOfDigest).fill('\x00'); hmac_rec(key, [...keyList]).copy(k)}
        else if (key.length < blockSizeOfDigest) {k = Buffer.allocUnsafe(blockSizeOfDigest).fill('\x00'); key.copy(k)} 
        else k = key
        // create 'key xor ipad' and 'key xor opad' (according to HMAC specification)  
        var ik = Buffer.allocUnsafe(blockSizeOfDigest), ok = Buffer.allocUnsafe(blockSizeOfDigest)
        k.copy(ik); k.copy(ok)
        for (var i = 0; i < ik.length; i++) {ik[i] = 0x36 ^ ik[i]; ok[i] = 0x5c ^ ok[i]}
        // calculate HMAC(HMAC)
        var innerHMAC = hmac_rec(Buffer.concat([ ik, data ]), [...keyList]) 
        var HMAC = hmac_rec(Buffer.concat([ ok, innerHMAC ]), [...keyList])
    } else {
        // calculate regular HMAC(Hash)
        var HMAC = crypto.createHmac(digest, key).update(data).digest();
    }
    return HMAC 
}

Test:

var keyList = [ Buffer.from('inner-key1'), Buffer.from('inner-key2') ]
var data = Buffer.from('message', 'utf8')
var result = hmac_rec(data, keyList)
console.log(result.toString('hex')) // 48d2fcee3d16024d053db80f3e7140b853159f69d15a66d4cd6fad907b44e0cf

in accordance with the result of the posted Go Code.

英文:

HMAC by definition uses a digest internally and not an HMAC. Therefore, the Go implementation is actually a generalization of the HMAC definition and it is not surprising that most libraries do not support this, just as it is not supported out-of-the-box by NodeJS.
However, because of the comparatively simple definition of HMAC, it is easy to implement the required functionality.

The following is a recursive implementation that uses the crypto library:

const crypto = require(&#39;crypto&#39;)

function hmac_rec(data, keyList) {
    const digest = &#39;sha256&#39;, blockSizeOfDigest = 64
    var key = keyList.pop()
    if (keyList.length &gt; 0) {
        // adjust key (according to HMAC specification)
        if (key.length &gt; blockSizeOfDigest) {k = Buffer.allocUnsafe(blockSizeOfDigest).fill(&#39;\x00&#39;); hmac_rec(key, [...keyList]).copy(k)}
        else if (key.length &lt; blockSizeOfDigest) {k = Buffer.allocUnsafe(blockSizeOfDigest).fill(&#39;\x00&#39;); key.copy(k)} 
        else k = key
        // create &#39;key xor ipad&#39; and &#39;key xor opad&#39; (according to HMAC specification)  
        var ik = Buffer.allocUnsafe(blockSizeOfDigest), ok = Buffer.allocUnsafe(blockSizeOfDigest)
        k.copy(ik); k.copy(ok)
        for (var i = 0; i &lt; ik.length; i++) {ik[i] = 0x36 ^ ik[i]; ok[i] = 0x5c ^ ok[i]}
        // calculate HMac(HMac)
        var innerHMac = hmac_rec(Buffer.concat([ ik, data ]), [...keyList]) 
        var hMac = hmac_rec(Buffer.concat([ ok, innerHMac ]), [...keyList])
    } else {
        // calculate regular HMac(Hash)
        var hMac = crypto.createHmac(digest, key).update(data).digest();
    }
    return hMac 
}

Test:

var keyList = [ Buffer.from(&#39;inner-key1&#39;), Buffer.from(&#39;inner-key2&#39;) ]
var data = Buffer.from(&#39;message&#39;, &#39;utf8&#39;)
var result = hmac_rec(data, keyList)
console.log(result.toString(&#39;hex&#39;)) // 48d2fcee3d16024d053db80f3e7140b853159f69d15a66d4cd6fad907b44e0cf

in accordance with the result of the posted Go Code.

huangapple
  • 本文由 发表于 2023年8月4日 21:58:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76836631.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定