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

Другие вопросы по тегам