# 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()`.

```javascript
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()`.

```javascript
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.

```javascript
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).

```javascript
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]]