Web Crypto API
The Web Crypto API provides a set of low-level cryptographic primitives that are controlled by the script engine. It allows web applications to perform cryptographic operations such as hashing, signature generation and verification, and encryption and decryption.
1. The SubtleCrypto Interface
The core of the API is accessed through the window.crypto.subtle property. All operations are asynchronous and return Promises.
2. Generating Random Numbers
For cryptographic purposes (like generating IVs or salts), you should never use Math.random(). Instead, use crypto.getRandomValues().
const array = new Uint32Array(10);
window.crypto.getRandomValues(array);
console.log("Your lucky numbers:");
for (const num of array) {
console.log(num);
}
3. Hashing (Digesting)
To create a hash (digest) of data, use digest().
async function sha256(message) {
// encode as (utf-8) Uint8Array
const msgBuffer = new TextEncoder().encode(message);
// hash the message
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
// convert ArrayBuffer to Array
const hashArray = Array.from(new Uint8Array(hashBuffer));
// convert bytes to hex string
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
return hashHex;
}
sha256('Hello World').then(digest => console.log(digest));
4. Generating Keys
You can generate symmetric or asymmetric keys.
async function generateKey() {
const key = await window.crypto.subtle.generateKey(
{
name: "AES-GCM",
length: 256
},
true, // extractable
["encrypt", "decrypt"]
);
return key;
}
5. Encryption and Decryption
Example using AES-GCM (Galois/Counter Mode).
async function encryptMessage(key, message) {
const encoded = new TextEncoder().encode(message);
// The IV (Initialization Vector) must be unique for every encryption
const iv = window.crypto.getRandomValues(new Uint8Array(12));
const ciphertext = await window.crypto.subtle.encrypt(
{
name: "AES-GCM",
iv: iv
},
key,
encoded
);
return { ciphertext, iv };
}
async function decryptMessage(key, ciphertext, iv) {
const decrypted = await window.crypto.subtle.decrypt(
{
name: "AES-GCM",
iv: iv
},
key,
ciphertext
);
return new TextDecoder().decode(decrypted);
}
// Usage
(async () => {
const key = await generateKey();
const { ciphertext, iv } = await encryptMessage(key, "Secret Message");
console.log("Encrypted buffer:", ciphertext);
const decrypted = await decryptMessage(key, ciphertext, iv);
console.log("Decrypted:", decrypted);
})();
programming/javascript/vanilla/javascript programming/javascript/vanilla/promises-async-await programming/javascript/vanilla/typed-arrays