Skip to content

Commit 98d2da2

Browse files
Merge pull request mdn#34 from wbamberg/add-webcrypto-encrypt-decrypt
Add examples for encrypt/decrypt
2 parents 066c671 + 1f0a368 commit 98d2da2

File tree

12 files changed

+604
-9
lines changed

12 files changed

+604
-9
lines changed

web-crypto/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33
Examples of how to use the [Web Crypto API](https://developer.mozilla.org/docs/Web/API/Web_Crypto_API).
44

55
* [sign/verify](sign-verify/index.html): examples showing how to use the [`SubtleCrypto.sign()`](https://developer.mozilla.org/docs/Web/API/SubtleCrypto/sign) and [`SubtleCrypto.verify()`](https://developer.mozilla.org/docs/Web/API/SubtleCrypto/verify) APIs.
6+
7+
* [encrypt/decrypt](encrypt-decrypt/index.html): examples showing how to use the [`SubtleCrypto.encrypt()`](https://developer.mozilla.org/docs/Web/API/SubtleCrypto/encrypt) and [`SubtleCrypto.decrypt()`](https://developer.mozilla.org/docs/Web/API/SubtleCrypto/decrypt) APIs.

web-crypto/encrypt-decrypt/aes-cbc.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
(() => {
2+
3+
/*
4+
Store the calculated ciphertext and IV here, so we can decrypt the message later.
5+
*/
6+
let ciphertext;
7+
let iv;
8+
9+
/*
10+
Fetch the contents of the "message" textbox, and encode it
11+
in a form we can use for the encrypt operation.
12+
*/
13+
function getMessageEncoding() {
14+
const messageBox = document.querySelector("#aes-cbc-message");
15+
let message = messageBox.value;
16+
let enc = new TextEncoder();
17+
return enc.encode(message);
18+
}
19+
20+
/*
21+
Get the encoded message, encrypt it and display a representation
22+
of the ciphertext in the "Ciphertext" element.
23+
*/
24+
async function encryptMessage(key) {
25+
let encoded = getMessageEncoding();
26+
// The iv must never be reused with a given key.
27+
iv = window.crypto.getRandomValues(new Uint8Array(16));
28+
ciphertext = await window.crypto.subtle.encrypt(
29+
{
30+
name: "AES-CBC",
31+
iv
32+
},
33+
key,
34+
encoded
35+
);
36+
37+
let buffer = new Uint8Array(ciphertext, 0, 5);
38+
const ciphertextValue = document.querySelector(".aes-cbc .ciphertext-value");
39+
ciphertextValue.classList.add('fade-in');
40+
ciphertextValue.addEventListener('animationend', () => {
41+
ciphertextValue.classList.remove('fade-in');
42+
});
43+
ciphertextValue.textContent = `${buffer}...[${ciphertext.byteLength} bytes total]`;
44+
}
45+
46+
/*
47+
Fetch the encoded message and decrypt it.
48+
Write the decrypted message into the "Decrypted" box.
49+
*/
50+
async function decryptMessage(key) {
51+
let encoded = getMessageEncoding();
52+
let decrypted = await window.crypto.subtle.decrypt(
53+
{
54+
name: "AES-CBC",
55+
iv
56+
},
57+
key,
58+
ciphertext
59+
);
60+
61+
let dec = new TextDecoder();
62+
const decryptedValue = document.querySelector(".aes-cbc .decrypted-value");
63+
decryptedValue.classList.add('fade-in');
64+
decryptedValue.addEventListener('animationend', () => {
65+
decryptedValue.classList.remove('fade-in');
66+
});
67+
decryptedValue.textContent = dec.decode(decrypted);
68+
}
69+
70+
/*
71+
Generate an encryption key, then set up event listeners
72+
on the "Encrypt" and "Decrypt" buttons.
73+
*/
74+
window.crypto.subtle.generateKey(
75+
{
76+
name: "AES-CBC",
77+
length: 256
78+
},
79+
true,
80+
["encrypt", "decrypt"]
81+
).then((key) => {
82+
const encryptButton = document.querySelector(".aes-cbc .encrypt-button");
83+
encryptButton.addEventListener("click", () => {
84+
encryptMessage(key);
85+
});
86+
87+
const decryptButton = document.querySelector(".aes-cbc .decrypt-button");
88+
decryptButton.addEventListener("click", () => {
89+
decryptMessage(key);
90+
});
91+
});
92+
93+
})();

web-crypto/encrypt-decrypt/aes-ctr.js

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
(() => {
2+
3+
/*
4+
Store the calculated ciphertext and counter here, so we can decrypt the message later.
5+
*/
6+
let ciphertext;
7+
let counter;
8+
9+
/*
10+
Fetch the contents of the "message" textbox, and encode it
11+
in a form we can use for the encrypt operation.
12+
*/
13+
function getMessageEncoding() {
14+
const messageBox = document.querySelector("#aes-ctr-message");
15+
let message = messageBox.value;
16+
let enc = new TextEncoder();
17+
return enc.encode(message);
18+
}
19+
20+
/*
21+
Get the encoded message, encrypt it and display a representation
22+
of the ciphertext in the "Ciphertext" element.
23+
*/
24+
async function encryptMessage(key) {
25+
let encoded = getMessageEncoding();
26+
// The counter block value must never be reused with a given key.
27+
counter = window.crypto.getRandomValues(new Uint8Array(16)),
28+
ciphertext = await window.crypto.subtle.encrypt(
29+
{
30+
name: "AES-CTR",
31+
counter,
32+
length: 64
33+
},
34+
key,
35+
encoded
36+
);
37+
38+
let buffer = new Uint8Array(ciphertext, 0, 5);
39+
const ciphertextValue = document.querySelector(".aes-ctr .ciphertext-value");
40+
ciphertextValue.classList.add('fade-in');
41+
ciphertextValue.addEventListener('animationend', () => {
42+
ciphertextValue.classList.remove('fade-in');
43+
});
44+
ciphertextValue.textContent = `${buffer}...[${ciphertext.byteLength} bytes total]`;
45+
}
46+
47+
/*
48+
Fetch the encoded message and decrypt it.
49+
Write the decrypted message into the "Decrypted" box.
50+
*/
51+
async function decryptMessage(key) {
52+
let encoded = getMessageEncoding();
53+
let decrypted = await window.crypto.subtle.decrypt(
54+
{
55+
name: "AES-CTR",
56+
counter,
57+
length: 64
58+
},
59+
key,
60+
ciphertext
61+
);
62+
63+
let dec = new TextDecoder();
64+
const decryptedValue = document.querySelector(".aes-ctr .decrypted-value");
65+
decryptedValue.classList.add('fade-in');
66+
decryptedValue.addEventListener('animationend', () => {
67+
decryptedValue.classList.remove('fade-in');
68+
});
69+
decryptedValue.textContent = dec.decode(decrypted);
70+
}
71+
72+
/*
73+
Generate an encryption key, then set up event listeners
74+
on the "Encrypt" and "Decrypt" buttons.
75+
*/
76+
window.crypto.subtle.generateKey(
77+
{
78+
name: "AES-CTR",
79+
length: 256
80+
},
81+
true,
82+
["encrypt", "decrypt"]
83+
).then((key) => {
84+
const encryptButton = document.querySelector(".aes-ctr .encrypt-button");
85+
encryptButton.addEventListener("click", () => {
86+
encryptMessage(key);
87+
});
88+
89+
const decryptButton = document.querySelector(".aes-ctr .decrypt-button");
90+
decryptButton.addEventListener("click", () => {
91+
decryptMessage(key);
92+
});
93+
});
94+
95+
})();

web-crypto/encrypt-decrypt/aes-gcm.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
(() => {
2+
3+
/*
4+
Store the calculated ciphertext and IV here, so we can decrypt the message later.
5+
*/
6+
let ciphertext;
7+
let iv;
8+
9+
/*
10+
Fetch the contents of the "message" textbox, and encode it
11+
in a form we can use for the encrypt operation.
12+
*/
13+
function getMessageEncoding() {
14+
const messageBox = document.querySelector("#aes-gcm-message");
15+
let message = messageBox.value;
16+
let enc = new TextEncoder();
17+
return enc.encode(message);
18+
}
19+
20+
/*
21+
Get the encoded message, encrypt it and display a representation
22+
of the ciphertext in the "Ciphertext" element.
23+
*/
24+
async function encryptMessage(key) {
25+
let encoded = getMessageEncoding();
26+
// The iv must never be reused with a given key.
27+
iv = window.crypto.getRandomValues(new Uint8Array(12));
28+
ciphertext = await window.crypto.subtle.encrypt(
29+
{
30+
name: "AES-GCM",
31+
iv: iv
32+
},
33+
key,
34+
encoded
35+
);
36+
37+
let buffer = new Uint8Array(ciphertext, 0, 5);
38+
const ciphertextValue = document.querySelector(".aes-gcm .ciphertext-value");
39+
ciphertextValue.classList.add('fade-in');
40+
ciphertextValue.addEventListener('animationend', () => {
41+
ciphertextValue.classList.remove('fade-in');
42+
});
43+
ciphertextValue.textContent = `${buffer}...[${ciphertext.byteLength} bytes total]`;
44+
}
45+
46+
/*
47+
Fetch the encoded message and decrypt it.
48+
Write the decrypted message into the "Decrypted" box.
49+
*/
50+
async function decryptMessage(key) {
51+
let encoded = getMessageEncoding();
52+
let decrypted = await window.crypto.subtle.decrypt(
53+
{
54+
name: "AES-GCM",
55+
iv: iv
56+
},
57+
key,
58+
ciphertext
59+
);
60+
61+
let dec = new TextDecoder();
62+
const decryptedValue = document.querySelector(".aes-gcm .decrypted-value");
63+
decryptedValue.classList.add('fade-in');
64+
decryptedValue.addEventListener('animationend', () => {
65+
decryptedValue.classList.remove('fade-in');
66+
});
67+
decryptedValue.textContent = dec.decode(decrypted);
68+
}
69+
70+
/*
71+
Generate an encryption key, then set up event listeners
72+
on the "Encrypt" and "Decrypt" buttons.
73+
*/
74+
window.crypto.subtle.generateKey(
75+
{
76+
name: "AES-GCM",
77+
length: 256,
78+
},
79+
true,
80+
["encrypt", "decrypt"]
81+
).then((key) => {
82+
const encryptButton = document.querySelector(".aes-gcm .encrypt-button");
83+
encryptButton.addEventListener("click", () => {
84+
encryptMessage(key);
85+
});
86+
87+
const decryptButton = document.querySelector(".aes-gcm .decrypt-button");
88+
decryptButton.addEventListener("click", () => {
89+
decryptMessage(key);
90+
});
91+
});
92+
93+
})();

web-crypto/encrypt-decrypt/index.html

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Web Crypto API example</title>
6+
<link rel="stylesheet" href="style.css">
7+
</head>
8+
9+
<body>
10+
<main>
11+
<h1>Web Crypto: encrypt/decrypt</h1>
12+
13+
<section class="description">
14+
<p>This page shows the use of the <code>encrypt()</code> and <code>decrypt()</code> functions of the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API">Web Crypto API</a>. It contains four separate examples, one for each encryption algorithm supported:</p>
15+
<ul>
16+
<li>"RSA-OAEP"</li>
17+
<li>"AES-CTR"</li>
18+
<li>"AES-CBC"</li>
19+
<li>"AES-GCM"</li>
20+
</ul>
21+
<hr/>
22+
<p>Each example has five components:</p>
23+
<ul>
24+
<li>A text box containing a message to encrypt.</li>
25+
<li>A representation of the ciphertext.</li>
26+
<li>A box that will contain the decrypted ciphertext.</li>
27+
<li>An "Encrypt" button: this encrypts the text box contents, displays part of the ciphertext, and stores the complete ciphertext.</li>
28+
<li>A "Decrypt" button: this decrypts the ciphertext and writes the result into the "Decrypted" box.</li>
29+
</ul>
30+
<p>Try it:</p>
31+
<ul>
32+
<li>Press "Encrypt". The ciphertext should appear.</li>
33+
<li>Press "Decrypt". The decrypted text should appear, and match the original message.</li>
34+
<li>Edit the text box contents.</li>
35+
<li>Press "Encrypt" again. A different ciphertext should appear.</li>
36+
<li>Press "Decrypt" again. The new text box contents should appear next to "Decrypted:".</li>
37+
</ul>
38+
</section>
39+
40+
<section class="examples">
41+
<section class="encrypt-decrypt rsa-oaep">
42+
<h2 class="encrypt-decrypt-heading">RSA-OAEP</h2>
43+
<section class="encrypt-decrypt-controls">
44+
<div class="message-control">
45+
<label for="rsa-oaep-message">Enter a message to encrypt:</label>
46+
<input type="text" id="rsa-oaep-message" name="message" size="25"
47+
value="The owl hoots at midnight">
48+
</div>
49+
<div class="ciphertext">Ciphertext:<span class="ciphertext-value"></span></div>
50+
<div class="decrypted">Decrypted:<span class="decrypted-value"></span></div>
51+
<input class="encrypt-button" type="button" value="Encrypt">
52+
<input class="decrypt-button" type="button" value="Decrypt">
53+
</section>
54+
</section>
55+
56+
<section class="encrypt-decrypt aes-ctr">
57+
<h2 class="encrypt-decrypt-heading">AES-CTR</h2>
58+
<section class="encrypt-decrypt-controls">
59+
<div class="message-control">
60+
<label for="aes-ctr-message">Enter a message to encrypt:</label>
61+
<input type="text" id="aes-ctr-message" name="message" size="25"
62+
value="The tiger prowls at dawn">
63+
</div>
64+
<div class="ciphertext">Ciphertext:<span class="ciphertext-value"></span></div>
65+
<div class="decrypted">Decrypted:<span class="decrypted-value"></span></div>
66+
<input class="encrypt-button" type="button" value="Encrypt">
67+
<input class="decrypt-button" type="button" value="Decrypt">
68+
</section>
69+
</section>
70+
71+
<section class="encrypt-decrypt aes-cbc">
72+
<h2 class="encrypt-decrypt-heading">AES-CBC</h2>
73+
<section class="encrypt-decrypt-controls">
74+
<div class="message-control">
75+
<label for="aes-cbc-message">Enter a message to encrypt:</label>
76+
<input type="text" id="aes-cbc-message" name="message" size="25"
77+
value="The eagle flies at twilight">
78+
</div>
79+
<div class="ciphertext">Ciphertext:<span class="ciphertext-value"></span></div>
80+
<div class="decrypted">Decrypted:<span class="decrypted-value"></span></div>
81+
<input class="encrypt-button" type="button" value="Encrypt">
82+
<input class="decrypt-button" type="button" value="Decrypt">
83+
</section>
84+
</section>
85+
86+
<section class="encrypt-decrypt aes-gcm">
87+
<h2 class="encrypt-decrypt-heading">AES-GCM</h2>
88+
<section class="encrypt-decrypt-controls">
89+
<div class="message-control">
90+
<label for="aes-gcm-message">Enter a message to encrypt:</label>
91+
<input type="text" id="aes-gcm-message" name="message" size="25"
92+
value="The bunny hops at teatime">
93+
</div>
94+
<div class="ciphertext">Ciphertext:<span class="ciphertext-value"></span></div>
95+
<div class="decrypted">Decrypted:<span class="decrypted-value"></span></div>
96+
<input class="encrypt-button" type="button" value="Encrypt">
97+
<input class="decrypt-button" type="button" value="Decrypt">
98+
</section>
99+
</section>
100+
101+
</section>
102+
</main>
103+
104+
</body>
105+
<script src="rsa-oaep.js"></script>
106+
<script src="aes-cbc.js"></script>
107+
<script src="aes-ctr.js"></script>
108+
<script src="aes-gcm.js"></script>
109+
</html>

0 commit comments

Comments
 (0)