算法HMAC的使用步骤
【摘要】 1 简介本文详细分析HMAC通过密码和订单数据生成签名的步骤,并展示使用go实现一个例子展示HMAC如何计算和校验的 2 HMAC(Hash-based Message Authentication Code)概述HMAC 是基于哈希算法的一种消息认证码,它通过一个密钥和一个消息(数据)来生成一个签名(哈希值)。该签名是消息内容的“指纹”,可以确保消息的完整性和身份验证。只有知道密钥的双方...
1 简介
本文详细分析HMAC通过密码和订单数据生成签名的步骤,并展示使用go实现一个例子展示HMAC如何计算和校验的
2 HMAC(Hash-based Message Authentication Code)概述
HMAC 是基于哈希算法的一种消息认证码,它通过一个密钥和一个消息(数据)来生成一个签名(哈希值)。该签名是消息内容的“指纹”,可以确保消息的完整性和身份验证。只有知道密钥的双方才能计算和验证签名。
HMAC的基本计算步骤如下:
使用一个密钥和消息数据结合起来。
通过哈希算法(如 SHA-256)计算一个哈希值。
得到的哈希值就是HMAC签名。
接收方用相同的密钥对消息重新计算HMAC签名,并与发送方提供的签名进行对比,若匹配则验证通过。
3 HMAC 生成签名的步骤
准备数据:消息和密钥。
生成密钥的内外填充(Inner and Outer padding):HMAC算法会使用特定的填充方式,将密钥填充成一个固定长度的值,以适应哈希算法。
计算HMAC:首先计算内层哈希,然后计算外层哈希,最终得到HMAC签名。
HMAC 计算流程:
对消息 message 和密钥 key 进行组合。
使用 SHA-256 等哈希算法生成消息的哈希值。
计算内外两次哈希的结果,生成最终的签名。
4 实现 HMAC 签名计算和验证
下面是一个使用 Go 语言实现的例子,展示如何生成和验证 HMAC 签名。
代码实现
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"log"
)
// 生成 HMAC 签名
func generateHMACSignature(message, secret string) (string, error) {
// 创建一个 HMAC 对象,使用 SHA-256 哈希算法和 secret 密钥
mac := hmac.New(sha256.New, []byte(secret))
// 写入消息内容
_, err := mac.Write([]byte(message))
if err != nil {
return "", err
}
// 计算哈希并将其编码为 Base64 字符串
signature := base64.StdEncoding.EncodeToString(mac.Sum(nil))
return signature, nil
}
// 验证 HMAC 签名
func verifyHMACSignature(message, signature, secret string) bool {
// 使用相同的密钥生成签名
expectedSignature, err := generateHMACSignature(message, secret)
if err != nil {
log.Println("Error generating signature:", err)
return false
}
// 将生成的签名与传入的签名进行比较
return hmac.Equal([]byte(expectedSignature), []byte(signature))
}
func main() {
// 示例消息和密钥
message := "OrderID=12345&Amount=199.99&CustomerID=67890"
secret := "supersecretkey"
// 生成 HMAC 签名
signature, err := generateHMACSignature(message, secret)
if err != nil {
log.Fatalf("Error generating HMAC signature: %v", err)
}
// 打印生成的签名
fmt.Println("Generated HMAC Signature:", signature)
// 验证 HMAC 签名
valid := verifyHMACSignature(message, signature, secret)
if valid {
fmt.Println("HMAC Signature is valid!")
} else {
fmt.Println("HMAC Signature is invalid!")
}
// 模拟一个错误的签名
invalidSignature := "invalid_signature"
invalid := verifyHMACSignature(message, invalidSignature, secret)
if invalid {
fmt.Println("Invalid signature was accepted, this should not happen!")
} else {
fmt.Println("Correctly rejected invalid signature.")
}
}
代码解析
- 生成HMAC签名(generateHMACSignature 函数)
输入:消息 (message) 和密钥 (secret)。
创建 HMAC 对象:使用 Go 内置的 hmac.New 函数与指定的哈希算法(这里使用 SHA-256)以及密钥来创建一个 HMAC 对象。
写入消息:使用 mac.Write 方法将消息写入 HMAC 对象。
计算 HMAC 签名:使用 mac.Sum(nil) 计算最终的 HMAC 签名并返回。
返回 Base64 编码:HMAC 签名是一个二进制数据,我们将其编码为 Base64 格式,以便于传输或存储。
-
验证HMAC签名(verifyHMACSignature 函数)
输入:消息 (message)、签名 (signature) 和密钥 (secret)。
重新生成签名:使用相同的消息和密钥重新计算 HMAC 签名。
比较签名:将生成的签名与接收到的签名进行比较,若一致则验证通过,返回 true,否则返回 false。 -
示例输出
生成一个签名并打印出来:
Generated HMAC Signature: cXkdVxGeK9S+PjV9phkT+7eb9Gg2RlR3zKX4BvIHqys=
验证签名是否有效:
HMAC Signature is valid!
模拟传入错误签名并验证:
Correctly rejected invalid signature.
HMAC如何保障不可抵赖性
密钥绑定签名:
HMAC签名使用了密钥(用户的密码或共享密钥)和消息(订单数据)进行计算。签名和数据是紧密绑定的,无法单独伪造签名而不改变数据,也无法篡改数据而不使签名失效。
用户身份验证:
因为签名的生成和验证依赖于一个私密的密钥,只有持有正确密钥的用户(或系统)才能计算正确的签名,因此系统能够确认是该用户(或系统)执行了操作,从而防止了用户否认的行为。
HMAC如何避免重放攻击
时间戳或唯一标识符:
为了避免重放攻击,HMAC通常会与时间戳或唯一标识符(如订单ID)一起使用。这使得每次请求都有一个唯一的签名,即使是相同的数据,由于时间戳的不同,每次生成的签名也不同。
验证时间有效性:
服务器可以根据时间戳判断请求是否在有效时间窗口内(例如5分钟)。如果时间戳过旧,则拒绝该请求,防止攻击者重放旧请求。
5 总结
HMAC通过结合消息内容和密钥生成一个唯一的签名,使得只有持有正确密钥的用户才能生成有效签名,从而保证了消息的完整性和不可抵赖性。
同时,通过结合时间戳和签名,HMAC可以防止重放攻击,因为每个签名都会与时间或唯一标识符绑定,避免重复使用相同的签名。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)