在开发过程中,我们经常使用 HMAC(散列消息认证码)对数据进行签名,以确保数据完整性和身份验证。
然而,不同编程语言在对签名数据进行编码时可能会有所不同,导致相同的 HMAC 计算在不同语言中产生不同的结果。
这篇文章也是因为我直接将 PHP 的签名算法扔给 ChatGPT 生成,并没有实际测试,导致客户反馈签名计算失败,测试后才发现的。
本文将以 Go 和 PHP 为例,探讨为什么直接对 HMAC 签名进行 Base64 编码与先转换为 16 进制字符串再编码的结果不同。
package main
import (
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"encoding/hex"
"fmt"
)
func main() {
data := "hello"
password := "123456"
h := hmac.New(sha1.New, []byte(password))
h.Write([]byte(data))
signatureBytes := h.Sum(nil)
// 直接对 HMAC 结果进行 Base64 编码
base64Signature := base64.StdEncoding.EncodeToString(signatureBytes)
fmt.Println(base64Signature) // 输出:NYSQUfYBHG0EZ6pU+r+Iw4CvPIQ=
// 先转换成 16 进制字符串,再进行 Base64 编码
hexString := hex.EncodeToString(signatureBytes)
base64OfHex := base64.StdEncoding.EncodeToString([]byte(hexString))
fmt.Println(base64OfHex) // 输出:MzU4NDkwNTFmNjAxMWM2ZDA0NjdhYTU0ZmFiZjg4YzM4MGFmM2M4NA==
}
<?php
$data = "hello";
$password = "123456";
// 直接对 HMAC 结果进行 Base64 编码
echo base64_encode(hash_hmac('sha1', $data, $password, true));
// 输出:NYSQUfYBHG0EZ6pU+r+Iw4CvPIQ=
echo "\n";
// 先转换成 16 进制字符串,再进行 Base64 编码
echo base64_encode(hash_hmac('sha1', $data, $password));
// 输出:MzU4NDkwNTFmNjAxMWM2ZDA0NjdhYTU0ZmFiZjg4YzM4MGFmM2M4NA==
?>
表面上看,Go 和 PHP 代码的逻辑是相同的,但它们的 Base64 结果却不同。
其根本原因在于编码前的输入数据不同。
hash_hmac(
string $algo,
string $data,
#[\SensitiveParameter] string $key,
bool $binary = false
): string
PHP 手册中也提到了:当 binary
设置为 true
输出原始二进制数据,设置为 false
输出小写 16 进制字符串。
signatureBytes
是 HMAC 计算出的二进制数据。hash_hmac('sha1', $data, $password, true)
也返回二进制数据。hash_hmac('sha1', $data, $password)
默认返回 16 进制字符串,每个字节被转换成 2 个字符。hex.EncodeToString(signatureBytes)
也会将二进制数据转换为 16 进制字符串。Base64 编码的主要作用是将二进制数据转换为文本格式,便于在 URL 或 JSON 等环境中传输。
它不会改变数据的内容,而是按照固定的方式将每 3 个字节转换为 4 个可打印字符。
因此,输入数据的不同会直接影响最终的编码结果。
如果希望跨语言 HMAC 计算保持一致,建议:
hash_hmac('sha1', $data, $password, true)
以获取二进制结果。base64.StdEncoding.EncodeToString(signatureBytes)
,避免中间转换为 16 进制字符串。希望这篇文章能帮助你理解 HMAC 签名在不同语言中的编码差异,并在开发中避免类似的问题!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有