You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 11:54:32