很多 Go 开发者第一次用 HmacSHA256,卡住的并不是算法本身,而是“该用哪个标准库”“返回值为什么看不懂”“落地时该输出什么格式”。这篇文章直接用一段可运行的 Go 代码把流程拆开:先算出 HMAC,再分别转成十六进制和 Base64,最后结合输出结果解释它们各自适合什么场景。读完你可以判断自己在接口签名、支付对接或数据校验时,应该保留二进制结果,还是转成可传输字符串。
HmacSHA256 适合用在什么场景
HmacSHA256 是实际开发里很常见的一种消息认证算法,安全性通常也比 MD5 更高。在一些需要签名校验的场景里,它的出现频率很高,例如接口鉴权、回调验签,以及文中提到的微信支付推荐做法。
在 Go 里实现它并不复杂。虽然不像 PHP 那样可以直接用一个 hash_hmac 函数完成,但相较于不少语言里偏冗长的写法,Go 标准库已经足够直接:核心就是 crypto/hmac 配合 crypto/sha256。
Go 语言中如何实现 HmacSHA256
下面这段代码完整展示了从 HMAC 计算,到十六进制和 Base64 输出的实现方式。原始逻辑可以概括为三步:创建 HMAC 实例、写入待加密内容、取回最终摘要。

package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"fmt"
)
// HmacSha256 计算HmacSha256
// key 是加密所使用的key
// data 是加密的内容
func HmacSha256(key string, data string) []byte {
mac := hmac.New(sha256.New, []byte(key))
_, _ = mac.Write([]byte(data))
return mac.Sum(nil)
}
// HmacSha256ToHex 将加密后的二进制转16进制字符串
func HmacSha256ToHex(key string, data string) string {
return hex.EncodeToString(HmacSha256(key, data))
}
// HmacSha256ToHex 将加密后的二进制转Base64字符串
func HmacSha256ToBase64(key string, data string) string {
return base64.URLEncoding.EncodeToString(HmacSha256(key, data))
}
func main() {
// secret 是加密要使用的key
// apple 是要加密的内容
fmt.Printf("HmacSha256转16字符串: %sn", HmacSha256ToHex("secret", "apple"))
fmt.Printf("HmacSha256转base字符串: %sn", HmacSha256ToBase64("secret", "apple"))
}
这段实现里,HmacSha256 返回的是原始二进制摘要,也就是最底层的 HMAC 结果。随后又封装了两个辅助函数:
HmacSha256ToHex:把结果转成十六进制字符串。HmacSha256ToBase64:把结果转成 Base64 字符串。
如果你只是要和第三方接口约定签名格式,通常直接调用后面两个封装函数会更方便;如果还要继续做底层字节处理,则保留 []byte 返回值更灵活。
为什么结果通常还要转成 Hex 或 Base64
HmacSha256 算出的本质上是二进制数据,其中会包含不可见字符,因此并不适合直接打印、传输或拼接到 URL、JSON、表单字段里。实际项目里,最常见的做法就是把它编码成可读、可传输的字符串。
文中的两种输出方式分别对应两类常见需求:
- 十六进制:格式直观,调试和比对都比较方便,很多签名文档会直接要求这种形式。
- Base64:字符串更紧凑,适合需要减少长度、在协议中传输摘要值的情况。
示例代码里使用的是 base64.URLEncoding,说明输出结果会采用 URL 安全字符集,这在需要通过 URL 或部分 Web 场景传递签名时更省心。
运行结果与输出说明
按照示例中的 key 和 data,程序运行结果如下:

HmacSha256转16字符串: 37431003b2d14b6bddb9334c7ec2ff0ea0c65f96ec650952384e56cae83c398f
HmacSha256转base字符串: N0MQA7LRS2vduTNMfsL_DqDGX5bsZQlSOE5Wyug8OY8=
这里可以直接看出,同一份 HMAC 结果经过不同编码后,会变成两种外观不同但语义一致的字符串。换句话说,变化的是“表示形式”,不是底层摘要本身。
如果你在对接接口时发现本地算出的值和文档示例不同,优先排查以下几点:
key是否完全一致,包括大小写和隐藏空格。- 参与签名的原始字符串是否一致,尤其是参数顺序、拼接符号和换行。
- 对方要求的是原始二进制、十六进制,还是 Base64。
- Base64 是否要求 URL 安全版本。
需要更多算法时可以直接用现成库
如果你的需求不止于 HmacSHA256,还要处理对称加密、非对称加密或其他摘要算法,可以直接看一个现成的 Go 加解密库:https://github.com/forgoer/openssl。
这个库支持的常用算法包括 AES、DES、RSA、sha1、Hmac-Sha1、sha256、Hmac-Sha256 等。对于只做单一 HMAC 计算的场景,Go 标准库已经够用;如果项目里还涉及多种加解密能力,再引入统一封装库会更省事。













