#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. Когда я выполняю вышеизложенное, я получаю следующее:
Я не уверен, почему он выглядит неопределенным, но я могу это заметить arrayBuffer
и binaryDer
не имею точно такого же размера. Не знаю, значит ли это что-нибудь, и не знаю, как это исправить, любая помощь будет признательна!
Комментарии:
1. Пожалуйста, опубликуйте полный код, например, каковы определения
arrayBufferToBase64()
иaddNewLines()
?2. Не заметил, что они еще не встали, спасибо!
3. Мне это просто кажется ошибкой в структуре вашего JavaScript. Выведите импортированный открытый ключ
importPublicKey()
вthen(function(result)
блоке передreturn
инструкцией.4. Код становится понятнее с помощью async/await ( синтаксический сахар для обещаний ): jsfiddle.net/omsyLhn3
5. Вывод результата прямо перед тем, как оператор return действительно сработает!! Сейчас я посмотрю на ваш jsfiddle, большое вам спасибо!