0Pricing
Java Academy · 课时

用于消息完整性的 HMAC-SHA256

创建并验证 HMAC-SHA256 签名,确保 API 负载的完整性

用于消息完整性的 HMAC-SHA256 是 CoddyKit 上的免费 Java Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。

什么是 HMAC?

HMAC(基于哈希的消息认证码)将密码学哈希函数与秘密密钥结合,生成 MAC。它既能证明数据未被篡改,也能证明发送方知道秘密密钥,即 AND。

HMAC 与普通哈希

任何人都可以计算普通的 SHA-256 哈希。HMAC 需要秘密密钥,只有知道该密钥的参与方才能创建或验证有效的 HMAC。普通哈希可以提供完整性,但不能提供认证。

在 Java 中计算 HMAC-SHA256

请使用 Mac.getInstance("HmacSHA256"),使用 SecretKeySpec 初始化,然后调用 doFinal(data)。

byte[] keyBytes = "my-secret-key".getBytes(StandardCharsets.UTF_8);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(keySpec);
byte[] hmac = mac.doFinal("payload data".getBytes(StandardCharsets.UTF_8));
String hmacHex = HexFormat.of().formatHex(hmac);
System.out.println(hmacHex); // 64-char hex

验证 HMAC

使用共享密钥对接收到的数据重新计算 HMAC。请使用常量时间比较(MessageDigest.isEqual)来防止时序攻击。

byte[] expectedHmac = computeHmac(key, receivedPayload);
byte[] actualHmac    = HexFormat.of().parseHex(receivedHmacHex);
boolean valid = MessageDigest.isEqual(expectedHmac, actualHmac);
if (!valid) throw new SecurityException("HMAC verification failed — data tampered!");

生成安全密钥

HMAC 密钥应由随机字节组成,而不是密码。请使用 KeyGenerator 或 SecureRandom 生成 256 位密钥。

KeyGenerator kg = KeyGenerator.getInstance("HmacSHA256");
kg.init(256);
SecretKey key = kg.generateKey();
String b64Key = Base64.getEncoder().encodeToString(key.getEncoded());

用于 API 请求签名的 HMAC

对 HTTP 方法、路径、时间戳和请求正文计算 HMAC。将 HMAC 放入 X-Signature 标头。服务器会重新计算并进行比较,以验证请求未被篡改。

String payload = method + "\n" + path + "\n" + timestamp + "\n" + body;
byte[] hmac = computeHmac(apiSecretKey, payload);
request.header("X-Signature", "hmac-sha256=" + HexFormat.of().formatHex(hmac));
request.header("X-Timestamp", timestamp);

防止重放攻击

攻击者可以重放有效的已签名请求。请在已签名的 payload 中加入时间戳,并拒绝早于几分钟的请求。

long timestamp = Long.parseLong(request.getHeader("X-Timestamp"));
if (Math.abs(System.currentTimeMillis() / 1000 - timestamp) > 300) {
    throw new SecurityException("Request too old — possible replay attack");
}

用于 Webhook 验证的 HMAC

GitHub、Stripe 和许多服务都会使用 HMAC 对 Webhook 进行签名。请验证 X-Hub-Signature-256 标头,确保 Webhook 来自该服务且未被修改。

// GitHub webhook verification:
String received = request.getHeader("X-Hub-Signature-256").replace("sha256=","");
byte[] expected = computeHmac(webhookSecret, request.getBody());
boolean valid = MessageDigest.isEqual(expected, HexFormat.of().parseHex(received));

JWT 中的 HMAC

HS256(HMAC-SHA256)是常见的 JWT 签名算法。标头和载荷会使用共享秘密进行签名。签发方和验证方都必须知道该秘密,适合处于同一信任边界内的微服务。

HMAC 密钥轮换

请定期轮换 HMAC 密钥。轮换期间,在短暂的重叠时期内同时接受使用旧密钥和新密钥生成的 HMAC,然后停用旧密钥。

何时使用 HMAC,何时使用数字签名

HMAC:对称方式,双方共享秘密,速度快,适用于内部 API 和 Webhook 验证。数字签名(RSA/ECDSA):非对称方式,只有签名方拥有私钥,任何拥有公钥的人都可以验证,适用于分布式系统中的 JWT。

快速检查

为什么 HMAC 比较必须使用常量时间相等判断?

回顾

HMAC-SHA256 提供经过认证的完整性,能够证明数据来源且数据未被篡改。请使用 Mac.getInstance("HmacSHA256")。始终使用常量时间比较。加入时间戳以防止重放攻击。HMAC 可用于 API 签名、Webhook 验证和 HS256 JWT。

常见问题解答

「用于消息完整性的 HMAC-SHA256」课时是免费的吗?

是的 — 「用于消息完整性的 HMAC-SHA256」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。

「用于消息完整性的 HMAC-SHA256」这节课中我会学到什么?

创建并验证 HMAC-SHA256 签名,确保 API 负载的完整性 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Java Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「用于消息完整性的 HMAC-SHA256」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Java Academy 课中编写并运行代码吗?

能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 使用 MessageDigest 进行加密散列
  2. AES 对称加密
  3. 用于消息完整性的 HMAC-SHA256
  4. JWT:结构、创建与验证
← 返回 Java Academy