# Node.js API compatibility - Crypto

The `crypto` API in Node.js provides a set of cryptographic functionalities to help developers secure their applications. It includes methods for hashing, encryption, decryption, and generating secure random values. This module is available in the Azion Runtime through Node.js compatibility, so you can use it inside functions to sign requests, verify message integrity, or generate unique identifiers close to your users.

---

## Example: HMAC and UUID generation

The example below shows how to use the `crypto` module to generate HMAC signatures and UUIDs:

```javascript
/**
 * An example of using the Node.js Crypto API in an Azion Function.
 * Support:
 * - Extended by library `crypto-browserify`
 * - Implemented aditional methods:
 *  - randomUUID (named exported only)
 * @module runtime-apis/nodejs/crypto/main
 * @example
 * // Execute with Azion Bundler:
 * npx edge-functions build
 * npx edge-functions 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);
  // 5f2f3c2b9

  const uuid = randomUUID();
  console.log(uuid);
  // 1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4c1e

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

export default main;
```

---

## Example: Hash generation with SHA-256

Use hashing to verify data integrity or create deterministic identifiers:

```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: a1b2c3d4e5f6...

  // 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;
```

---

## Example: Random bytes generation

Generate cryptographically secure random values for tokens, session IDs, or nonces:

```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;
```

---

## Example: Web Crypto API integration

The `crypto` module also provides access to the Web Crypto API through `crypto.subtle`. Note that `crypto.subtle` is equivalent to `globalThis.crypto.subtle`:

```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);

  // 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);

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

export default main;
```

---

## Supported APIs

| 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 |

:::note
APIs marked as 🟡 Partially supported have limited functionality compared to the full Node.js implementation. For encryption and signing operations, consider using the Web Crypto API (`crypto.subtle`) as a more complete alternative.
:::

---

## Related resources

- [Node.js `crypto` documentation](https://nodejs.org/api/crypto.html)
- [Web Crypto API on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API)