Как импортировать ключ (), чтобы получить КриптоОбъект из экспортированного ключа?

#javascript #rsa #webcrypto-api

Вопрос:

Попытка использовать веб-API SubtleCrypto для создания пары открытых/закрытых ключей, затем использовать эту пару ключей для шифрования от пользователя, вводящего открытый ключ, но importKey() продолжает давать результат как неопределенный. Для генерации открытого/закрытого ключа у меня есть следующее:

 window.crypto.subtle.generateKey(
    {
        name: "RSA-OAEP",
        modulusLength: 2048, // can be 1024, 2048 or 4096
        publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
        hash: {name: "SHA-256"} // or SHA-512
    },
    true,
    ["encrypt", "decrypt"]
).then(function(keyPair) {

    console.log(keyPair);

    window.crypto.subtle.exportKey(
        "pkcs8",
        keyPair.privateKey
    ).then(function(exportedPrivateKey) {
        // converting exported private key to PEM format
        var pem = toPem(exportedPrivateKey);
        console.log(pem);
    }).catch(function(err) {
        console.log(err);
    });

    window.crypto.subtle.exportKey(
        "spki",
        keyPair.publicKey
    ).then(function(exportedPublicKey) {
        // converting exported private key to PEM format
        var pem = toPemP(exportedPublicKey);
        console.log(pem);
        let resultingKey = importPublicKey(pem)
        console.log('keyPairPublic: ', keyPair.publicKey)
        console.log('resultingKey: ', resultingKey)

    }).catch(function(err) {
        console.log(err);
    });
});
 

функции toPem() и toPemP() заключаются в следующем:

 function toPem(privateKey) {
    var b64 = addNewLines(arrayBufferToBase64(privateKey));
    var pem = "-----BEGIN PRIVATE KEY-----n"   b64   "-----END PRIVATE KEY-----";
    
    return pem;
}

function toPemP(publicKey) {
    var b64 = addNewLines(arrayBufferToBase64(publicKey));
    var pem = "-----BEGIN PUBLIC KEY-----n"   b64   "-----END PUBLIC KEY-----";
    
    return pem;
}

function arrayBufferToBase64(arrayBuffer) {
    console.log('arrayBuffer', arrayBuffer);
    var byteArray = new Uint8Array(arrayBuffer);
    var byteString = '';
    for(var i=0; i < byteArray.byteLength; i  ) {
        byteString  = String.fromCharCode(byteArray[i]);
    }
    var b64 = window.btoa(byteString);

    return b64;
}

function addNewLines(str) {
    var finalString = '';
    while(str.length > 0) {
        finalString  = str.substring(0, 64)   'n';
        str = str.substring(64);
    }

    return finalString;
}
 

The importKey() function is as follows:

 function importPublicKey(pem) {
    // base64 decode the string to get the binary data
    // fetch the part of the PEM string between header and footer
    const pemHeader = "-----BEGIN PUBLIC KEY-----";
    const pemFooter = "-----END PUBLIC KEY-----";
    let pemContents = pem.substring(pemHeader.length, pem.length - pemFooter.length)
    pemContents = pemContents.replace(/s/g, '');
    console.log('pemContents:', pemContents)
    let binaryDerString = window.atob(pemContents);
    // convert from a binary string to an ArrayBuffer
    const binaryDer = str2ab(binaryDerString);
    console.log('binaryDer', binaryDer)

    window.crypto.subtle.importKey(
        "spki",
        binaryDer,
        {
            name: "RSA-OAEP",
            hash: { name: "SHA-256" }
        },
        true,
        ["encrypt"]
    ).then(function(result) {
        return resu<
    }).catch(function(err) {
        console.log('err: ', err);
    })
}
 

Где str2ab() это выглядит следующим образом:

 function str2ab(str) {
    const buf = new ArrayBuffer(str.length);
    const bufView = new Uint8Array(buf);
    for (let i = 0, strLen = str.length; i < strLen; i  ) {
        bufView[i] = str.charCodeAt(i);
    }
    return buf;
}
 

Все вышеперечисленные функции были взяты из документации SubtleCrypto. Когда я выполняю вышеизложенное, я получаю следующее:

Результаты importKey()

Я не уверен, почему он выглядит неопределенным, но я могу это заметить arrayBuffer и binaryDer не имею точно такого же размера. Не знаю, значит ли это что-нибудь, и не знаю, как это исправить, любая помощь будет признательна!

Комментарии:

1. Пожалуйста, опубликуйте полный код, например, каковы определения arrayBufferToBase64() и addNewLines() ?

2. Не заметил, что они еще не встали, спасибо!

3. Мне это просто кажется ошибкой в структуре вашего JavaScript. Выведите импортированный открытый ключ importPublicKey() в then(function(result) блоке перед return инструкцией.

4. Код становится понятнее с помощью async/await ( синтаксический сахар для обещаний ): jsfiddle.net/omsyLhn3

5. Вывод результата прямо перед тем, как оператор return действительно сработает!! Сейчас я посмотрю на ваш jsfiddle, большое вам спасибо!