Java生成HMAC的实现代码正误判断及正确实现方案咨询
现有实现存在的问题
你的代码逻辑存在不必要的二次编码问题,会导致输出结果不符合常规HMAC接口的校验要求:
- 错误的编码逻辑:你对HMAC计算得到的原始字节先做了十六进制编码,再把十六进制编码后的字节做Base64编码,属于多余的操作。常规HMAC输出要么直接返回原始字节的Base64编码,要么直接返回原始字节的十六进制字符串,两次编码后的结果无法被正常的校验逻辑识别。
- 冗余代码:你定义的
API_SECRET_CODE常量没有在generateHMAC方法中被使用,如果是打算默认使用该常量作为签名密钥,当前逻辑没有实现对应的功能。 - 写法冗余:
org.apache.commons.codec的HmacUtils已经封装了更简化的工具方法,不需要手动初始化Mac实例、手动处理编码转换。
正确实现方案
场景1:输出HMAC-SHA512原始字节的Base64编码(最常用的接口签名场景)
import org.apache.commons.codec.digest.HmacAlgorithms; import org.apache.commons.codec.digest.HmacUtils; import java.nio.charset.StandardCharsets; public class HMACGenerator { // 如果需要默认密钥可以保留该常量,按需使用 public static final String API_SECRET_CODE = "The quick brown fox jumps over the lazy dog"; public static String generateHMAC(String key, String message) { // 直接调用封装好的hmacSha512方法,返回原始字节后直接做Base64编码 return HmacUtils.hmacSha512Base64(key.getBytes(StandardCharsets.UTF_8), message.getBytes(StandardCharsets.UTF_8)); } // 如果需要使用默认密钥的重载方法,可以补充实现 public static String generateHMACWithDefaultKey(String message) { return generateHMAC(API_SECRET_CODE, message); } }
场景2:输出HMAC-SHA512的十六进制字符串
如果你的对接方要求返回十六进制格式的签名结果,改用以下实现即可:
public static String generateHMACHex(String key, String message) { return HmacUtils.hmacSha512Hex(key.getBytes(StandardCharsets.UTF_8), message.getBytes(StandardCharsets.UTF_8)); }
验证方式
你可以用标准测试向量验证结果正确性:
- 测试密钥:
The quick brown fox jumps over the lazy dog - 测试消息:
test - 标准HMAC-SHA512十六进制结果:
de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d95fa9f34c7a90abe1ff7a57ad4c57804109200b48000d1f261651492125e1a0434ed4e012fdd818a08e561040 - 标准HMAC-SHA512 Base64结果:
3nybhbi3iqa8ino29wqQcBydtNlfqfNMepCr4f96V61MV4BBCSALSAANHyYWUUkhJeGgQ07U4AS/dgYoI5WEECA==
你可以将自己的代码输出和上述结果对比,即可确认正确性。
内容的提问来源于stack exchange,提问作者Ahmed Ramsey
相关产品推荐
相关产品推荐

