page wrnexusencryption { seo { title = "@wrnexus/encryption" description = "Hashing, HMAC, authenticated encryption, and key derivation." } view {
W WRNexusJS
Browse documentation
Security · Preview

@wrnexus/encryption

Hashing, HMAC, authenticated encryption, and key derivation.

Private registry access required

This package is not available from the public npm registry. After WorkRoot approves access and supplies private registry instructions, install the release-aligned package:

bun add @wrnexus/encryption@0.2.59

Request preview access. Never put registry tokens in source control.

Dependency-free crypto helpers for WRNexusJS: authenticated symmetric encryption (AES-256-GCM), hashing, and HMAC signing.

Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

Overview

This package provides small, focused cryptographic primitives for server-side use: encrypting secrets/tokens/database fields at rest with AES-256-GCM, deriving keys from passwords via PBKDF2, computing SHA-256 digests, and signing/verifying payloads with HMAC-SHA256. It is built entirely on the standard Web Crypto API (crypto.subtle) plus btoa/atob and TextEncoder/TextDecoder — no third-party dependencies. Reach for it whenever you need to protect sensitive values or verify webhook signatures. All functions are async (Web Crypto is promise-based).

bun add @wrnexus/encryption
Private package — the machine must be authenticated to the wrnexus npm org
(a read token in ~/.npmrc). Requires Bun (Node is not supported).

API

All keys are exchanged as base64 strings and all digests/signatures as hex strings.

ExportSignatureDescription
generateKey() => Promise<string>Generate a random 256-bit AES key, base64-encoded. Store it as a secret.
deriveKey(password: string, salt: string) => Promise<string>Derive a base64 AES-256 key from a password + salt using PBKDF2 (100,000 iterations, SHA-256).
encrypt(plaintext: string, key: string) => Promise<string>AES-256-GCM encrypt a string. Returns base64 of iv(12 bytes) ‖ ciphertext+tag. A fresh random IV is used each call.
decrypt(payload: string, key: string) => Promise<string>Decrypt a value produced by encrypt. Throws if the key is wrong or the data was tampered with.
sha256(data: string) => Promise<string>SHA-256 hex digest of a string (e.g. content hashing, dedup keys).
hmacSign(data: string, secret: string) => Promise<string>HMAC-SHA256 hex signature of data with secret (e.g. signing webhooks).
hmacVerify(data: string, secret: string, signature: string) => Promise<boolean>Constant-time verify of an HMAC-SHA256 hex signature.

Notes:

  • generateKey produces a 32-byte (256-bit) key via crypto.getRandomValues.
  • encrypt/decrypt require a base64-encoded 256-bit key; anything else throws "Encryption key must be a base64 256-bit key".
  • decrypt throws "Invalid ciphertext" if the payload is shorter than the 12-byte IV, and the underlying Web Crypto call throws on any authentication (tag) mismatch.
  • hmacVerify compares in constant time (length check plus XOR accumulation) to avoid timing leaks.

Usage

Symmetric encryption of a secret at rest:

import { generateKey, encrypt, decrypt } from "@wrnexus/encryption";

const key = await generateKey(); // store this safely (env/secret manager)

const box = await encrypt("card #1234", key); // opaque base64 string, safe to persist
const plain = await decrypt(box, key); // "card #1234"

Deriving a key from a user password instead of a random key:

import { deriveKey, encrypt } from "@wrnexus/encryption";

const key = await deriveKey("correct horse battery staple", "per-user-salt");
const box = await encrypt("secret note", key);

Hashing and webhook signature verification:

import { sha256, hmacSign, hmacVerify } from "@wrnexus/encryption";

const digest = await sha256("some content"); // 64-char hex string

const signature = await hmacSign(rawBody, webhookSecret);
const ok = await hmacVerify(rawBody, webhookSecret, incomingSignatureHeader);
if (!ok) throw new Error("Invalid webhook signature");

Requirements / Notes

  • Bun-only. Relies on the Web Crypto API (crypto.subtle, crypto.getRandomValues) and the global btoa/atob, TextEncoder/TextDecoder — all available in Bun's runtime.
  • No dependencies. The package has an empty dependency set; nothing is bundled beyond standard runtime APIs.
  • Algorithms: AES-256-GCM (encryption), PBKDF2 with 100k SHA-256 iterations (key derivation), SHA-256 (digest), HMAC-SHA256 (signing).
  • Keep generated/derived keys and HMAC secrets out of source control; treat them as first-class secrets.

Complete TypeScript API

This declaration comes from the exact installed package and lists its exported functions, classes, interfaces, and types.

/**
 * @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 { decrypt, deriveKey, encrypt, generateKey, hmacSign, hmacVerify, sha256 };

Examples

Examples are taken from this package's installed documentation and must be evaluated with its requirements and stability notes.

Symmetric encryption of a secret at rest

import { generateKey, encrypt, decrypt } from "@wrnexus/encryption";

const key = await generateKey(); // store this safely (env/secret manager)

const box = await encrypt("card #1234", key); // opaque base64 string, safe to persist
const plain = await decrypt(box, key); // "card #1234"

Deriving a key from a user password instead of a random key

import { deriveKey, encrypt } from "@wrnexus/encryption";

const key = await deriveKey("correct horse battery staple", "per-user-salt");
const box = await encrypt("secret note", key);

Hashing and webhook signature verification

import { sha256, hmacSign, hmacVerify } from "@wrnexus/encryption";

const digest = await sha256("some content"); // 64-char hex string

const signature = await hmacSign(rawBody, webhookSecret);
const ok = await hmacVerify(rawBody, webhookSecret, incomingSignatureHeader);
if (!ok) throw new Error("Invalid webhook signature");
} }