Skip to content
Blog

JavaScript Cryptography using RSA-OAEP

Learn how to implement secure message encryption in JavaScript using the Web Cryptography API RSA-OAEP algorithm. This guide covers key generation, encryption, decryption, and validation processes for robust data protection.

Published

In today’s digital landscape, ensuring secure communication is more critical than ever. This article explores how to implement the RSA-OAEP algorithm using the Web Cryptography API in JavaScript to safeguard data transmission.

1. Generating a Key Pair

The first step in establishing secure communication is generating a key pair. The generateKeyPair function utilizes the RSA-OAEP algorithm with a modulus length of 1024 bits and employs SHA-256 for hashing. Both public and private keys are marked as extractable, enabling their export for future use. The keys are then exported in SPKI (for the public key) and PKCS8 (for the private key) formats before being returned .

async function generateKeyPair() {
  const keyPair = await crypto.subtle.generateKey(
    {
      name: "RSA-OAEP",
      modulusLength: 1024,
      publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
      hash: "SHA-256",
    },
    true,
    ["encrypt", "decrypt"],
  );

  const publicKeyJwk = await crypto.subtle.exportKey("spki", keyPair.publicKey);
  const privateKeyJwk = await crypto.subtle.exportKey(
    "pkcs8",
    keyPair.privateKey,
  );
  return { publicKeyJwk, privateKeyJwk };
}

2. Encrypting a Message

To securely transmit messages, we employ the encrypt function, which takes a public key and a message string. It imports the public key and proceeds to encrypt the message using the RSA-OAEP algorithm .

async function encrypt(publicKeyJwk, message) {
  const importedPublicKey = await crypto.subtle.importKey(
    "spki",
    publicKeyJwk,
    {
      name: "RSA-OAEP",
      hash: "SHA-256",
    },
    true,
    ["encrypt"],
  );

  const encrypted = await crypto.subtle.encrypt(
    { name: "RSA-OAEP" },
    importedPublicKey,
    new TextEncoder().encode(message),
  );

  return encrypted;
}

3. Decrypting an Encrypted Message

For the recipient to read the encrypted message, the decrypt function comes into play. It accepts a private key and an encrypted message, importing the private key before decrypting the message with RSA-OAEP .

async function decrypt(privateKeyJwk, message) {
  const importedPrivateKey = await crypto.subtle.importKey(
    "pkcs8",
    privateKeyJwk,
    {
      name: "RSA-OAEP",
      hash: "SHA-256",
    },
    true,
    ["decrypt"],
  );

  const decrypted = await crypto.subtle.decrypt(
    { name: "RSA-OAEP" },
    importedPrivateKey,
    message,
  );

  return decrypted;
}

4. Running the Code

The example usage demonstrates the process by generating a key pair, encrypting a message, and subsequently decrypting it:

(async () => {
  const { publicKeyJwk, privateKeyJwk } = await generateKeyPair();
  console.log("generateKeyPair: ", publicKeyJwk, privateKeyJwk);

  const encrypted = await encrypt(publicKeyJwk, "hello");
  console.log("encrypted: ", encrypted);

  const decrypted = await decrypt(privateKeyJwk, encrypted);
  console.log("decrypted: ", decrypted, new TextDecoder().decode(decrypted));
})();

Important Considerations

Conclusion

By adopting secure communication techniques like those discussed here, you can significantly enhance the confidentiality and integrity of your data, particularly when handling sensitive information. For further exploration, consider understanding and implementing ECDSA in JavaScript cryptography .

Further Reading

JavaScript encryptionWeb Cryptography APIRSA-OAEPkey generationmessage encryptiondecryptionexpirationdata protectionsecurity