Go 语言中实现 HmacSHA256:从标准库写法到 Hex 与 Base64 输出

青禾
青禾
发布时间:2026-08-25 | 86人浏览过
原创

前言

很多人第一次在 Go 里处理 HmacSHA256,难点其实不在算法,而在结果如何落地使用:算出来的是二进制,接口文档要的却往往是可传输字符串。下面结合一段可直接运行的示例,把标准库实现、Hex 与 Base64 转换,以及验签时最容易出错的环节一次说明白。

很多 Go 开发者第一次用 HmacSHA256,卡住的并不是算法本身,而是“该用哪个标准库”“返回值为什么看不懂”“落地时该输出什么格式”。这篇文章直接用一段可运行的 Go 代码把流程拆开:先算出 HMAC,再分别转成十六进制和 Base64,最后结合输出结果解释它们各自适合什么场景。读完你可以判断自己在接口签名、支付对接或数据校验时,应该保留二进制结果,还是转成可传输字符串。

HmacSHA256 适合用在什么场景

HmacSHA256 是实际开发里很常见的一种消息认证算法,安全性通常也比 MD5 更高。在一些需要签名校验的场景里,它的出现频率很高,例如接口鉴权、回调验签,以及文中提到的微信支付推荐做法。

在 Go 里实现它并不复杂。虽然不像 PHP 那样可以直接用一个 hash_hmac 函数完成,但相较于不少语言里偏冗长的写法,Go 标准库已经足够直接:核心就是 crypto/hmac 配合 crypto/sha256。

Go 语言中如何实现 HmacSHA256

下面这段代码完整展示了从 HMAC 计算,到十六进制和 Base64 输出的实现方式。原始逻辑可以概括为三步:创建 HMAC 实例、写入待加密内容、取回最终摘要。

展示 Go 中 HmacSHA256 从 key 和 data 输入,到二进制摘要、Hex 与 Base64 两种输出的暖色专栏流程图。
HmacSHA256 的实现与输出流程把 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 输出结果为什么要转码,以及排查签名不一致时应检查哪些项目的暖色专栏便签图。
输出格式与验签排查要点这张图适合放在输出结果章节后,帮助读者区分“摘要本身”和“字符串表示形式”。
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 标准库已经够用;如果项目里还涉及多种加解密能力,再引入统一封装库会更省事。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表