为何PHP生成的HMAC-SHA256与在线工具结果不一致?
HMAC-SHA256生成结果与在线工具不一致的原因
问题重现
我用以下PHP代码生成HMAC-SHA256并做Base64编码:
$data ="sdkfhglkjfdsglfdslkgjdfl;kjsdflk;jsdlgldgweprepoifepiorgi"; $secret = "da851675-c797-4edd-b492-af1c0753e5c0"; $hash = hash_hmac('sha256', $data, $secret); $base64 = base64_encode($hash); echo $base64;
但生成的哈希结果始终和在线HMAC工具的结果不一致,下面这段JavaScript代码也存在同样问题:
var data ="sdkfhglkjfdsglfdslkgjdfl;kjsdflk;jsdlgldgweprepoifepiorgi" var secret = "da851675-c797-4edd-b492-af1c0753e5c0" function generate_data_hash(data, secret) { var hash = CryptoJS.HmacSHA256(data, secret); var hashInBase64 = CryptoJS.enc.Base64.stringify(hash); return hashInBase64 } console.log(generate_data_hash(data, secret))
问题根源
- PHP代码的核心错误:
hash_hmac()函数默认返回的是十六进制编码的字符串,而非HMAC-SHA256算法生成的原始二进制哈希值。你后续对这个十六进制字符串做Base64编码,本质是对"哈希的字符串表示"编码,而非对"哈希本身"编码,结果自然和在线工具不符。 - JavaScript代码的误解:你的CryptoJS代码逻辑是正确的——
CryptoJS.HmacSHA256()返回的是原始哈希对象,直接用Base64.stringify()处理就能得到标准结果。如果测试结果不一致,大概率是测试时输入参数不匹配,或者在线工具误将密钥解析为十六进制格式(而非明文)。
修正后的代码
PHP版本
给hash_hmac()添加第四个参数true,获取原始二进制哈希值后再做Base64编码:
$data ="sdkfhglkjfdsglfdslkgjdfl;kjsdflk;jsdlgldgweprepoifepiorgi"; $secret = "da851675-c797-4edd-b492-af1c0753e5c0"; // 传入true参数获取二进制哈希值 $hash = hash_hmac('sha256', $data, $secret, true); $base64 = base64_encode($hash); echo $base64;
JavaScript版本(无需修改,确认输入一致即可)
var data ="sdkfhglkjfdsglfdslkgjdfl;kjsdflk;jsdlgldgweprepoifepiorgi" var secret = "da851675-c797-4edd-b492-af1c0753e5c0" function generate_data_hash(data, secret) { var hash = CryptoJS.HmacSHA256(data, secret); var hashInBase64 = CryptoJS.enc.Base64.stringify(hash); return hashInBase64 } console.log(generate_data_hash(data, secret))
验证
修正后的PHP代码生成的结果,会和CryptoJS代码以及标准在线工具的输出完全一致。
内容的提问来源于stack exchange,提问作者Gan3i
相关产品推荐
相关产品推荐

