226 lines
16 KiB
Plaintext
226 lines
16 KiB
Plaintext
page wrnexusencryption {
|
|
seo {
|
|
title = "@wrnexus/encryption"
|
|
description = "Hashing, HMAC, authenticated encryption, and key derivation."
|
|
}
|
|
|
|
view {
|
|
<div class="docs-shell">
|
|
<a href="#main" class="skip-link">Skip to content</a>
|
|
<header class="topbar">
|
|
<a class="brand" href="/"><span>W</span> WRNexusJS</a>
|
|
<nav aria-label="Primary"><a href="/getting-started">Get started</a><a href="/packages">Packages</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/language">Language</a><a href="/architecture">Architecture</a></nav>
|
|
<div class="topbar-actions"><a class="preview-pill" href="/access">Private preview · v0.8.7</a><button data-wire-theme-toggle class="theme-button" aria-label="Toggle color theme" title="Toggle color theme">◐</button></div>
|
|
</header>
|
|
<div class="mobile-doc-nav"><details><summary>Browse documentation</summary><nav><a href="/getting-started">Get started</a><a href="/packages">Packages</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/language">Language</a><a href="/architecture">Architecture</a><a href="/tutorial">Tutorial</a><a href="/guides/project-structure">Guides</a><a href="/examples">Examples</a><a href="/search">Search</a></nav></details></div>
|
|
<main id="main" class="portal-main docs-layout docs-layout--navigation"><aside class="docs-section-menu" aria-label="Documentation sections"><nav>
|
|
<section><strong>Get started</strong><a href="/getting-started">Quick start</a><a href="/tutorial">Tutorial</a><a href="/guides/full-stack-auth-demo">Auth dashboard demo</a><a href="/guides/configuration-and-profiles">Configuration</a></section>
|
|
<section><strong>Build</strong><a href="/guides/pages-and-components">Pages and components</a><a href="/guides/routing">Routing</a><a href="/guides/server-data">Server data</a><a href="/guides/forms-and-validation">Forms and validation</a><a href="/guides/database">Database</a></section>
|
|
<section><strong>Auth and security</strong><a href="/guides/authentication">Authentication</a><a href="/guides/authorization">Authorization</a><a href="/guides/security">Application security</a><a href="/security">Security policy</a></section>
|
|
<section><strong>Reference</strong><a href="/packages">Packages overview</a><a href="/packages/cli">CLI</a><a href="/language">.wrn language</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/examples">Examples</a></section>
|
|
<section class="package-menu"><strong>Packages</strong><a href="/packages/ai">@wrnexus/ai</a><a href="/packages/auth">@wrnexus/auth</a><a href="/packages/authz">@wrnexus/authz</a><a href="/packages/benchmark">@wrnexus/benchmark</a><a href="/packages/cache">@wrnexus/cache</a><a href="/packages/captcha">@wrnexus/captcha</a><a href="/packages/cli">@wrnexus/cli</a><a href="/packages/compiler">@wrnexus/compiler</a><a href="/packages/content">@wrnexus/content</a><a href="/packages/core">@wrnexus/core</a><a href="/packages/csr">@wrnexus/csr</a><a href="/packages/db">@wrnexus/db</a><a href="/packages/dev-server">@wrnexus/dev-server</a><a href="/packages/dev-toolbar">@wrnexus/dev-toolbar</a><a href="/packages/encryption">@wrnexus/encryption</a><a href="/packages/graphql">@wrnexus/graphql</a><a href="/packages/helpers">@wrnexus/helpers</a><a href="/packages/i18n">@wrnexus/i18n</a><a href="/packages/identity">@wrnexus/identity</a><a href="/packages/image">@wrnexus/image</a><a href="/packages/jwt">@wrnexus/jwt</a><a href="/packages/language-server">@wrnexus/language-server</a><a href="/packages/mcp">@wrnexus/mcp</a><a href="/packages/mobile">@wrnexus/mobile</a><a href="/packages/native">@wrnexus/native</a><a href="/packages/oauth">@wrnexus/oauth</a><a href="/packages/observability">@wrnexus/observability</a><a href="/packages/playground">@wrnexus/playground</a><a href="/packages/plugin">@wrnexus/plugin</a><a href="/packages/pubsub">@wrnexus/pubsub</a><a href="/packages/pwa">@wrnexus/pwa</a><a href="/packages/queue">@wrnexus/queue</a><a href="/packages/reactive">@wrnexus/reactive</a><a href="/packages/realtime">@wrnexus/realtime</a><a href="/packages/router">@wrnexus/router</a><a href="/packages/security">@wrnexus/security</a><a href="/packages/ssr">@wrnexus/ssr</a><a href="/packages/store">@wrnexus/store</a><a href="/packages/styles">@wrnexus/styles</a><a href="/packages/syntax">@wrnexus/syntax</a><a href="/packages/test">@wrnexus/test</a><a href="/packages/tracking">@wrnexus/tracking</a><a href="/packages/typecheck">@wrnexus/typecheck</a><a href="/packages/ui">@wrnexus/ui</a><a href="/packages/uploader">@wrnexus/uploader</a><a href="/packages/validation">@wrnexus/validation</a></section>
|
|
</nav></aside><div class="docs-reading-column">
|
|
<article class="documentation prose standalone package-document"><nav class="breadcrumbs" aria-label="Breadcrumb"><a href="/">Home</a><span>/</span><a href="/packages">Packages</a><span>/</span><span aria-current="page">@wrnexus/encryption</span></nav><section class="doc-intro"><span class="eyebrow">Security · Package reference</span><h1>@wrnexus/encryption</h1><p>Hashing, HMAC, authenticated encryption, and key derivation.</p><div class="doc-meta"><span>v0.8.7</span><span>Private registry</span><span>Security</span></div><section id="access" class="access-callout"><h2>Install the package</h2><p>After WorkRoot approves private registry access, install the release-aligned package:</p><pre><code>bun add @wrnexus/encryption@0.8.7</code><button type="button" class="copy-button" aria-label="Copy installation command">Copy</button></pre><p><a href="/access">Request preview access</a>. Never put registry tokens in source control.</p></section></section><section id="guide"><p>Authenticated encryption, hashing, HMAC, key rotation, and optional encrypted HTTP exchanges for WRNexusJS.</p>
|
|
<h3 id="core-helpers">Core helpers</h3>
|
|
<ul>
|
|
<li><code>generateKey()</code> — random 256-bit AES key encoded as base64.</li>
|
|
<li><code>deriveKey(password, salt)</code> — PBKDF2-derived AES key.</li>
|
|
<li><code>encrypt(plaintext, key)</code> / <code>decrypt(payload, key)</code> — AES-256-GCM.</li>
|
|
<li><code>sha256(data)</code> — SHA-256 digest.</li>
|
|
<li><code>hmacSign(data, secret)</code> / <code>hmacVerify(...)</code> — HMAC-SHA256.</li>
|
|
<li><code>createKeyring(keys)</code> — active/previous key management.</li>
|
|
<li><code>seal()</code> / <code>open()</code> — versioned ciphertext with key ID.</li>
|
|
</ul>
|
|
<h3 id="encrypted-http-envelope">Encrypted HTTP envelope</h3>
|
|
<pre data-language="ts"><code>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 });</code></pre>
|
|
<p>The envelope binds authenticated ciphertext to:</p>
|
|
<ul>
|
|
<li>HTTP method</li>
|
|
<li>URL path and query</li>
|
|
<li>request ID</li>
|
|
<li>timestamp and expiry window</li>
|
|
<li>encryption key ID</li>
|
|
<li>optional replay-store consumption</li>
|
|
</ul>
|
|
<p><code>encryptedBody()</code> decrypts request bodies only. <code>encryptedExchange()</code> also encrypts successful downstream responses while allowing application exceptions to propagate normally. <code>encryptedFetch()</code> provides a convenient controlled-client call.</p>
|
|
<h3 id="security-boundary">Security boundary</h3>
|
|
<p>Encrypted HTTP bodies <strong>do not replace TLS/HTTPS</strong>. Always use HTTPS.</p>
|
|
<p>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.</p>
|
|
<p>Use a shared replay store such as Redis in multi-instance deployments. The memory replay store is process-local.</p></section><section id="api" class="api"><h2>Complete TypeScript API</h2><p>Generated from the exact installed package declarations.</p><pre data-language="typescript"><code>import { Middleware } from '@wrnexus/core';
|
|
|
|
interface EncryptionKey {
|
|
id: string;
|
|
secret: string;
|
|
active?: boolean;
|
|
createdAt?: number;
|
|
}
|
|
interface EncryptionKeyring {
|
|
active(): EncryptionKey;
|
|
get(id: string): EncryptionKey | undefined;
|
|
keys(): EncryptionKey[];
|
|
rotate(key?: EncryptionKey): Promise<EncryptionKey>;
|
|
remove(id: string): boolean;
|
|
}
|
|
declare function createKeyring(initial: EncryptionKey[]): EncryptionKeyring;
|
|
/** Versioned payload: `wrn1.<key-id>.<aes-gcm-payload>`. */
|
|
declare function seal(plaintext: string, keyring: EncryptionKeyring): Promise<string>;
|
|
declare function open(sealed: string, keyring: EncryptionKeyring): Promise<string>;
|
|
declare function sealedKeyId(sealed: string): string | null;
|
|
declare function needsRotation(sealed: string, keyring: EncryptionKeyring): boolean;
|
|
|
|
declare const ENCRYPTED_HTTP_CONTENT_TYPE = "application/wrn+json";
|
|
declare const ENCRYPTED_HTTP_VERSION = "wrn-http-1";
|
|
interface EncryptedHttpEnvelope {
|
|
version: typeof ENCRYPTED_HTTP_VERSION;
|
|
keyId: string;
|
|
requestId: string;
|
|
timestamp: number;
|
|
ciphertext: string;
|
|
}
|
|
interface ReplayStore {
|
|
consume(id: string, expiresAt: number): boolean | Promise<boolean>;
|
|
}
|
|
interface EncryptedHttpOptions {
|
|
keyring: EncryptionKeyring;
|
|
maxAgeMs?: number;
|
|
maxBodyBytes?: number;
|
|
replayStore?: ReplayStore;
|
|
now?: () => number;
|
|
/** Require the clear request-id header used to bind encrypted responses. Default true. */
|
|
requireRequestIdHeader?: boolean;
|
|
}
|
|
interface DecryptedHttpBody<T> {
|
|
body: T;
|
|
requestId: string;
|
|
timestamp: number;
|
|
keyId: string;
|
|
}
|
|
declare function createMemoryReplayStore(now?: () => number): ReplayStore;
|
|
declare function encryptHttpBody<T>(body: T, input: {
|
|
keyring: EncryptionKeyring;
|
|
method?: string;
|
|
url: string | URL;
|
|
requestId?: string;
|
|
timestamp?: number;
|
|
}): Promise<EncryptedHttpEnvelope>;
|
|
declare function decryptHttpBody<T>(value: unknown, input: {
|
|
keyring: EncryptionKeyring;
|
|
method?: string;
|
|
url: string | URL;
|
|
maxAgeMs?: number;
|
|
replayStore?: ReplayStore;
|
|
now?: () => number;
|
|
expectedRequestId?: string;
|
|
}): Promise<DecryptedHttpBody<T>>;
|
|
declare function createEncryptedRequest<T>(url: string | URL, body: T, input: Omit<RequestInit, "body"> & {
|
|
keyring: EncryptionKeyring;
|
|
requestId?: string;
|
|
}): Promise<Request>;
|
|
declare function decryptRequest<T>(request: Request, options: EncryptedHttpOptions): Promise<DecryptedHttpBody<T>>;
|
|
declare function encryptResponse<T>(body: T, request: Request, options: EncryptedHttpOptions & {
|
|
status?: number;
|
|
headers?: HeadersInit;
|
|
}): Promise<Response>;
|
|
declare function decryptEncryptedResponse<T>(response: Response, request: Request, options: EncryptedHttpOptions): Promise<DecryptedHttpBody<T>>;
|
|
declare function encryptedFetch<TRequest, TResponse>(url: string | URL, body: TRequest, input: Omit<RequestInit, "body"> & EncryptedHttpOptions): Promise<TResponse>;
|
|
declare function encryptedBody(options: EncryptedHttpOptions): Middleware;
|
|
declare function encryptedExchange(options: EncryptedHttpOptions & {
|
|
encryptResponses?: boolean;
|
|
}): Middleware;
|
|
|
|
/**
|
|
* @wrnexus/encryption — authenticated symmetric encryption (AES-256-GCM) via
|
|
* WebCrypto, dependency-free. Use it to encrypt secrets, tokens, or database
|
|
* fields at rest.
|
|
*
|
|
* const key = await generateKey(); // store this safely
|
|
* const box = await encrypt("card #1234", key); // opaque base64 string
|
|
* const plain = await decrypt(box, key); // "card #1234"
|
|
*
|
|
* A key derived from a password (PBKDF2) is also supported via `deriveKey`.
|
|
*/
|
|
/** SHA-256 hex digest of a string (e.g. content hashing, dedup keys). */
|
|
declare function sha256(data: string): Promise<string>;
|
|
/** HMAC-SHA256 hex signature of `data` with `secret` (e.g. signing webhooks). */
|
|
declare function hmacSign(data: string, secret: string): Promise<string>;
|
|
/** Constant-time verify of an HMAC-SHA256 signature. */
|
|
declare function hmacVerify(data: string, secret: string, signature: string): Promise<boolean>;
|
|
/** Generate a random 256-bit key, base64-encoded. Store it as a secret. */
|
|
declare function generateKey(): Promise<string>;
|
|
/**
|
|
* Encrypt a string. Output is base64 of `iv(12) || ciphertext+tag`, safe to
|
|
* store or transmit. Each call uses a fresh random IV.
|
|
*/
|
|
declare function encrypt(plaintext: string, key: string): Promise<string>;
|
|
/** Decrypt a value produced by `encrypt`. Throws if the key is wrong or data tampered. */
|
|
declare function decrypt(payload: string, key: string): Promise<string>;
|
|
/** Derive a base64 AES key from a password + salt (PBKDF2, 100k iterations). */
|
|
declare function deriveKey(password: string, salt: string): Promise<string>;
|
|
|
|
export { type DecryptedHttpBody, ENCRYPTED_HTTP_CONTENT_TYPE, ENCRYPTED_HTTP_VERSION, type EncryptedHttpEnvelope, type EncryptedHttpOptions, type EncryptionKey, type EncryptionKeyring, type ReplayStore, createEncryptedRequest, createKeyring, createMemoryReplayStore, decrypt, decryptEncryptedResponse, decryptHttpBody, decryptRequest, deriveKey, encrypt, encryptHttpBody, encryptResponse, encryptedBody, encryptedExchange, encryptedFetch, generateKey, hmacSign, hmacVerify, needsRotation, open, seal, sealedKeyId, sha256 };
|
|
</code></pre></section><section id="examples" class="examples"><h2>Examples</h2><p>Copy-ready examples from the installed package documentation.</p><div class="example-grid"><article class="example-card"><h3>## Encrypted HTTP envelope</h3><pre data-language="ts"><code>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 });</code></pre></article><article class="example-card"><h3>Install @wrnexus/encryption</h3><pre data-language="sh"><code>bun add @wrnexus/encryption</code></pre></article></div></section></article></div>
|
|
<aside class="on-this-page"><h2>On this page</h2><nav><a class="toc-level-2" href="#guide">Guide</a><a class="toc-level-3" href="#core-helpers">Core helpers</a><a class="toc-level-3" href="#encrypted-http-envelope">Encrypted HTTP envelope</a><a class="toc-level-3" href="#security-boundary">Security boundary</a><a class="toc-level-2" href="#api">Complete API</a><a class="toc-level-2" href="#examples">Examples</a></nav></aside>
|
|
</main>
|
|
<footer><div class="footer-brand"><span class="footer-mark" aria-hidden="true">W</span><p><strong>WRNexusJS 0.8.7</strong><span>Complete API documentation generated from installed package declarations.</span></p></div><nav aria-label="Footer"><a href="/packages">All packages</a><a href="/getting-started">Get started</a><a href="/security">Security</a><a href="/support">Support</a><a href="/llms.txt">AI guide</a></nav><p class="footer-meta">Private Developer Preview · Bun-native</p></footer>
|
|
</div>
|
|
}
|
|
}
|