# node:crypto

The `node:crypto` module provides the Node.js cryptographic functions: hashing, HMAC signatures, encryption, decryption, and secure random values. In Node.js, the module wraps the OpenSSL hash, HMAC, cipher, decipher, sign, and verify functions. In Azion Runtime, the module is available through Node.js compatibility, so you can use it inside a function to sign requests, verify message integrity, or generate unique identifiers. Its `subtle` export, on the named import and on the default export, is the same object as `globalThis.crypto.subtle`, and the module also exports `webcrypto`.

> **Note**
>
> Under `azion dev`, `timingSafeEqual()` and `generateKeyPairSync()` throw `TypeError: (void 0) is not a function`, and the build warns `Import "timingSafeEqual" will always be undefined because there is no matching export in "internal-env-dev:crypto"`. Both functions work in a deployed function. Locally, `Buffer.isBuffer()` also returns `false` for the buffer that `randomBytes()` returns; deployed, it returns `true`.

---

## Examples

Each example is a complete function that imports from `node:crypto`. The response below each example is the one a deployed function returns. Random values, such as UUIDs and tokens, differ on every request.

### HMAC and UUID generation

This function signs a string with an HMAC key, prints the signature, and responds with a random UUID:

```javascript
/**
 * An example of using the Node.js Crypto API in an Azion Function.
 * Support:
 * - Extended by library `crypto-browserify`
 * - Implemented additional methods:
 *  - randomUUID (named export and default export)
 * @module runtime-apis/nodejs/crypto/main
 * @example
 * // Build and run with the Azion CLI:
 * azion build
 * azion dev
 */
import { createHmac, randomUUID } from "node:crypto";

/**
 * Example of using the Node.js Crypto API
 * @param {*} event
 * @returns
 */
const main = async (event) => {
  const hmac = createHmac("sha256", "a secret");
  hmac.update("Azion Functions");
  const hmacResult = hmac.digest("hex");
  console.log(hmacResult);
  // 86fec9e22ad82998c7007d637f61a5206e2b64ee2a8ac2ed12f1f359e3d14bc6

  const uuid = randomUUID();
  console.log(uuid);
  // 9b942e1e-6ceb-49cd-9d75-e50c7852e950

  return new Response(uuid, { status: 200 });
};

export default main;
```

The function responds with the UUID:

```text
9b942e1e-6ceb-49cd-9d75-e50c7852e950
```

### Hash generation with SHA-256

This function hashes a fixed string to check data integrity, and hashes the request URL to build a deterministic cache key:

```javascript
import { createHash } from "node:crypto";

const main = async (event) => {
  // Create a SHA-256 hash
  const hash = createHash("sha256");
  hash.update("Hello, Azion Runtime!");
  
  const digest = hash.digest("hex");
  console.log("SHA-256 hash:", digest);
  // SHA-256 hash: 6183c5245446e11f9d5dc70b167bb7fb6d8f878576765db2106c18c24eba2970

  // Hash request data for caching keys
  // Note: event.request is available in Functions for Applications
  const requestUrl = event.request?.url || "https://default.example.com";
  const cacheKey = createHash("sha256")
    .update(requestUrl)
    .digest("hex");
  
  console.log("Cache key:", cacheKey);

  return new Response(JSON.stringify({ digest, cacheKey }), {
    headers: { "Content-Type": "application/json" }
  });
};

export default main;
```

The function responds with both hashes. The `digest` value is the same on every request; the `cacheKey` value depends on the request URL, so yours differs:

```json
{"digest":"6183c5245446e11f9d5dc70b167bb7fb6d8f878576765db2106c18c24eba2970","cacheKey":"22d8de40ffcb2a09a030d3798d6821add8941a103b43c8e722d87b7ee59aa821"}
```

### Random bytes generation

This function generates secure random values for a token, a session ID, and a nonce, and sets the nonce in a `Content-Security-Policy` header:

