Import RSA key in JavaScript

To perform any kind of encryption or decryption we have to use the public and private keys.

And thus we need to import the RSA key in JavaScript to use it.

We cannot directly use the keys in a string format rather than we have to convert them to the crypto key to make it work.

To convert the RSA key to a crypto key we can use the window.crypto.subtle.importKey() method.

For any type of key, remove the prefix and suffix of the key and convert it to the base24. Form the array buffer from this base24 string and then convert it to the crypto key.

function importKey(pemEncodedKey) {
  // helper function
  // from https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
  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;
  }

  // main function to load the public key
  // and convert it to crypto key
  // for encryption in browser
  function importRsaKey(pem) {
    // fetch the part of the PEM string between header and footer
    // replace this
    const pemHeader = "-----BEGIN PUBLIC KEY-----";
    const pemFooter = "-----END PUBLIC KEY-----";

    const pemContents = pem.substring(pemHeader.length, pem.length - pemFooter.length);

    // base64 decode the string to get the binary data
    const binaryDerString = window.atob(pemContents);
    
    // convert from a binary string to an ArrayBuffer
    const binaryDer = str2ab(binaryDerString);

    return window.crypto.subtle.importKey(
      "spki",
      binaryDer,
      {
        name: "RSA-OAEP",
        hash: "SHA-256",
      },
      true,
      ["encrypt"]
    );
  }

  return importRsaKey(pemEncodedKey);
}

You can update the pemHeader and pemFooter according to your key type and update the algorithm and hash too.

The importKey method returns a promise.

Input:
const encrypt = async function () {
  try {
    const pemEncodedKey = `-----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArIJnjwOZJsraOXwxkfYsCfxpMJVwYewHA/j3BE3pa1wfp2ptG+xDClt2RsFoDIUalq2/fJDnIsfUG9DEuPkMg47Hn91EfpLgHUlBgnF/jJ08EZhN8yKPQlM2OJhFzc6Aak8a56Jczw4VvT4dHJ414EfnzcPF1pBpfP5OeXQrIQ4rPbbt/umyyTei/MqrtMfUnbJUoWZ2/70Uj2YW5QdoBXPS9k6DwaSIwnjfSIXkfab5tr2xidjjYkOJ9fWbtqFK8d4/yFzsw84rRrZQl35+ymkQf4aVXrm3RDuSxJjGgTvP6R4h2CGGEA7pK/ckmAghio3B43mtKbvDhB8AvFzRSwIDAQAB
    -----END PUBLIC KEY-----`;

    let publicKey = await importKey(pemEncodedKey);
    console.log(publicKey);
  } catch (e) {
    console.error("Error importing key", e);
  }
};

encrypt();

Output:
CryptoKey {type: 'public', extractable: true, algorithm: {…}, usages: Array(1)}