CryptoJS.enc.Base64的Java等效实现及HMAC签名代码适配问题
问题描述
尝试将生成API HMAC签名的NodeJS代码迁移至Java,因编码方式错误导致输出结果不一致。
NodeJS 代码
var APIKey = "secret"; var secretByteArray = CryptoJS.enc.Base64.parse(APIKey); var hash = CryptoJS.HmacSHA256("Message", secretByteArray); var hashInBase64 = CryptoJS.enc.Base64.stringify(hash); document.write(hashInBase64);
Java 代码(原错误版本)
try { String secret = "secret"; String message = "Message"; byte[] secretByteArray = Base64.getEncoder().encode(secret.getBytes()); //byte[] secretByteArray = Base64.encodeBase64(secret.getBytes("utf-8"), true); Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); SecretKeySpec secret_key = new SecretKeySpec(secretByteArray, "HmacSHA256"); sha256_HMAC.init(secret_key); String hash = Base64.getEncoder().encodeToString(sha256_HMAC.doFinal(message.getBytes())); System.out.println(hash); } catch (Exception e){ System.out.println("Error"); }
请问Java中应使用什么替代Base64.getEncoder().encode?
解决方案
问题核心是编码方向搞反了:
- NodeJS里
CryptoJS.enc.Base64.parse(APIKey)的作用是将Base64格式的密钥字符串解码为字节数组,作为HMAC的密钥。 - 你当前Java代码用
Base64.getEncoder().encode(secret.getBytes())是把明文密钥字符串编码成Base64字节数组,和JS逻辑完全相反,导致密钥不一致,签名结果自然不同。
正确的替代方式是使用Base64解码方法:Base64.getDecoder().decode(secret.getBytes(StandardCharsets.UTF_8))
修正后的Java代码
import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public class HmacExample { public static void main(String[] args) { try { String secret = "secret"; String message = "Message"; // 对应JS的CryptoJS.enc.Base64.parse:将Base64字符串解码为字节数组 byte[] secretByteArray = Base64.getDecoder().decode(secret.getBytes(StandardCharsets.UTF_8)); Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); SecretKeySpec secret_key = new SecretKeySpec(secretByteArray, "HmacSHA256"); sha256_HMAC.init(secret_key); byte[] hashBytes = sha256_HMAC.doFinal(message.getBytes(StandardCharsets.UTF_8)); String hash = Base64.getEncoder().encodeToString(hashBytes); System.out.println(hash); } catch (NoSuchAlgorithmException | InvalidKeyException e) { System.out.println("Error: " + e.getMessage()); } } }
额外说明
- 明确指定字符集
StandardCharsets.UTF_8,避免不同平台默认编码差异导致的问题。 - 如果使用的是Apache Commons Codec的
Base64类,对应解码方法是Base64.decodeBase64(secret.getBytes(StandardCharsets.UTF_8)),和JDK自带的Base64逻辑一致。
内容的提问来源于stack exchange,提问作者Rohit
相关产品推荐
相关产品推荐

