Asymmetric encryption with the Web Cryptography API

The Web Cryptography API lets us generate RSA and EC keypairs, but these keys don’t support encryption/decryption! The only algorithms supporting encryption and decryption are symmetric (and the obscure-sounding RSA-OAEP). Instead of directly providing asymmetric encryption/decryption, the Web Cryptography API provides the deriveKey method, which lets two communicators derive a shared symmetric secret. This post shows how to derive a shared AES key given two ECDH keys. This code should log true, asserting that Alice’s derived AES key is the same as Bob’s derived AES key:

const aliceKeyPair = await genKeyPair();
const bobKeyPair   = await genKeyPair();
const aliceSecret  = await deriveKey(aliceKeyPair.privateKey, bobKeyPair.publicKey  );
const bobSecret    = await deriveKey(  bobKeyPair.privateKey, aliceKeyPair.publicKey);
console.log((await exportKey(aliceSecret)).k === (await exportKey(bobSecret)).k);

Here’s the accompanying code which calls the crypto.subtle API:

function genKeyPair() {
  return crypto.subtle.generateKey({name:"ECDH", namedCurve: "P-256"}, true, ["deriveKey"]);
function deriveKey(privKey, pubKey) {
  return crypto.subtle.deriveKey(
    {"name": "ECDH", "public": pubKey},
    {name:"AES-CTR", length: 256},
    ["encrypt", "decrypt"]
async function exportKey(k) {
  return JSON.stringify(await crypto.subtle.exportKey("jwk", k));

After Alice and Bob have derived their shared symmetric secret, they can use this to communicate using normal symmetric crypto.

I just released Vidrio, a free app for macOS and Windows to make your screen-sharing awesomely holographic. Vidrio shows your webcam video on your screen, just like a mirror. Then you just share or record your screen with Zoom, QuickTime, or any other app. Vidrio makes your presentations effortlessly engaging, showing your gestures, gazes, and expressions. #1 on Product Hunt. Available for macOS and Windows.

With Vidrio

With generic competitor

More by Jim

Tagged #programming, #crypto, #javascript. All content copyright James Fisher 2017. This post is not associated with my employer. Found an error? Edit this page.