Как сделать подпись Base64 HmacSHA256 байтов полезной нагрузки в JavaScript эквивалентной Java? - PullRequest
0 голосов
/ 06 июля 2019

В Java для создания подписи некоторых данных мы используем экземпляр Mac, который позволяет подписывать любой байтовый массив. Как сделать функцию в JavaScript, которая выдает одну и ту же сигнатуру для одного и того же байтового массива?

Пример реализации Java (метод sign подписывает message с HmacSHA256 и затем преобразует signature в строку base64, безопасную для URL):

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 строка подписи. Я пытаюсь создать эквивалент метода sign в JavaScript, чтобы получить ту же сигнатуру.

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.

Ответы [ 2 ]

0 голосов
/ 06 июля 2019

Решение оказалось не сложным. Перед использованием 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(/\=+$/, '');
}
0 голосов
/ 06 июля 2019

Base64 и HmacSHA256 должны быть включены в CryptoJS после установки.Попробуйте этот подход:

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