```javascript
import { randomBytes } from "node:crypto";
import { Buffer } from "node:buffer";

const main = async (event) => {
  // Generate 32 random bytes
  // Note: randomBytes returns a Buffer in Azion Runtime
  const bytes = randomBytes(32);
  
  // Ensure compatibility: convert to Buffer if needed
  const buffer = Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes);
  
  const token = buffer.toString("hex");
  console.log("Secure token:", token);

  // Generate a shorter session ID
  const sessionId = randomBytes(16).toString("base64url");
  console.log("Session ID:", sessionId);

  // Generate a nonce for CSP headers
  const nonce = randomBytes(16).toString("base64");

  // Show raw buffer output (common in Node.js)
  console.log("Raw buffer:", bytes);

  return new Response(JSON.stringify({ token, sessionId, nonce }), {
    headers: {
      "Content-Type": "application/json",
      "Content-Security-Policy": `script-src 'nonce-${nonce}'`
    }
  });
};

export default main;
```

The function responds with the three values and sets `Content-Security-Policy` to `script-src 'nonce-<nonce>'`, where `<nonce>` is the `nonce` value of the same response. The values differ on every request:

```json
{"token":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","sessionId":"AAECAwQFBgcICQoLDA0ODw","nonce":"AAECAwQFBgcICQoLDA0ODw=="}
```

### Web Crypto API integration

The `crypto` module also gives access to the Web Crypto API through `crypto.subtle`, which is the same object as `globalThis.crypto.subtle`. This function generates an AES key, exports it, and encrypts a string with it:

```javascript
import crypto from "node:crypto";

const main = async (event) => {
  // Access Web Crypto API
  // Note: crypto.subtle === globalThis.crypto.subtle in Azion Runtime
  const subtle = crypto.subtle;

  // Generate an AES key for encryption
  const key = await subtle.generateKey(
    { name: "AES-GCM", length: 256 },
    true,
    ["encrypt", "decrypt"]
  );

  // Export the key for storage
  const exportedKey = await subtle.exportKey("raw", key);
  const keyBuffer = new Uint8Array(exportedKey);
  
  console.log("Generated key length:", keyBuffer.length);
  // Generated key length: 32

  // Encrypt data
  const iv = crypto.getRandomValues(new Uint8Array(12));
  const encoder = new TextEncoder();
  const data = encoder.encode("Sensitive data to encrypt");

  const encrypted = await subtle.encrypt(
    { name: "AES-GCM", iv },
    key,
    data
  );

  console.log("Encrypted data length:", encrypted.byteLength);
  // Encrypted data length: 41

  return new Response("Encryption complete", { status: 200 });
};

export default main;
```

The function responds with a confirmation, after it logs a key length of `32` bytes and an encrypted length of `41` bytes:

```text
Encryption complete
```

---

## Supported APIs

The table lists the status of each `node:crypto` API in Azion Runtime:

| API                 | Status                 |
| ------------------- | ---------------------- |
| `constants`         | 🟢 Supported           |
| `createHash()`      | 🟢 Supported           |
| `createHmac()`      | 🟢 Supported           |
| `getRandomValues()` | 🟢 Supported           |
| `randomBytes()`     | 🟢 Supported           |
| `randomUUID()`      | 🟢 Supported           |
| `subtle`            | 🟢 Supported           |
| `webcrypto`         | 🟢 Supported           |
| `createCipher()`    | 🟡 Partially supported |
| `createDecipher()`  | 🟡 Partially supported |
| `createSign()`      | 🟡 Partially supported |
| `createVerify()`    | 🟡 Partially supported |

APIs marked 🟡 Partially supported have limited functionality compared to the full Node.js implementation. For encryption and signing, the Web Crypto API (`crypto.subtle`) is a more complete alternative. The module also exports functions the table does not list: `createCipheriv()` and `createDecipheriv()` encrypt and decrypt with `aes-256-cbc`, `pbkdf2Sync()` derives a key from a password, `getHashes()` is available, and `timingSafeEqual()` and `generateKeyPairSync()` work in a deployed function.

---

## Related resources

- [Node.js APIs](/en/documentation/devtools/runtime/node.md): How each Node.js module behaves in Azion Runtime, with its support status.
- [SubtleCrypto](/en/documentation/devtools/runtime/api-reference/subtle-crypto.md): The Web Crypto methods that `crypto.subtle` exposes for encryption, signing, and key management.
- [Node.js crypto documentation](https://nodejs.org/api/crypto.html): The parameters and return values of every `node:crypto` API, as Node.js documents them.
- [Web Crypto API on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API): The standard behind `crypto.subtle` and `crypto.getRandomValues()`.
