# Compatibilidade APIs Node.js - Crypto

A API `crypto` no Node.js fornece um conjunto de funcionalidades criptográficas para ajudar os desenvolvedores a proteger suas aplicações. Ela inclui métodos para hashing, criptografia, descriptografia e geração de valores aleatórios seguros. Este módulo está disponível no Azion Runtime através da compatibilidade com Node.js, permitindo seu uso dentro de functions para assinar requisições, verificar integridade de mensagens ou gerar identificadores únicos próximos aos usuários.

---

## Exemplo: HMAC e geração de UUID

O exemplo abaixo mostra como usar o módulo `crypto` para gerar assinaturas HMAC e 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;
```

---

## Exemplo: Geração de hash com SHA-256

Use hashing para verificar integridade de dados ou criar identificadores determinísticos:

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

---

## Exemplo: Geração de bytes aleatórios

Gere valores aleatórios criptograficamente seguros para tokens, IDs de sessão ou 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;
```

---

## Exemplo: Integração com Web Crypto API

O módulo `crypto` também fornece acesso à Web Crypto API através do `crypto.subtle`. Note que `crypto.subtle` é equivalente a `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;
```

---

## APIs com suporte

| API | Status |
|-----|--------|
| `constants` | 🟢 Com suporte |
| `createHash` | 🟢 Com suporte |
| `createHmac` | 🟢 Com suporte |
| `getRandomValues` | 🟢 Com suporte |
| `randomBytes` | 🟢 Com suporte |
| `randomUUID` | 🟢 Com suporte |
| `subtle` | 🟢 Com suporte |
| `webcrypto` | 🟢 Com suporte |
| `createCipher` | 🟡 Parcialmente suportado |
| `createDecipher` | 🟡 Parcialmente suportado |
| `createSign` | 🟡 Parcialmente suportado |
| `createVerify` | 🟡 Parcialmente suportado |

:::note
APIs marcadas como 🟡 Parcialmente suportado têm funcionalidade limitada em comparação com a implementação completa do Node.js. Para operações de criptografia e assinatura, considere usar a Web Crypto API (`crypto.subtle`) como uma alternativa mais completa.
:::

---

## Recursos relacionados

- [Documentação do `crypto` no Node.js](https://nodejs.org/api/crypto.html)
- [Web Crypto API no MDN](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API)