如何在 Java 脚本中使字节负载的 Base64 HmacSHA256 签名等同于 Java?

How to make a Base64 HmacSHA256 signature of bytes payload in JavaScript equivalent to Java?

在 Java 中,我们使用 Mac 实例对某些数据进行签名,该实例允许对任何字节数组进行签名。如何在 Java 脚本中创建一个函数,它为相同的字节数组生成相同的签名?

Java 实现的示例(方法 sign 使用 HmacSHA256 标记 message 然后将 signature 转换为 url-safe base64字符串):

public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException {

    byte[] secret = new byte[5];
    secret[0] = 0x1e;
    secret[1] = 0x03;
    secret[2] = 0x01;
    secret[3] = 0x02;
    secret[4] = 0x03;

    byte[] message = new byte[5];
    message[0] = 0x01;
    message[1] = 0x03;
    message[2] = 0x02;
    message[3] = 0x1e;
    message[4] = 0x03;

    System.out.println(sign(secret, message));
}

private static String sign(byte[] secret, byte[] message) throws NoSuchAlgorithmException, InvalidKeyException {

    Mac sha256Hmac = Mac.getInstance("HmacSHA256");
    SecretKeySpec secretKey = new SecretKeySpec(secret, "HmacSHA256");
    sha256Hmac.init(secretKey);

    byte[] signature = sha256Hmac.doFinal(message);
    return Base64.getUrlEncoder().withoutPadding().encodeToString(signature);
}

上面的示例生成 q-l6FioFNkAqMIIxX5rs3AF-VnGIzpApCSSDHmnmjF8 签名字符串。我正在尝试在 Java 脚本中创建与 sign 方法等效的方法以获得相同的签名。

function main(){
    var secret = [5];
    secret[0] = 0x1e;
    secret[1] = 0x03;
    secret[2] = 0x01;
    secret[3] = 0x02;
    secret[4] = 0x03;

    var message = [5];
    message[0] = 0x01;
    message[1] = 0x03;
    message[2] = 0x02;
    message[3] = 0x1e;
    message[4] = 0x03;

    console.log(sign(secret, message));
}

function sign(secret, message){

    // ?

}

我找不到用 CryptoJS 对字节进行签名的方法。

Base64 和 HmacSHA256 应该在安装后包含在 CryptoJS 中。试试这个方法:

function sign(secret, message){
const hash = CryptoJS.HmacSHA256(message.join(''), secret.join('')); 
const hashInBase64 = CryptoJS.enc.Base64.stringify(hash);
return hashInBase64}

解决方案似乎并不复杂。在使用 CryptoJS 之前,我们必须正确地将字节数组转换为字符串。返回 base64 字符串后,我们应该将其转义为 url 友好字符串。

function sign(secret, message){

    var secretString = String.fromCharCode.apply(String, secret);
    var messageString = String.fromCharCode.apply(String, message);

    var hash = CryptoJS.HmacSHA256(messageString, secretString);
    return CryptoJS.enc.Base64.stringify(hash).replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/, '');
}