# @wrnexus/encryption

Authenticated encryption, hashing, HMAC, key rotation, and optional encrypted HTTP exchanges for WRNexusJS.

## Core helpers

- `generateKey()` — random 256-bit AES key encoded as base64.
- `deriveKey(password, salt)` — PBKDF2-derived AES key.
- `encrypt(plaintext, key)` / `decrypt(payload, key)` — AES-256-GCM.
- `sha256(data)` — SHA-256 digest.
- `hmacSign(data, secret)` / `hmacVerify(...)` — HMAC-SHA256.
- `createKeyring(keys)` — active/previous key management.
- `seal()` / `open()` — versioned ciphertext with key ID.

## Encrypted HTTP envelope

```ts
import {
  createEncryptedRequest,
  createKeyring,
  createMemoryReplayStore,
  decryptEncryptedResponse,
  encryptedExchange,
} from "@wrnexus/encryption";

const keyring = createKeyring([{ id: "2026-08", secret: process.env.API_BODY_KEY!, active: true }]);

const replayStore = createMemoryReplayStore();

// Server middleware.
app.use(
  encryptedExchange({
    keyring,
    replayStore,
    maxAgeMs: 60_000,
    maxBodyBytes: 1_048_576,
  }),
);

// Controlled service/native client.
const request = await createEncryptedRequest(
  "https://api.example.com/private/report",
  { reportId: "report-1" },
  { method: "POST", keyring },
);
const response = await fetch(request);
const result = await decryptEncryptedResponse(response, request, { keyring });
```

The envelope binds authenticated ciphertext to:

- HTTP method
- URL path and query
- request ID
- timestamp and expiry window
- encryption key ID
- optional replay-store consumption

`encryptedBody()` decrypts request bodies only. `encryptedExchange()` also encrypts successful downstream responses while allowing application exceptions to propagate normally. `encryptedFetch()` provides a convenient controlled-client call.

## Security boundary

Encrypted HTTP bodies **do not replace TLS/HTTPS**. Always use HTTPS.

This layer is appropriate for service-to-service traffic, native/mobile applications, controlled agents, and selected fields protected with server-managed keys. It cannot conceal data from an end user when browser JavaScript receives the decryption key. Never ship a long-lived server encryption key to a browser.

Use a shared replay store such as Redis in multi-instance deployments. The memory replay store is process-local.
