预期 MAC 不同于从 NodeJS 到 Go 服务器的传入
Expected MAC different than incoming one from NodeJS to Go server
我在尝试在我的 NodeJS 和 Go 服务器之间实现 HMAC 时遇到问题。现在,从我的 Go 服务器生成的预期 MAC 与来自我的 NodeJS 服务器的实际 MAC 不同。
// NodeJS generated MAC
const generateMAC = (message, secret) => {
return crypto.createHmac('sha256', secret).update(message).digest('hex');
};
req.headers['blocklist-auth'] = generateMAC(
JSON.stringify(req.body),
secret
);
Go HMAC 验证(从 NodeJS 接收 MAC 并尝试 tp 验证)
func generateMAC(message []byte, secret []byte) []byte {
mac := hmac.New(sha256.New, secret)
_, err := mac.Write(message)
if err != nil {
return nil
}
s := mac.Sum(nil)
return s
}
// ValidMAC reports whether messageMAC is a valid HMAC tag for message.
func validMAC(message []byte, messageMAC []byte, secret []byte) bool {
expectedMAC := generateMAC(message, secret)
log.Infof("E: %s -- M: %s", string(expectedMAC), string(messageMAC), )
return hmac.Equal(messageMAC, expectedMAC)
}
调试后,我记录了预期的 MAC 和实际的 MAC 的样子
预计:
n\ufffd\ufffdmi\u0015\ufffd|\ufffdE\ufffd\ufffd>\ufffd\u000e0\u0012C1\ufffd\ufffd\ufffds?!\u001a|\ufffdH<!
实际:
55d31eb5caf5f5046d054fcf39721ba273cd97da66f663f8337e10ac62045197
我注意到预期和实际 MAC 之间的长度也不同。来自 NodeJS 的长度是预期 MAC 的两倍。不知道为什么。
它们似乎产生相同的结果,但您传递给节点代码中的摘要调用的编码是 'hex'
。
如果在两端以相同的方式编码 return,它们应该匹配。
const crypto = require('crypto')
const generateMAC = (message, secret) =>
crypto.createHmac('sha256', secret).update(message).digest('base64')
console.log(generateMAC('foo', 'bar'))
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
)
func generateMAC(message []byte, secret []byte) string {
mac := hmac.New(sha256.New, secret)
_, err := mac.Write(message)
if err != nil {
return "oh no"
}
return base64.StdEncoding.EncodeToString(mac.Sum(nil))
}
func main() {
fmt.Println(generateMAC([]byte("foo"), []byte("bar")))
}
这两个都产生相同的输出,因为它们都编码为 base64:FHkzIYqqvAuLEKKzpcNGhMjZQ0G88QpHNtxycPd0GFE=
.
.digest()
return如果未指定编码,默认情况下是一个缓冲区,然后您也可以使用 these encodings 之一在单独的 .toString()
中使用它。
我在尝试在我的 NodeJS 和 Go 服务器之间实现 HMAC 时遇到问题。现在,从我的 Go 服务器生成的预期 MAC 与来自我的 NodeJS 服务器的实际 MAC 不同。
// NodeJS generated MAC
const generateMAC = (message, secret) => {
return crypto.createHmac('sha256', secret).update(message).digest('hex');
};
req.headers['blocklist-auth'] = generateMAC(
JSON.stringify(req.body),
secret
);
Go HMAC 验证(从 NodeJS 接收 MAC 并尝试 tp 验证)
func generateMAC(message []byte, secret []byte) []byte {
mac := hmac.New(sha256.New, secret)
_, err := mac.Write(message)
if err != nil {
return nil
}
s := mac.Sum(nil)
return s
}
// ValidMAC reports whether messageMAC is a valid HMAC tag for message.
func validMAC(message []byte, messageMAC []byte, secret []byte) bool {
expectedMAC := generateMAC(message, secret)
log.Infof("E: %s -- M: %s", string(expectedMAC), string(messageMAC), )
return hmac.Equal(messageMAC, expectedMAC)
}
调试后,我记录了预期的 MAC 和实际的 MAC 的样子
预计:
n\ufffd\ufffdmi\u0015\ufffd|\ufffdE\ufffd\ufffd>\ufffd\u000e0\u0012C1\ufffd\ufffd\ufffds?!\u001a|\ufffdH<!
实际:
55d31eb5caf5f5046d054fcf39721ba273cd97da66f663f8337e10ac62045197
我注意到预期和实际 MAC 之间的长度也不同。来自 NodeJS 的长度是预期 MAC 的两倍。不知道为什么。
它们似乎产生相同的结果,但您传递给节点代码中的摘要调用的编码是 'hex'
。
如果在两端以相同的方式编码 return,它们应该匹配。
const crypto = require('crypto')
const generateMAC = (message, secret) =>
crypto.createHmac('sha256', secret).update(message).digest('base64')
console.log(generateMAC('foo', 'bar'))
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
)
func generateMAC(message []byte, secret []byte) string {
mac := hmac.New(sha256.New, secret)
_, err := mac.Write(message)
if err != nil {
return "oh no"
}
return base64.StdEncoding.EncodeToString(mac.Sum(nil))
}
func main() {
fmt.Println(generateMAC([]byte("foo"), []byte("bar")))
}
这两个都产生相同的输出,因为它们都编码为 base64:FHkzIYqqvAuLEKKzpcNGhMjZQ0G88QpHNtxycPd0GFE=
.
.digest()
return如果未指定编码,默认情况下是一个缓冲区,然后您也可以使用 these encodings 之一在单独的 .toString()
中使用它。