在RestFul接口使用Hmac算法

举报
码乐 发表于 2025/08/14 06:33:55 2025/08/14
【摘要】 1 简介HMAC(基于哈希的消息认证码)是一种消息认证码(MAC),通过对要认证的数据和秘密共享密钥执行加密哈希函数来获取。与任何 MAC 一样,它用于数据完整性和身份验证。HMAC(基于哈希的消息认证码)是一种加密技术,它使用哈希函数和密钥来确保数据的完整性和真实性。与基于签名和非对称密码学的方法不同。HMAC 的 公式非常容易理解: HMAC = hashFunc(secret ke...

1 简介

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

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

		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 示例:

    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):

	key = "secretkey",message = "The quick brown fox jumps over the lazy dog"

→ HMAC-SHA256(HEX 大写):

	033D11A367048B3748B5FF62776B23263681FA30B4AB6B188BB249080044BCBF

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

→ HMAC-SHA256(HEX 大写):

	FA591B27098AEDAB0B019DECB0D3704903FD81B2B502BD5EA2A38DCBAD7EDFEA

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

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

    特性		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。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。