Javascript public/private key encryption

Viewed 8179

I'd like to generate a public/private keypair in javascript, and use the public key to encrypt message and the private key to decrypt the message.

I prefer native browser support over external libraries. How can I do this in JavaScript?

Modern browsers implement window.crypto.subtle.generateKey. I can use it to generate ECDSA private/public keys to sign/verify messages, this works. But I cannot find a way how to use it to generate pub/private keys to encrypt/decrypt. If I try the generateKey for the recommended AES-GCM Algorithm, it generates just one cryptoKey, which can be probably used to both encrypt and decrypt. But I prefer to get a keypair (publib/private keys), not just a single key. Any suggestions?

This table lists currently supported methods, but it seems none of the green algorithms is what I need: https://diafygi.github.io/webcrypto-examples/

3 Answers

mdn example

const encode = (e => e.encode.bind(e))(new TextEncoder)

let { publicKey: pub, privateKey: key } = await crypto.subtle.generateKey({ name: 'ECDH', namedCurve: 'P-521' }, true, ['deriveKey']) // generate key pairs

// get server ecdh public key
let jwk = await fetch('/others public key').then(res=>res.json())
let spub = await crypto.subtle.importKey('jwk', jwk, { name: 'ECDH', namedCurve: 'P-521' }, false, [])

// use spub and key derive a ase key
let gcm = crypto.subtle.deriveKey({ name: 'ECDH', namedCurve: 'P-521', public: spub }, key, { name: 'AES-GCM', length: 256 }, true, ["encrypt", "decrypt"])

// now use gcm to encrypt or decrypt
let text = crypto.subtle.encrypt({ name: 'AES', length: 256 }, gcm, encode('hello world'))

// same on the server

Related