Skip to content

Commit 38cce8a

Browse files
committed
[add] Webcrypto example misc/aes_gcm
1 parent 7e65def commit 38cce8a

File tree

3 files changed

+157
-0
lines changed

3 files changed

+157
-0
lines changed

‎README.rst

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,6 +1545,97 @@ example.js:
15451545
curl http://localhost/read
15461546
200 <empty reply>
15471547
1548+
Webcrypto (AES-GSM) [misc/aes_gsm]
1549+
----------------------------------
1550+
1551+
nginx.conf:
1552+
1553+
.. code-block:: nginx
1554+
1555+
http {
1556+
js_path "/etc/nginx/njs/";
1557+
1558+
js_import main from misc/aes_gsm.js;
1559+
1560+
server {
1561+
listen 80;
1562+
1563+
location /encrypt {
1564+
js_content main.encrypt;
1565+
}
1566+
1567+
location /decrypt {
1568+
js_content main.decrypt;
1569+
}
1570+
}
1571+
}
1572+
1573+
example.js:
1574+
1575+
.. code-block:: js
1576+
1577+
async function encryptUAM(key_in, iv, text) {
1578+
const alg = { name: 'AES-GCM', iv: iv ? Buffer.from(iv, 'hex')
1579+
: crypto.getRandomValues(new Uint8Array(12)) };
1580+
1581+
const sha256 = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(key_in));
1582+
const key = await crypto.subtle.importKey('raw', sha256, alg, false, ['encrypt']);
1583+
1584+
const cipher = await crypto.subtle.encrypt(alg, key, new TextEncoder().encode(text));
1585+
1586+
return JSON.stringify({
1587+
cipher: btoa(String.fromCharCode.apply(null, new Uint8Array(cipher))),
1588+
iv: btoa(String.fromCharCode.apply(null, new Uint8Array(alg.iv))),
1589+
});
1590+
}
1591+
1592+
async function decryptUAM(key_in, value) {
1593+
value = JSON.parse(value);
1594+
1595+
ngx.log(ngx.ERR, njs.dump(value))
1596+
const alg = { name: 'AES-GCM', iv: Buffer.from(value.iv, 'base64') };
1597+
const sha256 = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(key_in));
1598+
const key = await crypto.subtle.importKey('raw', sha256, alg, false, ['decrypt']);
1599+
1600+
const decrypt = await crypto.subtle.decrypt(alg, key, Buffer.from(value.cipher, 'base64'));
1601+
ngx.log(ngx.ERR, njs.dump(new Uint8Array(decrypt)))
1602+
return new TextDecoder().decode(decrypt);
1603+
}
1604+
1605+
async function encrypt(r) {
1606+
try {
1607+
let encrypted = await encryptUAM(r.args.key, r.args.iv, r.requestText);
1608+
r.return(200, encrypted);
1609+
} catch (e) {
1610+
r.return(500, `encryption failed with ${e.message}`);
1611+
}
1612+
}
1613+
1614+
async function decrypt(r) {
1615+
try {
1616+
let decrypted = await decryptUAM(r.args.key, r.requestText);
1617+
r.return(200, decrypted);
1618+
} catch (e) {
1619+
r.return(500, `decryption failed with ${e.message}`);
1620+
}
1621+
}
1622+
1623+
export default {encrypt, decrypt};
1624+
1625+
.. code-block:: shell
1626+
1627+
curl 'http://localhost/encrypt?key=mySecret&iv=000000000000000000000001' -d TEXT-TO-BE-ENCODED
1628+
{"cipher":"kLKXeb/h1inwXYlP7M504xCD+/1sF4yesCSUc7/OJiyPyw==","iv":"AAAAAAAAAAAAAAAB"}
1629+
1630+
curl 'http://localhost/decrypt?key=mySecret' -d '{"cipher":"kLKXeb/h1inwXYlP7M504xCD+/1sF4yesCSUc7/OJiyPyw==","iv":"AAAAAAAAAAAAAAAA"}'
1631+
decryption failed with EVP_DecryptFinal_ex() failed
1632+
1633+
curl 'http://localhost/decrypt?key=mySecre' -d '{"cipher":"kLKXeb/h1inwXYlP7M504xCD+/1sF4yesCSUc7/OJiyPyw==","iv":"AAAAAAAAAAAAAAAB"}'
1634+
decryption failed with EVP_DecryptFinal_ex() failed
1635+
1636+
curl 'http://localhost/decrypt?key=mySecret' -d '{"cipher":"kLKXeb/h1inwXYlP7M504xCD+/1sF4yesCSUc7/OJiyPyw==","iv":"AAAAAAAAAAAAAAAB"}'
1637+
TEXT-TO-BE-ENCODED
1638+
15481639
Command line interface
15491640
======================
15501641

‎conf/misc/aes_gcm.conf

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
load_module modules/ngx_http_js_module.so;
2+
3+
events { }
4+
5+
http {
6+
js_path "/etc/nginx/njs/";
7+
8+
js_import main from misc/aes_gcm.js;
9+
10+
server {
11+
listen 80;
12+
13+
location /encrypt {
14+
js_content main.encrypt;
15+
}
16+
17+
location /decrypt {
18+
js_content main.decrypt;
19+
}
20+
}
21+
}

‎njs/misc/aes_gcm.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
async function encryptUAM(key_in, iv, text) {
2+
const alg = { name: 'AES-GCM', iv: iv ? Buffer.from(iv, 'hex')
3+
: crypto.getRandomValues(new Uint8Array(12)) };
4+
5+
const sha256 = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(key_in));
6+
const key = await crypto.subtle.importKey('raw', sha256, alg, false, ['encrypt']);
7+
8+
const cipher = await crypto.subtle.encrypt(alg, key, new TextEncoder().encode(text));
9+
10+
return JSON.stringify({
11+
cipher: btoa(String.fromCharCode.apply(null, new Uint8Array(cipher))),
12+
iv: btoa(String.fromCharCode.apply(null, new Uint8Array(alg.iv))),
13+
});
14+
}
15+
16+
async function decryptUAM(key_in, value) {
17+
value = JSON.parse(value);
18+
19+
const alg = { name: 'AES-GCM', iv: Buffer.from(value.iv, 'base64') };
20+
const sha256 = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(key_in));
21+
const key = await crypto.subtle.importKey('raw', sha256, alg, false, ['decrypt']);
22+
23+
const decrypt = await crypto.subtle.decrypt(alg, key, Buffer.from(value.cipher, 'base64'));
24+
return new TextDecoder().decode(decrypt);
25+
}
26+
27+
async function encrypt(r) {
28+
try {
29+
let encrypted = await encryptUAM(r.args.key, r.args.iv, r.requestText);
30+
r.return(200, encrypted);
31+
} catch (e) {
32+
r.return(500, `encryption failed with ${e.message}`);
33+
}
34+
}
35+
36+
async function decrypt(r) {
37+
try {
38+
let decrypted = await decryptUAM(r.args.key, r.requestText);
39+
r.return(200, decrypted);
40+
} catch (e) {
41+
r.return(500, `decryption failed with ${e.message}`);
42+
}
43+
}
44+
45+
export default {encrypt, decrypt};

0 commit comments

Comments
 (0)