1. HMAC-SHA1 是什么?
HMAC(Hash-based Message Authentication Code,基于哈希的消息认证码)是一种消息认证算法。它结合了哈希函数(如 SHA1)和密钥,用于验证消息的完整性和真实性。
HMAC-SHA1 算法原理、流程及安全性分析,提供 Java 和 Python 代码实现。涵盖密钥处理、哈希计算步骤、API 签名应用及重放攻击防御建议。指出 SHA1 碰撞风险,推荐新系统使用 HMAC-SHA256。

HMAC(Hash-based Message Authentication Code,基于哈希的消息认证码)是一种消息认证算法。它结合了哈希函数(如 SHA1)和密钥,用于验证消息的完整性和真实性。
HMAC-SHA1 就是以 SHA1 为哈希函数的 HMAC 算法。
HMAC 的核心思想是:
用一个密钥和哈希函数,对消息进行两次哈希,得到一个消息认证码。
具体公式如下:
HMAC(K, M) = H((K' ⊕ opad) || H((K' ⊕ ipad) || M))
K:密钥M:消息H:哈希函数(这里是 SHA1)K':密钥 K,如果长度不足 block size(SHA1 的 block size 为 64 字节),则补零;如果超出则先哈希再补零opad:外部填充字节(0x5c 重复 64 次)ipad:内部填充字节(0x36 重复 64 次)⊕:按位异或||:拼接详细步骤:
Java 标准库 javax.crypto.Mac 和 javax.crypto.spec.SecretKeySpec 就可以实现 HMAC-SHA1。
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class HmacSHA1Util {
/**
* 生成 HMAC-SHA1 签名
* @param key 密钥(字节数组)
* @param message 消息内容(字节数组)
* @return 签名结果(字节数组)
* @throws Exception
*/
public static byte[] hmacSHA1(byte[] key, byte[] message) throws Exception {
SecretKeySpec signingKey = new SecretKeySpec(key, "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(signingKey);
return mac.doFinal(message);
}
/**
* 生成 HMAC-SHA1 签名,并返回 Base64 编码
* @param key 密钥
* @param message 消息内容
* @return 签名结果(Base64 字符串)
* @throws Exception
*/
public static String hmacSHA1Base64(String key, String message) throws Exception {
byte[] hmac = hmacSHA1(key.getBytes("UTF-8"), message.getBytes("UTF-8"));
return Base64.getEncoder().encodeToString(hmac);
}
/**
* 验证签名
*/
public static boolean verify(String key, String message, String signatureBase64) throws Exception {
String expected = hmacSHA1Base64(key, message);
// 防止时序攻击,建议用 MessageDigest.isEqual
return MessageDigest.isEqual(expected.getBytes("UTF-8"), signatureBase64.getBytes("UTF-8"));
}
// 示例
public static void main(String[] args) throws Exception {
String key = "secret_key";
String message = "hello world";
String signature = hmacSHA1Base64(key, message);
System.out.println("HMAC-SHA1 签名 (Base64): " + signature);
// 验证
boolean valid = verify(key, message, signature);
System.out.println("验证结果:" + valid);
}
}
key.getBytes("UTF-8") 和 message.getBytes("UTF-8") 用于将字符串转为字节数组。MessageDigest.isEqual 避免时序攻击。本示例仅用到 Java 标准库,无需额外依赖。
输出示例:
HMAC-SHA1 签名 (Base64): 2jmj7l5rSw0yVb/vlWAYkK/YBwk=
验证结果:true
Hex.encodeHexString。import hashlib
def hmac_sha1(key: bytes, message: bytes) -> bytes:
block_size = 64 # SHA1 block size
# 1. 密钥处理
if len(key) > block_size:
key = hashlib.sha1(key).digest()
key = key.ljust(block_size, b'\x00')
# 2. ipad 和 opad
ipad = bytes([0x36] * block_size)
opad = bytes([0x5c] * block_size)
# 3. 第一轮哈希
inner = hashlib.sha1(bytes([a ^ b for a, b in zip(key, ipad)]) + message).digest()
# 4. 第二轮哈希
hmac = hashlib.sha1(bytes([a ^ b for a, b in zip(key, opad)]) + inner).digest()
return hmac
# 示例
key = b'secret_key'
message = b'hello world'
hmac_value = hmac_sha1(key, message)
print(hmac_value.hex())
注意:实际项目中建议直接用 Python 标准库 hmac:
import hmac
import hashlib
key = b'secret_key'
message = b'hello world'
hmac_value = hmac.new(key, message, hashlib.sha1).hexdigest()
print(hmac_value)
| 算法 | 哈希长度 | 安全性 | 性能 |
|---|---|---|---|
| HMAC-MD5 | 128 位 | 较低 | 快 |
| HMAC-SHA1 | 160 位 | 中等 | 快 |
| HMAC-SHA256 | 256 位 | 高 | 较快 |
| HMAC-SHA512 | 512 位 | 很高 | 较慢 |
| HMAC-SM3 | 256 位 | 高(国密) | 较快 |
建议:
HMAC(key, timestamp + nonce + body),防止重放攻击import hmac
import hashlib
def generate_signature(key, message):
return hmac.new(key, message, hashlib.sha1).hexdigest()
def verify_signature(key, message, signature):
expected = generate_signature(key, message)
return hmac.compare_digest(expected, signature)
# 示例
key = b'supersecret123'
message = b'user_id=1001&amount=500×tamp=1718000000'
signature = generate_signature(key, message)
print('签名:', signature)
# 验证
print('验证结果:', verify_signature(key, message, signature))

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online