在RestFul接口应用Hmac算法

1 简介

HMAC(基于哈希的消息认证码)是一种消息认证码(MAC),通过对要认证的数据和秘密共享密钥执行加密哈希函数来获取。与任何 MAC 一样,它用于数据完整性和身份验证。

HMAC(基于哈希的消息认证码)是一种加密技术,它使用哈希函数和密钥来确保数据的完整性和真实性。与基于签名和非对称密码学的方法不同。HMAC 的 公式非常容易理解:

ini 复制代码
		HMAC = hashFunc(secret key + message) 

检查数据完整性对于参与通信的各方来说是必要的。HTTPS、SFTP、FTPS 和其他传输协议都可以使用 HMAC。加密哈希函数可以是 MD-5、SHA-1 或 SHA-256。

数字签名几乎与 HMAC 相似,即它们都采用哈希函数和共享密钥。区别在于密钥,即 HMAC 使用对称密钥(同一副本),而签名使用非对称密钥(两个不同的密钥)。

2 在Rest API 场景中的签名生成

有三种类型的身份验证功能。它们是消息加密、消息验证码和哈希函数。

MAC 和哈希(这里是 HMAC)之间的主要区别在于密钥的依赖性。

在 HMAC 中,我们必须在纯文本上应用哈希函数和键。哈希函数将应用于纯文本消息。但在应用之前,我们必须计算 S 位,然后将其附加到纯文本中,然后应用哈希函数。为了生成这些 S 位,我们使用发送方和接收方之间共享的密钥。

示例:按参数排序拼接,假设你的签名消息是把排序后的参数名和值直接拼成 key1value1key2value2...,要用 HMAC-SHA256 做签名,Go 示例:

go 复制代码
    import (
        "crypto/hmac"
        "crypto/sha256"
        "encoding/hex"
        "sort"
        "strings"
    )

    func SignParamsHMACSHA256(params map[string]string, secret string) string {
        // 1. 排序 keys
        keys := make([]string, 0, len(params))
        for k := range params {
            keys = append(keys, k)
        }
        sort.Strings(keys)

        // 2. 连接 key+value
        var sb strings.Builder
        for _, k := range keys {
            sb.WriteString(k)
            sb.WriteString(params[k])
        }
        message := []byte(sb.String())

        // 3. HMAC-SHA256
        mac := hmac.New(sha256.New, []byte(secret))
        mac.Write(message)
        sig := mac.Sum(nil)

        // 4. 输出 hex 大写(或按接口约定)
        return strings.ToUpper(hex.EncodeToString(sig))
    }
    

注意:如果你之前的协议是 sha1(appSecret + concatenation + appSecret),改用 HMAC 会生成不同结果------必须客户端/服务端同一套约定。

3 Go 演示输出(样例并给出结果)

下面是两组示例(我在分析里验证过输出)。示例输出(全部为大写 hex):

ini 复制代码
	key = "secretkey",message = "The quick brown fox jumps over the lazy dog"
    

→ HMAC-SHA256(HEX 大写):

markdown 复制代码
	033D11A367048B3748B5FF62776B23263681FA30B4AB6B188BB249080044BCBF

message = (把字段拼接成的字符串,例如之前的推送拼接结果)

→ HMAC-SHA256(HEX 大写):

markdown 复制代码
	FA591B27098AEDAB0B019DECB0D3704903FD81B2B502BD5EA2A38DCBAD7EDFEA

(提示:实际签名需保证字符编码一致(UTF-8)、参数排序规则完全一致、以及是否包含 appKey/timestamp 等都必须和服务端一致。)

  • 与"对称算法"(如 AES)的主要不同点(对比表)

    css 复制代码
    特性		HMAC-SHA256(消息认证码)								对称加密(例如 AES)
    目的		完整性 & 认证:确保消息未被篡改并且来自持有密钥的一方	保密性:确保消息内容不可被未授权方读取
    可逆性		不可逆(MAC) --- 输出固定长度的标识,不能从 MAC 恢复消息或密钥	可逆(解密) --- 解密能恢复原始明文(需要密钥/IV)
    输入 / 输出	输入任意长度消息 → 输出固定长度 MAC(32 字节 for SHA-256)	输入明文 → 输出密文(长度≈明文长度 + padding/IV)
    使用密钥		使用共享密钥(对称),用于计算 MAC(不可用于"解密")		使用共享密钥进行加密/解密
    防篡改		是(用于检测篡改)									默认不保证完整性(通常需要 AEAD 模式如 AES-GCM 才同时保证机密性和完整性)
    典型用途		API 签名、消息认证、token 完整性			存储加密、传输加密(如果用 TLS、或 AES-GCM 作为 AEAD)
    计算成本		一次或两次哈希运算(很快)			块密码运算 + 可能的模式开销(现代 CPU 有 AES 指令加速)

4 小结

HMAC 用来证明消息是完整且来自密钥持有方;对称加密用来隐藏消息内容。两者通常结合使用(例如:先加密再用 HMAC 签名,或使用 AEAD 模式同时提供两者)。

(在 API 场景)使用 crypto/hmac + sha256(或更强的 sha512)进行消息签名。

签名时用稳定的"规范化"流程:统一字符编码(UTF-8)、参数名大小写、排序规则、空值处理(忽略/当空串)等。

用 hmac.Equal 做常量时间比较,避免时序泄露。

加入 timestamp / nonce / replay window(如 ±5 分钟)防止重放攻击。

建议密钥长度至少 256 位(32 字节),并定期轮换。

如果既要保密又要认证,优先使用 AEAD(例如 AES-GCM 或使用 TLS),或"先加密后签名"且管理好 IV/nonce。

相关推荐
bobz9651 分钟前
小而精的 HRM 模型
后端
crossoverJie30 分钟前
在多语言的分布式系统中如何传递 Trace 信息
分布式·后端·开源
用户8485081469036 分钟前
SurrealDB 快速上手教程
数据库·后端
数据智能老司机40 分钟前
图算法趣味学——图遍历
数据结构·算法·云计算
范特西_1 小时前
交错字符串-二维dp
算法·动态规划
用户6147493427741 小时前
JeecgBoot 项目理解与使用心得
后端
是阿建吖!1 小时前
【递归、搜索与回溯算法】穷举、暴搜、深搜、回溯、剪枝
算法·bfs·剪枝
ZIQ1 小时前
单机线程池任务防丢设计与实现思路
后端
MaxHua1 小时前
我用 Java 飞算 AI 快速开发了一个音频转文字工具
后端
欧阳码农1 小时前
langgraph开发Deep Research智能体-项目搭建
前端·后端·langchain