JS SubtleCrypto RSA Шифрование и дешифрование
Итак, я пытаюсь реализовать некоторые методы для шифрования, а затем дешифрования некоторых данных. У меня нет опыта в этом, и я пытался следить за некоторыми сообщениями в Интернете о том, как это сделать.
Когда я передаю зашифрованное «привет» в функцию дешифрования, я получаю следующее:
let a = importPublicKeyAndEncrypt('hello')
CryptoKey {type: "public", extractable: true, algorithm: {…}, usages: Array(1)} W29iamVjdCBBcnJheUJ1ZmZlcl0=
importPrivateKeyAndDecrypt(a)
Promise {<pending>}
DOMException: Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.
at importPrivateKeyAndDecrypt (<anonymous>:26:60)
Функция дешифрования работает правильно, когда я использую зашифрованные сообщения из одного из сообщений, которые я видел для PKCS#8, но не когда я генерирую свои собственные ключи.
Вот код Что я делаю не так?
// PEM encoded X.509 key
const publicKey = `
-----BEGIN PUBLIC KEY-----
<removed for space>
-----END PUBLIC KEY-----`;
// PEM encoded PKCS#8 key
const privateKey = `
-----BEGIN PRIVATE KEY-----
<removed for space>
-----END PRIVATE KEY-----`;
async function importPublicKeyAndEncrypt(str) {
try {
const pub = await importPublicKey(publicKey);
console.log(pub);
const encrypted = await encryptRSA(pub, new TextEncoder().encode(str));
const encryptedBase64 = window.btoa(ab2str(encrypted));
console.log(encryptedBase64.replace(/(.{64})/g, '$1\n'));
} catch (error) {
console.log(error);
}
}
async function importPrivateKeyAndDecrypt(str) {
try {
const priv = await importPrivateKey(privateKey);
const decrypted = await decryptRSA(priv, str2ab(window.atob(str)));
console.log(decrypted);
} catch (error) {
console.log(error);
}
}
async function importPublicKey(spkiPem) {
return await window.crypto.subtle.importKey(
'spki',
getSpkiDer(spkiPem),
{
name: 'RSA-OAEP',
hash: 'SHA-256',
},
true,
['encrypt']
);
}
async function importPrivateKey(pkcs8Pem) {
return await window.crypto.subtle.importKey(
'pkcs8',
getPkcs8DerDecode(pkcs8Pem),
{
name: 'RSA-OAEP',
hash: 'SHA-256',
},
true,
['decrypt']
);
}
async function encryptRSA(key, plaintext) {
let encrypted = await window.crypto.subtle.encrypt(
{
name: 'RSA-OAEP',
},
key,
plaintext
);
return encrypted;
}
async function decryptRSA(key, ciphertext) {
let decrypted = await window.crypto.subtle.decrypt(
{
name: 'RSA-OAEP',
},
key,
ciphertext
);
return new TextDecoder().decode(decrypted);
}
function getSpkiDer(spkiPem) {
const pemHeader = '-----BEGIN PUBLIC KEY-----';
const pemFooter = '-----END PUBLIC KEY-----';
var pemContents = spkiPem.substring(
pemHeader.length,
spkiPem.length - pemFooter.length
);
var binaryDerString = window.atob(pemContents);
return str2ab(binaryDerString);
}
function getPkcs8DerDecode(pkcs8Pem) {
const pemHeader = '-----BEGIN PRIVATE KEY-----';
const pemFooter = '-----END PRIVATE KEY-----';
var pemContents = pkcs8Pem.substring(
pemHeader.length,
pkcs8Pem.length - pemFooter.length
);
var binaryDerString = window.atob(pemContents);
return str2ab(binaryDerString);
}
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;
}
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint8Array(buf));
}
2 ответа
Есть только два мелких недостатка.
Во-первых,
return
операторы отсутствуют внутри и внутри (хотя последнее не обязательно для текущего фрагмента кода).
Также необходимо дождаться обещания
importPublicKeyAndEncrypt()
перед
importPrivateKeyAndDecrypt()
можно назвать.
С этими исправлениями код работает:
Я использую jsencrypt
Сторона клиента:
const publicKey = `-----BEGIN PUBLIC KEY-----
keydatakeydata
-----END PUBLIC KEY-----`;
export function encrypt(text) {
let encrypt = new JSEncrypt();
encrypt.setPublicKey(publicKey);
let encrypted = encrypt.encrypt(text);
return encrypted.toString();
}
NodeJs
function decryptString(ciphertext) {
const privateKey = fs.readFileSync('./rsa_512_priv.pem').toString();
const decrypted = crypto.privateDecrypt({
key: privateKey,
padding: crypto.constants.RSA_PKCS1_PADDING
}, Buffer.from(ciphertext, 'base64'));
return decrypted.toString("utf8");
}
ключи были сгенерированы сopenssl genrsa -out rsa_1024_priv.pem 1024
openssl rsa -pubout -in rsa_1024_priv.pem -out rsa_1024_pub.pem