Skip to content

Instantly share code, notes, and snippets.

@schmijos
Forked from tgranqvist/README.md
Last active October 21, 2025 11:55
Show Gist options
  • Select an option

  • Save schmijos/9d35022cdf200556ecd4b56e7e27de89 to your computer and use it in GitHub Desktop.

Select an option

Save schmijos/9d35022cdf200556ecd4b56e7e27de89 to your computer and use it in GitHub Desktop.
Web Crypto API and OpenSSL

Web Crypto API and OpenSSL

This is a small demo using the Web Crypto API and OpenSSL to do file encryption with an RSA keypair.

Steps

  1. Generate the keypair
  2. Extract public key
  3. Create webpage
  4. Encrypt in browser
  5. Decrypt in command line

Key generation

# openssl genrsa -out key.pem 2048

Extract public key

 openssl rsa -in key.pem -pubout -out public.pem

Create webpage

  • Place the source from index.html next to public.pem from the previous step
  • Serve it somehow

Encrypt in webpage

  • Visit the file you are serving from the previous step
  • Type a message in the text box, click encrypt
  • Download the file by clicking the link

Decrypt in console

openssl pkeyutl -decrypt -inkey key.pem -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -in .\message.enc
<!doctype HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Web Crypto API playground</title>
</head>
<body>
<form>
<label>
Message to encrypt: <input id="message" type="text" size="35" required>
</label>
<button id="encrypt" type="button">Encrypt</button>
</form>
<a id="link" href="#">Download encrypted file</a>
</body>
<script>
const base64ToArrayBuffer = (base64) => {
return Uint8Array.from(window.atob(base64), c => c.charCodeAt(0));
};
const importRsaKey = (pem) => {
const pemHeader = "-----BEGIN PUBLIC KEY-----";
const pemFooter = "-----END PUBLIC KEY-----";
const pemContents = pem.replace(pemHeader, "").replace(pemFooter, "").replace(/\s+/g, "");
const binaryDer = base64ToArrayBuffer(pemContents);
return window.crypto.subtle.importKey(
"spki",
binaryDer,
{
name: "RSA-OAEP",
hash: "SHA-256"
},
true,
["encrypt"]
);
}
const encrypt = async (event) => {
event.preventDefault();
const keyData = await fetch("public.pem")
.then((response) => response.text());
const key = await importRsaKey(keyData);
const message = document.getElementById("message").value;
const encrypted = await crypto.subtle.encrypt(
{name: "RSA-OAEP"},
key,
new TextEncoder().encode(message)
);
const fileData = new Blob([new Uint8Array(encrypted)], {type: 'application/download'});
const fileUrl = window.URL.createObjectURL(fileData);
document.getElementById("link").href = fileUrl;
document.getElementById("link").download = "message.enc";
};
document.getElementById("encrypt").addEventListener("click", encrypt);
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment