# node:crypto

O módulo `node:crypto` fornece as funções criptográficas do Node.js: hashing, assinaturas HMAC, criptografia, descriptografia e valores aleatórios seguros. No Node.js, o módulo encapsula as funções de hash, HMAC, cifra, decifra, assinatura e verificação do OpenSSL. No Azion Runtime, o módulo está disponível por meio da compatibilidade com Node.js, e você pode usá-lo dentro de uma function para assinar requisições, verificar a integridade de mensagens ou gerar identificadores únicos. Sua exportação `subtle`, na importação nomeada e na exportação padrão, é o mesmo objeto que `globalThis.crypto.subtle`, e o módulo também exporta `webcrypto`.

> **nota**
>
> Com `azion dev`, `timingSafeEqual()` e `generateKeyPairSync()` lançam `TypeError: (void 0) is not a function`, e o build emite o aviso `Import "timingSafeEqual" will always be undefined because there is no matching export in "internal-env-dev:crypto"`. As duas funções funcionam em uma function após o deploy. Localmente, `Buffer.isBuffer()` também retorna `false` para o buffer que `randomBytes()` retorna; após o deploy, retorna `true`.

---

## Exemplos

Cada exemplo é uma function completa que importa de `node:crypto`. A resposta abaixo de cada exemplo é a que uma function com deploy feito retorna. Valores aleatórios, como UUIDs e tokens, mudam a cada requisição.

### HMAC e geração de UUID

Esta function assina uma string com uma chave HMAC, imprime a assinatura e responde com um UUID aleatório:

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

A function responde com o UUID:

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

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

Esta function gera o hash de uma string fixa para verificar a integridade dos dados e gera o hash da URL da requisição para criar uma chave de cache determinística:

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

A function responde com os dois hashes. O valor `digest` é o mesmo a cada requisição; o valor `cacheKey` depende da URL da requisição, então o seu é diferente:

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

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

Esta function gera valores aleatórios seguros para um token, um ID de sessão e um nonce, e define o nonce em um header `Content-Security-Policy`:

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

A function responde com os três valores e define `Content-Security-Policy` como `script-src 'nonce-<nonce>'`, em que `<nonce>` é o valor de `nonce` da mesma resposta. Os valores mudam a cada requisição:

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

### Integração com a Web Crypto API

O módulo `crypto` também dá acesso à Web Crypto API por meio de `crypto.subtle`, que é o mesmo objeto que `globalThis.crypto.subtle`. Esta function gera uma chave AES, exporta essa chave e criptografa uma string com ela:

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

A function responde com uma confirmação, depois de registrar no log um tamanho de chave de `32` bytes e um tamanho criptografado de `41` bytes:

```text
Encryption complete
```

---

## APIs com suporte

A tabela lista o status de cada API de `node:crypto` no Azion Runtime:

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

As APIs marcadas como 🟡 Parcialmente suportado têm funcionalidade limitada em comparação com a implementação completa do Node.js. Para criptografia e assinatura, a Web Crypto API (`crypto.subtle`) é uma alternativa mais completa. O módulo também exporta funções que a tabela não lista: `createCipheriv()` e `createDecipheriv()` criptografam e descriptografam com `aes-256-cbc`, `pbkdf2Sync()` deriva uma chave a partir de uma senha e `getHashes()` está disponível. `timingSafeEqual()` e `generateKeyPairSync()`, também exportadas, funcionam em uma function após o deploy.

---

## Recursos relacionados

- [APIs do Node.js](/pt-br/documentacao/devtools/runtime/node.md): Como cada módulo do Node.js se comporta no Azion Runtime, com seu status de suporte.
- [SubtleCrypto](/pt-br/documentacao/devtools/runtime/api-reference/subtle-crypto.md): Os métodos da Web Crypto que `crypto.subtle` expõe para criptografia, assinatura e gerenciamento de chaves.
- [Documentação do crypto no Node.js](https://nodejs.org/api/crypto.html): Os parâmetros e os valores de retorno de cada API de `node:crypto`, conforme a documentação do Node.js.
- [Web Crypto API na MDN](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API): O padrão por trás de `crypto.subtle` e `crypto.getRandomValues()`.
