Python与Haskell实现HMAC-SHA256签名时编码输出不一致
差异产生原因
两端输出不一致是因为使用了不同变体的Base64编码规则,HMAC-SHA256哈希计算本身逻辑完全正确:
- Python端
base64.b64encode实现的是标准Base64编码,使用+、/作为编码字符集的第62、63位特殊字符 - Haskell端引入的
Data.ByteString.Base64.URL模块提供的是URL安全Base64编码,该变体为了避免URL转义歧义,会将标准Base64中的+替换为-、/替换为_,和你观察到的字符替换规律完全吻合。
修复方案
将Haskell端的Base64编码从URL安全变体替换为标准Base64,即可和Python输出完全对齐,修改步骤如下:
- 替换导入模块,移除URL安全Base64的导入,引入标准Base64模块:
-- 移除原导入:import qualified Data.ByteString.Base64.URL as U import qualified Data.ByteString.Base64 as B64
- 修改签名函数的编码逻辑,去掉多余的
encodeUtf8转码(标准Base64编码输出本身就是合法的UTF-8字节串,不需要二次转码),调用标准Base64编码方法:
apiSignTest :: BC.ByteString -> BC.ByteString -> BC.ByteString -> BC.ByteString -> IO BC.ByteString apiSignTest time method endpoint body = do let signContent = mconcat [time, method, endpoint, body] let hmacHash = H.hmac (BC.pack C.apiSecretFuture) signContent return $ B64.encode hmacHash
修改后重新编译运行,两端的签名输出会完全一致。
内容的提问来源于stack exchange,提问作者artin ghasivand
相关产品推荐
相关产品推荐

