英文:
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.
> Note: go `hmac.New` first arg is a custom hash which is HMAC. But I didn't find any alternative in nodejs version.
Nodejs [createHmac][1] only support string hash algorithm, and can't support custom hash algorithm. Does anyone know how to implement the same feature in nodejs?
```go
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)))
}
|
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('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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论