### Install age-encryption with npm Source: https://github.com/filosottile/typage/blob/main/README.md Install the age-encryption package using npm. ```sh npm install age-encryption ``` -------------------------------- ### Install and Use age-plugin-fido2prf Source: https://github.com/filosottile/typage/blob/main/README.md Install the plugin and use it to decrypt a file from the CLI using a FIDO2 key identity. Ensure the identity.txt file contains your FIDO2 key's identity string. ```sh go install filippo.io/typage/fido2prf/cmd/age-plugin-fido2prf@latest cat << EOF > identity.txt AGE-PLUGIN-FIDO2PRF-1Q9VGPY2E7S5FJJS3N7P03TZMMEJ94S6HYLDJLU8WVX2HP8SXQUGJUZ68LN6GP705662VS06UEX5J42W80NZT8Y2DQ8GTDN50VGATCNYLJ4HY2W5J67KYCTM858UFDCNUUDZ6U28WEMUKGVG9RNELRJDH8NFEP999Z8XFSS8XLS448A3TSQKWG9DMPL8ZCRRA02KSUC2UXTYDFNVYAE5KCMMRV9KXSMMNWJQKXATNVGTXV35G EOF age -d -i identity.txt << EOF -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IGFnZS1lbmNyeXB0aW9uLm9yZy9maWRv MnByZiBJSFFHd0poUkNSYThuVnB6b1R1bjdBClJ3d3dRUUtiRjN4TkU0VWx1SUZU WnJtTVBFUTZoR0d4eUx2WXFOSFBsQzQKLS0tIFNWVGRnNzV4L00wblRENUZyYlFh WU5wQmVsdG5hL0lmcXhTVzZHTVRtdFkK2rYiueXr8dgM1GiLVrBMC/LQRzkDacMw GEtVcMZyh7b90z6VR3KT92EIlA== -----END AGE ENCRYPTED FILE----- EOF ``` -------------------------------- ### generateHybridIdentity() Source: https://context7.com/filosottile/typage/llms.txt Generates a post-quantum hybrid identity using ML-KEM 768 × X25519. The returned string starts with `AGE-SECRET-KEY-PQ-1...` and its corresponding recipient begins with `age1pq1...`. Use this when long-term resistance to quantum computers is required. ```APIDOC ## generateHybridIdentity() ### Description Generates a post-quantum hybrid identity using ML-KEM 768 × X25519. The returned string starts with `AGE-SECRET-KEY-PQ-1...` and its corresponding recipient begins with `age1pq1...`. Use this when long-term resistance to quantum computers is required. ### Usage ```ts import * as age from "age-encryption" const identity = await age.generateHybridIdentity() const recipient = await age.identityToRecipient(identity) console.log(identity) // AGE-SECRET-KEY-PQ-1... (keep secret) console.log(recipient) // age1pq1... (share this) const e = new age.Encrypter() e.addRecipient(recipient) const ciphertext = await e.encrypt("post-quantum protected message") const d = new age.Decrypter() d.addIdentity(identity) const plaintext = await d.decrypt(ciphertext, "text") console.log(plaintext) // "post-quantum protected message" ``` ``` -------------------------------- ### Build Browser Library with esbuild Source: https://github.com/filosottile/typage/blob/main/README.md Use esbuild to bundle and minify the age-encryption library for browser use, exposing it as a global variable. ```sh cd "$(mktemp -d)" && npm init -y && npm install esbuild age-encryption npx esbuild --target=es2022 --bundle --minify --outfile=age.js --global-name=age age-encryption ``` -------------------------------- ### Encrypt and Decrypt with Post-Quantum Hybrid Keys Source: https://github.com/filosottile/typage/blob/main/README.md Illustrates the process of generating an identity that uses post-quantum hybrid keys for enhanced security. ```APIDOC ## Encrypt and Decrypt with Post-Quantum Hybrid Keys ### Description This example demonstrates generating an identity that incorporates post-quantum cryptography alongside traditional algorithms for hybrid key encryption. ### Method N/A (TypeScript functions and classes) ### Endpoint N/A ### Parameters N/A ### Request Example ```ts import * as age from "age-encryption" const identity = await age.generateHybridIdentity() const recipient = await age.identityToRecipient(identity) console.log(identity) console.log(recipient) // ... further encryption/decryption steps would follow ``` ### Response - `identity`: The generated hybrid identity object. - `recipient`: The derived recipient object for the hybrid identity. ``` -------------------------------- ### Generate Identity and Encrypt/Decrypt Source: https://github.com/filosottile/typage/blob/main/README.md Demonstrates how to generate a new identity, derive a recipient, and then encrypt and decrypt a message using these. ```APIDOC ## Generate Identity and Encrypt/Decrypt ### Description This example shows the basic workflow of generating a new identity, converting it to a recipient, encrypting a message, and then decrypting it back using the generated identity. ### Method N/A (TypeScript functions and classes) ### Endpoint N/A ### Parameters N/A ### Request Example ```ts import * as age from "age-encryption" const identity = await age.generateIdentity() const recipient = await age.identityToRecipient(identity) console.log(identity) console.log(recipient) const e = new age.Encrypter() e.addRecipient(recipient) const ciphertext = await e.encrypt("Hello, age!") const d = new age.Decrypter() d.addIdentity(identity) const out = await d.decrypt(ciphertext, "text") console.log(out) ``` ### Response #### Success Response - `identity`: The generated identity object. - `recipient`: The derived recipient object. - `out`: The decrypted message string. ``` -------------------------------- ### ASCII Armoring Source: https://github.com/filosottile/typage/blob/main/README.md Shows how to encode encrypted binary data into an ASCII armored format and decode it back. ```APIDOC ## ASCII Armoring ### Description This example demonstrates how to use the ASCII armoring feature to encode binary encrypted data into a text-based format (similar to PEM) and then decode it back to binary for decryption. ### Method N/A (TypeScript functions and classes) ### Endpoint N/A ### Parameters N/A ### Request Example ```ts import * as age from "age-encryption" const identity = await age.generateIdentity() const recipient = await age.identityToRecipient(identity) console.log(identity) console.log(recipient) const e = new age.Encrypter() e.addRecipient(recipient) const ciphertext = await e.encrypt("Hello, age!") const armored = age.armor.encode(ciphertext) console.log(armored) // -----BEGIN AGE ENCRYPTED FILE----- // YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0QXVkQmNwZ3ZzYnNRZDJP // WlFId3hyeFNmRS9SdUVUTkFhY1FXSno5VUFBClNOSWhEbnhoK21TaEs3SWRGdklw // OW9pdlBZbDg3SEVSQ1FZZHBvUS90YjgKLS0tIGRCVXNNWmdJS0ZkNlNZbStPZWh4 // N2FBNUJZdTFxMmYwVTEzUWwvTFVNeUkKrNZnrZjMlXvoCHz0FUS/bp9129XtSV1Q // 2twDjjAOwgBtBYoji9gKWgOG4w== // -----END AGE ENCRYPTED FILE----- const d = new age.Decrypter() d.addIdentity(identity) const decoded = age.armor.decode(armored) const out = await d.decrypt(decoded, "text") console.log(out) ``` ### Response - `armored`: The ASCII armored string representation of the encrypted data. - `out`: The decrypted message string. ``` -------------------------------- ### Generate FIDO2 Credentials Source: https://github.com/filosottile/typage/blob/main/README.md Generate FIDO2 credentials from the command line. Ensure the relying party ID matches the website's origin for browser compatibility. ```sh age-plugin-fido2prf -generate RPID ``` -------------------------------- ### Add age-encryption with Deno Source: https://github.com/filosottile/typage/blob/main/README.md Add the age-encryption package using Deno's JSR registry. ```sh deno add jsr:@age/age-encryption ``` -------------------------------- ### Encrypt and Decrypt with a Passphrase Source: https://github.com/filosottile/typage/blob/main/README.md Demonstrates encrypting and decrypting data using a secret passphrase. ```APIDOC ## Encrypt and Decrypt with a Passphrase ### Description This example shows how to encrypt data using a passphrase and then decrypt it using the same passphrase. This method is suitable when you don't need to manage cryptographic identities. ### Method N/A (TypeScript functions and classes) ### Endpoint N/A ### Parameters N/A ### Request Example ```ts import { Encrypter, Decrypter } from "age-encryption" const e = new Encrypter() e.setPassphrase("burst-swarm-slender-curve-ability-various-crystal-moon-affair-three") const ciphertext = await e.encrypt("Hello, age!") const d = new Decrypter() d.addPassphrase("burst-swarm-slender-curve-ability-various-crystal-moon-affair-three") const out = await d.decrypt(ciphertext, "text") console.log(out) ``` ### Response - `ciphertext`: The encrypted data as a `Uint8Array`. - `out`: The decrypted message string. ``` -------------------------------- ### Create WebAuthn Credentials for Encryption Source: https://context7.com/filosottile/typage/llms.txt Generate WebAuthn credentials (passkeys or hardware security keys) for use with `WebAuthnRecipient` and `WebAuthnIdentity`. Requires browser support for the PRF extension. Save the identity string for security keys as it cannot be regenerated. ```typescript import * as age from "age-encryption" // --- Passkey (discoverable, synced via iCloud Keychain / password manager) --- const passkeyIdentity = await age.webauthn.createCredential({ keyName: "age encryption key 🦈", // rpId defaults to window.location.hostname }) console.log(passkeyIdentity) // AGE-PLUGIN-FIDO2PRF-1... // --- Hardware security key (non-discoverable, e.g. YubiKey) --- const hwKeyIdentity = await age.webauthn.createCredential({ type: "security-key", keyName: "YubiKey age key", rpId: "example.com", }) console.log(hwKeyIdentity) // AGE-PLUGIN-FIDO2PRF-1... (save this, it cannot be regenerated) ``` -------------------------------- ### webauthn.createCredential() - Create a WebAuthn credential for encryption Source: https://context7.com/filosottile/typage/llms.txt Creates a new WebAuthn credential (passkey or hardware security key) that can be used with `WebAuthnRecipient` and `WebAuthnIdentity`. Requires browser support for the PRF extension. ```APIDOC ## WebAuthn Credential Creation ### Description Create a WebAuthn credential (passkey or hardware security key) for encryption. ### Function - `webauthn.createCredential(options: { type?: "security-key", keyName: string, rpId?: string }): Promise`: Creates a new WebAuthn credential and returns an identity string. ### Example Usage ```ts import * as age from "age-encryption" // --- Passkey --- const passkeyIdentity = await age.webauthn.createCredential({ keyName: "age encryption key 🦈", }) console.log(passkeyIdentity) // AGE-PLUGIN-FIDO2PRF-1... // --- Hardware security key --- const hwKeyIdentity = await age.webauthn.createCredential({ type: "security-key", keyName: "YubiKey age key", rpId: "example.com", }) console.log(hwKeyIdentity) // AGE-PLUGIN-FIDO2PRF-1... (save this) ``` ``` -------------------------------- ### Basic Browser Encryption and Decryption Source: https://github.com/filosottile/typage/blob/main/README.md Demonstrates generating an identity, encrypting a string with a recipient, and decrypting it back in the browser using the age-encryption library. ```javascript (async () => { const identity = await age.generateIdentity() const recipient = await age.identityToRecipient(identity) console.log(identity) console.log(recipient) const e = new age.Encrypter() e.addRecipient(recipient) const ciphertext = await e.encrypt("Hello, age!") const d = new age.Decrypter() d.addIdentity(identity) const out = await d.decrypt(ciphertext, "text") console.log(out) })() ``` -------------------------------- ### Log Age Module Load Event Source: https://github.com/filosottile/typage/blob/main/wwwdev/index.html Listens for the 'load' event on the window and logs a message to the console when the 'age' module is loaded. Access 'age' via the JavaScript console. ```javascript window.addEventListener('load', () => { console.log('age module loaded') }) ``` -------------------------------- ### Generate Post-Quantum Hybrid Identity Source: https://context7.com/filosottile/typage/llms.txt Generates a hybrid identity for long-term resistance to quantum computers. Demonstrates encryption and decryption with this identity. ```typescript import * as age from "age-encryption" const identity = await age.generateHybridIdentity() const recipient = await age.identityToRecipient(identity) console.log(identity) // AGE-SECRET-KEY-PQ-1... (keep secret) console.log(recipient) // age1pq1... (share this) const e = new age.Encrypter() e.addRecipient(recipient) const ciphertext = await e.encrypt("post-quantum protected message") const d = new age.Decrypter() d.addIdentity(identity) const plaintext = await d.decrypt(ciphertext, "text") console.log(plaintext) // "post-quantum protected message" ``` -------------------------------- ### Encrypt and Decrypt with WebAuthn Passkeys Source: https://context7.com/filosottile/typage/llms.txt Use WebAuthnRecipient and WebAuthnIdentity for encryption and decryption keyed by a WebAuthn PRF credential. User verification (biometric/PIN) is prompted on each operation, with no extractable keys. ```typescript import * as age from "age-encryption" // --- Encrypt with a passkey (user prompted to select credential) --- const e = new age.Encrypter() e.addRecipient(new age.webauthn.WebAuthnRecipient()) const ciphertext = await e.encrypt("browser-protected secret") const armored = age.armor.encode(ciphertext) // --- Decrypt with a passkey --- const d = new age.Decrypter() d.addIdentity(new age.webauthn.WebAuthnIdentity()) const decoded = age.armor.decode(armored) const plaintext = await d.decrypt(decoded, "text") console.log(plaintext) // "browser-protected secret" ``` ```typescript // --- Use a specific hardware security key identity --- const hwKeyIdentity = "AGE-PLUGIN-FIDO2PRF-1Q9VGPY2E7S5FJJS3N7P03T..." const e2 = new age.Encrypter() e2.addRecipient(new age.webauthn.WebAuthnRecipient({ identity: hwKeyIdentity })) const ct2 = await e2.encrypt("hardware-key protected secret") const d2 = new age.Decrypter() d2.addIdentity(new age.webauthn.WebAuthnIdentity({ identity: hwKeyIdentity })) const pt2 = await d2.decrypt(ct2, "text") console.log(pt2) // "hardware-key protected secret" ``` -------------------------------- ### Encrypt and Decrypt using the Streams API Source: https://github.com/filosottile/typage/blob/main/README.md Illustrates encrypting and decrypting data using ReadableStreams, suitable for large files or network data. ```APIDOC ## Encrypt and Decrypt using the Streams API ### Description This example demonstrates how to use the `age-encryption` library with `ReadableStream` objects for encrypting and decrypting large amounts of data, such as files or network requests/responses, efficiently. ### Method N/A (TypeScript functions and classes) ### Endpoint N/A ### Parameters N/A ### Request Example ```ts import { Encrypter, Decrypter } from "age-encryption" const file = new File([new TextEncoder().encode("age")], "age.txt") const e = new Encrypter() e.setScryptWorkFactor(12) e.setPassphrase("light-original-energy-average-wish-blind-vendor-pencil-illness-scorpion") const encryptedStream = await e.encrypt(file.stream()) console.log(encryptedStream.size(file.size)) const d = new Decrypter() d.addPassphrase("light-original-energy-average-wish-blind-vendor-pencil-illness-scorpion") const decryptedStream = await d.decrypt(encryptedStream) console.log(decryptedStream.size(encryptedStream.size(file.size))) console.log(await new Response(decryptedStream).text()) ``` ### Response - `encryptedStream`: A `ReadableStream` of encrypted data. - `decryptedStream`: A `ReadableStream` of decrypted data. - The final `console.log` outputs the decrypted text content. ``` -------------------------------- ### identityToRecipient() Source: https://context7.com/filosottile/typage/llms.txt Converts an age identity string or a Web Crypto CryptoKey into the corresponding public recipient string. The recipient is safe to share; the identity must remain secret. ```APIDOC ## identityToRecipient() ### Description Converts an age identity string (`AGE-SECRET-KEY-1...` or `AGE-SECRET-KEY-PQ-1...`) or a Web Crypto `CryptoKey` into the corresponding public recipient string. The recipient is safe to share; the identity must remain secret. ### Usage ```ts import * as age from "age-encryption" // From a stored identity string const storedIdentity = "AGE-SECRET-KEY-1HRUMZM6XPUUTZ9VCAUM8P3SRMXH..." const recipient = await age.identityToRecipient(storedIdentity) console.log(recipient) // age1... // From a Web Crypto CryptoKey (non-extractable key) const keyPair = await crypto.subtle.generateKey({ name: "X25519" }, false, ["deriveBits"]) const recipientFromCrypto = await age.identityToRecipient( (keyPair as CryptoKeyPair).privateKey ) console.log(recipientFromCrypto) // age1... ``` ``` -------------------------------- ### Encrypt/Decrypt with Passphrase Source: https://github.com/filosottile/typage/blob/main/README.md Encrypts and decrypts a message using a passphrase. The passphrase must be the same for both encryption and decryption. Ensure the passphrase is kept secret. ```ts import { Encrypter, Decrypter } from "age-encryption" const e = new Encrypter() e.setPassphrase("burst-swarm-slender-curve-ability-various-crystal-moon-affair-three") const ciphertext = await e.encrypt("Hello, age!") const d = new Decrypter() d.addPassphrase("burst-swarm-slender-curve-ability-various-crystal-moon-affair-three") const out = await d.decrypt(ciphertext, "text") console.log(out) ``` -------------------------------- ### Custom Recipient and Identity Interfaces Source: https://context7.com/filosottile/typage/llms.txt Implement the `Recipient` and `Identity` interfaces to integrate with remote key stores, HSMs, or secrets managers. These methods handle raw `Stanza` objects. ```APIDOC ## Custom Recipient / Identity interfaces ### Description Implement the `Recipient` interface (`wrapFileKey`) and/or the `Identity` interface (`unwrapFileKey`) to integrate with remote APIs, HSMs, secrets managers, or age plugins. Both methods receive/return raw `Stanza` objects that are embedded in the age file header. ### Method `unwrapFileKey(stanzas: age.Stanza[]): Promise` ### Parameters - `stanzas` (Array): An array of Stanza objects to process. ### Request Example ```ts import * as age from "age-encryption" // Custom identity backed by a remote secrets manager class RemoteIdentity implements age.Identity { constructor(private readonly keyId: string) {} async unwrapFileKey(stanzas: age.Stanza[]): Promise { for (const stanza of stanzas) { if (stanza.args[0] !== "remote-kms") continue // Send stanza.body to a remote KMS and get the plaintext file key const response = await fetch("/api/kms/unwrap", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ keyId: this.keyId, wrappedKey: btoa(String.fromCharCode(...stanza.body)), }), }) if (!response.ok) throw new Error(`KMS error: ${response.status}`) const { fileKey } = await response.json() as { fileKey: number[] } return new Uint8Array(fileKey) } return null // no matching stanza } } const d = new age.Decrypter() d.addIdentity(new RemoteIdentity("my-kms-key-id")) const plaintext = await d.decrypt(ciphertext, "text") console.log(plaintext) ``` ``` -------------------------------- ### Browser Encryption with Passkeys Source: https://github.com/filosottile/typage/blob/main/README.md Encrypts a string using WebAuthn passkeys in the browser. Requires user confirmation via an authenticator. The encrypted output is armored. ```typescript await age.webauthn.createCredential({ keyName: "age encryption key 🦈" }) const e = new age.Encrypter() e.addRecipient(new age.webauthn.WebAuthnRecipient()) const ciphertext = await e.encrypt("Hello, age!") const armored = age.armor.encode(ciphertext) console.log(armored) ``` -------------------------------- ### Encrypter Source: https://context7.com/filosottile/typage/llms.txt The Encrypter class encrypts data using one or more recipients or a passphrase. These two modes are mutually exclusive. Call encrypt() with a string, Uint8Array, or ReadableStream. Multiple files can be encrypted with the same configured Encrypter instance. ```APIDOC ## Encrypter ### Description The `Encrypter` class encrypts data using one or more recipients (`addRecipient`) or a passphrase (`setPassphrase`). These two modes are mutually exclusive. Call `encrypt()` with a string, `Uint8Array`, or `ReadableStream`. Multiple files can be encrypted with the same configured `Encrypter` instance. ### Usage ```ts import { Encrypter } from "age-encryption" // --- Recipient-based encryption (multiple recipients) --- const e = new Encrypter() e.addRecipient("age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmokasj") e.addRecipient("age1pq1...") // also supports hybrid post-quantum recipients const ciphertext = await e.encrypt("Hello, age!") // ciphertext is Uint8Array // --- Passphrase-based encryption --- const ep = new Encrypter() ep.setScryptWorkFactor(14) // lower = faster but weaker; default is 18 ep.setPassphrase("burst-swarm-slender-curve-ability-various-crystal-moon") const ciphertextPass = await ep.encrypt(new TextEncoder().encode("secret data")) ``` ``` -------------------------------- ### Encrypt/Decrypt with ASCII Armoring Source: https://github.com/filosottile/typage/blob/main/README.md Encrypts a message and then encodes the resulting binary ciphertext into an ASCII-armored string. The armored string can be decoded back into binary for decryption. This is useful for text-based transport. ```ts import * as age from "age-encryption" const identity = await age.generateIdentity() const recipient = await age.identityToRecipient(identity) console.log(identity) console.log(recipient) const e = new age.Encrypter() e.addRecipient(recipient) const ciphertext = await e.encrypt("Hello, age!") const armored = age.armor.encode(ciphertext) console.log(armored) // -----BEGIN AGE ENCRYPTED FILE----- // YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0QXVkQmNwZ3ZzYnNRZDJP // WlFId3hyeFNmRS9SdUVUTkFhY1FXSno5VUFBClNOSWhEbnhoK21TaEs3SWRGdklw // OW9pdlBZbDg3SEVSQ1FZZHBvUS90YjgKLS0tIGRCVXNNWmdJS0ZkNlNZbStPZWh4 // N2FBNUJZdTFxMmYwVTEzUWwvTFVNeUkKrNZnrZjMlXvoCHz0FUS/bp9129XtSV1Q // 2twDjjAOwgBtBYoji9gKWgOG4w== // -----END AGE ENCRYPTED FILE----- const d = new age.Decrypter() d.addIdentity(identity) const decoded = age.armor.decode(armored) const out = await d.decrypt(decoded, "text") console.log(out) ``` -------------------------------- ### Decrypt Files with Decrypter Class Source: https://context7.com/filosottile/typage/llms.txt Use the Decrypter class to decrypt files using identity strings, Web Crypto keys, or passphrases. It attempts all configured methods in parallel, returning the first successful decryption. ```typescript import { Decrypter } from "age-encryption" // --- Decrypt with identity string --- const d = new Decrypter() d.addIdentity("AGE-SECRET-KEY-1HRUMZM6XPUUTZ9VCAUM8P3SRMXH...") const plaintext = await d.decrypt(ciphertext, "text") console.log(plaintext) // "Hello, age!" // --- Decrypt returning Uint8Array (default) --- const bytes = await d.decrypt(ciphertext) console.log(new TextDecoder().decode(bytes)) // --- Decrypt with a Web Crypto CryptoKey --- const keyPair = await crypto.subtle.generateKey({ name: "X25519" }, false, ["deriveBits"]) const d2 = new Decrypter() d2.addIdentity((keyPair as CryptoKeyPair).privateKey) const out = await d2.decrypt(ciphertext, "text") // --- Try multiple identities / passphrases --- const d3 = new Decrypter() d3.addPassphrase("first-possible-passphrase") d3.addPassphrase("second-possible-passphrase") d3.addIdentity("AGE-SECRET-KEY-1...") const result = await d3.decrypt(ciphertext, "text") // first match wins ``` -------------------------------- ### Generate Hybrid Identity and Encrypt/Decrypt Source: https://github.com/filosottile/typage/blob/main/README.md Generates a new post-quantum hybrid identity. This is a variant of identity generation for enhanced security. ```ts import * as age from "age-encryption" const identity = await age.generateHybridIdentity() const recipient = await age.identityToRecipient(identity) console.log(identity) console.log(recipient) // ... ``` -------------------------------- ### Encrypter.encrypt(stream) / Decrypter.decrypt(stream) - Streaming encryption and decryption Source: https://context7.com/filosottile/typage/llms.txt Enables memory-efficient streaming encryption and decryption for large files. Both `encrypt` and `decrypt` methods accept a `ReadableStream` and return a `ReadableStreamWithSize` which can be piped to other consumers. ```APIDOC ## Streaming Encryption and Decryption ### Description Process large files efficiently using streams for encryption and decryption. ### Methods - `Encrypter.encrypt(stream: ReadableStream): ReadableStreamWithSize` - `Decrypter.decrypt(stream: ReadableStream): ReadableStreamWithSize` Both methods return a `ReadableStreamWithSize` which has a `size(sourceSize)` method to estimate the output size. ### Example Usage ```ts import { Encrypter, Decrypter } from "age-encryption" // --- Stream encrypt a File --- const file = new File([new TextEncoder().encode("large file contents")], "data.txt") const e = new Encrypter() e.setPassphrase("...") const encryptedStream = await e.encrypt(file.stream()) console.log("encrypted size:", encryptedStream.size(file.size), "bytes") // --- Stream decrypt --- const d = new Decrypter() d.addPassphrase("...") const decryptedStream = await d.decrypt(encryptedBlob.stream()) console.log("plaintext size:", decryptedStream.size(encryptedBlob.size), "bytes") const text = await new Response(decryptedStream).text() console.log(text) ``` ``` -------------------------------- ### CSS Variables for Theming Source: https://github.com/filosottile/typage/blob/main/wwwdev/index.html Defines CSS variables for font family and color scheme, suitable for theming across different contexts. ```css typage dev { font-family: Avenir, Montserrat, Corbel, 'URW Gothic', source-sans-pro, sans-serif; color-scheme: light dark; } ``` -------------------------------- ### CSS Body Styling Source: https://github.com/filosottile/typage/blob/main/wwwdev/index.html Sets maximum width, margin, and padding for the body element to control layout and spacing. ```css body { max-width: 900px; margin: 5rem auto; padding: 0 30px; } ``` -------------------------------- ### Encrypt and Decrypt with Web Crypto API Key Source: https://github.com/filosottile/typage/blob/main/README.md Demonstrates using a Web Crypto API X25519 key pair for encryption and decryption with age. The private key is added as an identity to the decrypter. ```ts const keyPair = await crypto.subtle.generateKey({ name: "X25519" }, false, ["deriveBits"]) const identity = (keyPair as CryptoKeyPair).privateKey const recipient = await age.identityToRecipient(identity) console.log(recipient) const e = new age.Encrypter() e.addRecipient(recipient) const file = await e.encrypt("age") const d = new age.Decrypter() d.addIdentity(identity) const out = await d.decrypt(file, "text") console.log(out) ``` -------------------------------- ### Implement Custom Recipient/Identity for Remote Key Stores Source: https://context7.com/filosottile/typage/llms.txt Extend encryption capabilities by implementing the Recipient and Identity interfaces to integrate with remote APIs, HSMs, or secrets managers. Methods receive/return raw Stanza objects embedded in the age file header. ```typescript import * as age from "age-encryption" // Custom identity backed by a remote secrets manager class RemoteIdentity implements age.Identity { constructor(private readonly keyId: string) {} async unwrapFileKey(stanzas: age.Stanza[]): Promise { for (const stanza of stanzas) { if (stanza.args[0] !== "remote-kms") continue // Send stanza.body to a remote KMS and get the plaintext file key const response = await fetch("/api/kms/unwrap", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ keyId: this.keyId, wrappedKey: btoa(String.fromCharCode(...stanza.body)), }), }) if (!response.ok) throw new Error(`KMS error: ${response.status}`) const { fileKey } = await response.json() as { fileKey: number[] } return new Uint8Array(fileKey) } return null // no matching stanza } } const d = new age.Decrypter() d.addIdentity(new RemoteIdentity("my-kms-key-id")) const plaintext = await d.decrypt(ciphertext, "text") console.log(plaintext) ``` -------------------------------- ### ASCII Armor Encoding and Decoding with age-encryption Source: https://context7.com/filosottile/typage/llms.txt Use `armor.encode()` to wrap binary age ciphertext in a PEM-style ASCII block for safe transport in text-based formats. `armor.decode()` reverses this process, tolerating extra whitespace and CRLF line endings. ```typescript import * as age from "age-encryption" const identity = await age.generateIdentity() const recipient = await age.identityToRecipient(identity) const e = new age.Encrypter() e.addRecipient(recipient) const ciphertext = await e.encrypt("secret message") // Encode to ASCII armor const armored = age.armor.encode(ciphertext) console.log(armored) // -----BEGIN AGE ENCRYPTED FILE----- // YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOS... // -----END AGE ENCRYPTED FILE----- // Decode and decrypt const d = new age.Decrypter() d.addIdentity(identity) const raw = age.armor.decode(armored) const plaintext = await d.decrypt(raw, "text") console.log(plaintext) // "secret message" ``` -------------------------------- ### WebAuthn Recipient and Identity Source: https://context7.com/filosottile/typage/llms.txt Encrypt and decrypt using WebAuthn passkeys. This method prompts the user for biometric or PIN verification on every encrypt and decrypt call, ensuring no extractable key material is exposed. ```APIDOC ## Encrypt with a passkey ### Description Encrypts data using a WebAuthn Recipient, prompting the user for credential verification. ### Method `Encrypter.encrypt()` ### Parameters - `data` (string | Uint8Array): The data to encrypt. ### Request Example ```ts import * as age from "age-encryption" const e = new age.Encrypter() e.addRecipient(new age.webauthn.WebAuthnRecipient()) const ciphertext = await e.encrypt("browser-protected secret") const armored = age.armor.encode(ciphertext) ``` ## Decrypt with a passkey ### Description Decrypts data using a WebAuthn Identity, prompting the user for credential verification. ### Method `Decrypter.decrypt()` ### Parameters - `data` (Uint8Array): The encrypted data (decoded from armor). - `outputType` (string): The desired output type, e.g., "text". ### Request Example ```ts import * as age from "age-encryption" const d = new age.Decrypter() d.addIdentity(new age.webauthn.WebAuthnIdentity()) const decoded = age.armor.decode(armored) const plaintext = await d.decrypt(decoded, "text") console.log(plaintext) // "browser-protected secret" ``` ## Use a specific hardware security key identity ### Description Encrypts and decrypts data using a specific WebAuthn identity, identified by a string. ### Method `Encrypter.encrypt()` and `Decrypter.decrypt()` with `WebAuthnRecipient` and `WebAuthnIdentity` constructors accepting an `identity` option. ### Parameters - `identity` (string): The identifier for the specific hardware security key. ### Request Example ```ts // --- Use a specific hardware security key identity --- const hwKeyIdentity = "AGE-PLUGIN-FIDO2PRF-1Q9VGPY2E7S5FJJS3N7P03T..." const e2 = new age.Encrypter() e2.addRecipient(new age.webauthn.WebAuthnRecipient({ identity: hwKeyIdentity })) const ct2 = await e2.encrypt("hardware-key protected secret") const d2 = new age.Decrypter() d2.addIdentity(new age.webauthn.WebAuthnIdentity({ identity: hwKeyIdentity })) const pt2 = await d2.decrypt(ct2, "text") console.log(pt2) // "hardware-key protected secret" ``` ``` -------------------------------- ### Browser Encryption and Decryption with Age Source: https://github.com/filosottile/typage/blob/main/tests/examples/browser.html Generates an identity, creates a recipient, encrypts a message, and then decrypts it using the same identity. Ensure the 'age' library is loaded in the browser context. ```javascript (async () => { const identity = await age.generateIdentity() const recipient = await age.identityToRecipient(identity) console.log(identity) console.log(recipient) const e = new age.Encrypter() e.addRecipient(recipient) const ciphertext = await e.encrypt("Hello, age!") const d = new age.Decrypter() d.addIdentity(identity) const out = await d.decrypt(ciphertext, "text") console.log(out) globalThis.testDone = true })() ``` -------------------------------- ### Decrypter.decryptHeader() Source: https://context7.com/filosottile/typage/llms.txt Decrypts only the file header to retrieve the raw file key without processing the payload. Useful for delegated decryption. ```APIDOC ## `Decrypter.decryptHeader()` — Low-level detached header decryption ### Description Decrypts only the file header to retrieve the raw file key without processing the payload. Useful for delegated decryption architectures where the key material needs to be obtained separately from the streaming payload decryption. ### Method `Decrypter.decryptHeader(header: Uint8Array): Promise` ### Parameters - `header` (Uint8Array): The raw bytes of the file header, up to and including the MAC line. ### Response #### Success Response - `fileKey` (Uint8Array): The decrypted 16-byte file key. ### Request Example ```ts import { Decrypter } from "age-encryption" // Parse header only — obtain the file key const d = new Decrypter() d.addIdentity("AGE-SECRET-KEY-1...") // header is the raw bytes up to and including the MAC line const fileKey = await d.decryptHeader(header) // fileKey: Uint8Array(16) — use for custom payload decryption logic ``` ``` -------------------------------- ### Decrypter - Decrypt files with identities or passphrases Source: https://context7.com/filosottile/typage/llms.txt The Decrypter class allows decryption of files using configured identities or passphrases. It supports adding multiple identities and passphrases, and attempts decryption in parallel. The decrypt method can return plaintext as a string or a Uint8Array. ```APIDOC ## Decrypter ### Description Decrypt files with identities or passphrases. ### Methods - `addIdentity(identity: string | CryptoKey | Identity)`: Adds an identity for decryption. - `addPassphrase(passphrase: string)`: Adds a passphrase for decryption. - `decrypt(ciphertext: Uint8Array | ReadableStream, format?: "text"): Promise`: Decrypts the provided ciphertext. Returns a string if 'text' format is specified, otherwise returns a Uint8Array. ### Example Usage ```ts import { Decrypter } from "age-encryption" const d = new Decrypter() d.addIdentity("AGE-SECRET-KEY-1HRUMZM6XPUUTZ9VCAUM8P3SRMXH...") const plaintext = await d.decrypt(ciphertext, "text") console.log(plaintext) const bytes = await d.decrypt(ciphertext) console.log(new TextDecoder().decode(bytes)) ``` ``` -------------------------------- ### generateIdentity() Source: https://context7.com/filosottile/typage/llms.txt Generates a new random native age identity string (currently X25519). The returned string must be kept secret. Pass the result to identityToRecipient() to derive the shareable public recipient string. ```APIDOC ## generateIdentity() ### Description Generates a new random native age identity string (currently X25519). The returned string starts with `AGE-SECRET-KEY-1...` and must be kept secret. Pass the result to `identityToRecipient()` to derive the shareable public recipient string. ### Usage ```ts import * as age from "age-encryption" // Generate a new identity/recipient pair const identity = await age.generateIdentity() const recipient = await age.identityToRecipient(identity) console.log(identity) // AGE-SECRET-KEY-1HRUMZM6XPUUTZ9VCAUM8P3SRMXH... (keep secret) console.log(recipient) // age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmokasj (share this) ``` ``` -------------------------------- ### armor.encode() / armor.decode() - ASCII armor encoding Source: https://context7.com/filosottile/typage/llms.txt Provides functions to encode binary age ciphertext into a PEM-style ASCII armor block and decode it back. This is useful for safely transmitting ciphertext in text-based formats. ```APIDOC ## ASCII Armor Encoding ### Description Encode binary age ciphertext into ASCII armor and decode it back. ### Functions - `armor.encode(ciphertext: Uint8Array): string`: Wraps binary ciphertext in an ASCII armor block. - `armor.decode(armored: string): Uint8Array`: Decodes an ASCII armor block back into binary ciphertext. ### Example Usage ```ts import * as age from "age-encryption" const identity = await age.generateIdentity() const recipient = await age.identityToRecipient(identity) const e = new age.Encrypter() e.addRecipient(recipient) const ciphertext = await e.encrypt("secret message") // Encode to ASCII armor const armored = age.armor.encode(ciphertext) console.log(armored) // Decode and decrypt const d = new age.Decrypter() d.addIdentity(identity) const raw = age.armor.decode(armored) const plaintext = await d.decrypt(raw, "text") console.log(plaintext) // "secret message" ``` ``` -------------------------------- ### Browser Encryption with Security Keys Source: https://github.com/filosottile/typage/blob/main/README.md Encrypts a string using FIDO2 security keys in the browser. The identity string is mandatory for this type of credential. ```typescript const identity = await age.webauthn.createCredential({ type: "security-key", keyName: "age encryption key" }) console.log(identity) // AGE-PLUGIN-FIDO2PRF-1... const e = new age.Encrypter() e.addRecipient(new age.webauthn.WebAuthnRecipient({ identity: identity })) const ciphertext = await e.encrypt("Hello, age!") const armored = age.armor.encode(ciphertext) console.log(armored) ``` -------------------------------- ### Passphrase-Based Encryption Source: https://context7.com/filosottile/typage/llms.txt Encrypts data using a passphrase. Allows configuration of the scrypt work factor for trade-off between speed and security. Default work factor is 18. ```typescript import { Encrypter } from "age-encryption" // --- Passphrase-based encryption --- const ep = new Encrypter() ep.setScryptWorkFactor(14) // lower = faster but weaker; default is 18 ep.setPassphrase("burst-swarm-slender-curve-ability-various-crystal-moon") const ciphertextPass = await ep.encrypt(new TextEncoder().encode("secret data")) ``` -------------------------------- ### Stream Encryption and Decryption with age-encryption Source: https://context7.com/filosottile/typage/llms.txt Process large files efficiently using streams with Encrypter and Decrypter. Both methods return a stream that can calculate its expected output size. ```typescript import { Encrypter, Decrypter } from "age-encryption" // --- Stream encrypt a File --- const file = new File([new TextEncoder().encode("large file contents")], "data.txt") const e = new Encrypter() e.setScryptWorkFactor(12) e.setPassphrase("light-original-energy-average-wish-blind-vendor") const encryptedStream = await e.encrypt(file.stream()) // Pre-calculate output size without consuming the stream console.log("encrypted size:", encryptedStream.size(file.size), "bytes") // Pipe to a Response or another stream consumer const encryptedBlob = await new Response(encryptedStream).blob() // --- Stream decrypt --- const d = new Decrypter() d.addPassphrase("light-original-energy-average-wish-blind-vendor") const decryptedStream = await d.decrypt(encryptedBlob.stream()) console.log("plaintext size:", decryptedStream.size(encryptedBlob.size), "bytes") const text = await new Response(decryptedStream).text() console.log(text) // "large file contents" ``` -------------------------------- ### Generate Identity and Encrypt/Decrypt with Recipient Source: https://github.com/filosottile/typage/blob/main/README.md Generates a new identity, derives a recipient, and then encrypts a message. The message can then be decrypted using the generated identity. Ensure the identity is securely stored. ```ts import * as age from "age-encryption" const identity = await age.generateIdentity() const recipient = await age.identityToRecipient(identity) console.log(identity) console.log(recipient) const e = new age.Encrypter() e.addRecipient(recipient) const ciphertext = await e.encrypt("Hello, age!") const d = new age.Decrypter() d.addIdentity(identity) const out = await d.decrypt(ciphertext, "text") console.log(out) ``` -------------------------------- ### Browser Decryption with Passkeys Source: https://github.com/filosottile/typage/blob/main/README.md Decrypts an armored ciphertext using WebAuthn passkeys in the browser. Requires user confirmation via an authenticator. The identity string is optional if the passkey was generated by createCredential. ```typescript const d = new age.Decrypter() d.addIdentity(new age.webauthn.WebAuthnIdentity()) const decoded = age.armor.decode(armored) const out = await d.decrypt(decoded, "text") console.log(out) ``` -------------------------------- ### Encrypt/Decrypt using Streams API Source: https://github.com/filosottile/typage/blob/main/README.md Encrypts and decrypts data using the Streams API, suitable for large files or network data. Sets a scrypt work factor for passphrase-based encryption and uses a specific passphrase. The size of the encrypted stream is logged. ```ts import { Encrypter, Decrypter } from "age-encryption" const file = new File([new TextEncoder().encode("age")], "age.txt") const e = new Encrypter() e.setScryptWorkFactor(12) e.setPassphrase("light-original-energy-average-wish-blind-vendor-pencil-illness-scorpion") const encryptedStream = await e.encrypt(file.stream()) console.log(encryptedStream.size(file.size)) const d = new Decrypter() d.addPassphrase("light-original-energy-average-wish-blind-vendor-pencil-illness-scorpion") const decryptedStream = await d.decrypt(encryptedStream) console.log(decryptedStream.size(encryptedStream.size(file.size))) console.log(await new Response(decryptedStream).text()) ``` -------------------------------- ### Recipient-Based Encryption Source: https://context7.com/filosottile/typage/llms.txt Encrypts data for one or more recipients. Supports both classical X25519 and hybrid post-quantum recipients. ```typescript import { Encrypter } from "age-encryption" // --- Recipient-based encryption (multiple recipients) --- const e = new Encrypter() e.addRecipient("age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmokasj") e.addRecipient("age1pq1...") // also supports hybrid post-quantum recipients const ciphertext = await e.encrypt("Hello, age!") // ciphertext is Uint8Array ``` -------------------------------- ### Low-level Detached Header Decryption with Decrypter.decryptHeader() Source: https://context7.com/filosottile/typage/llms.txt Decrypt only the file header to obtain the raw file key without processing the payload. This is useful for delegated decryption architectures where key material is obtained separately from payload decryption. ```typescript import { Decrypter } from "age-encryption" // Parse header only — obtain the file key const d = new Decrypter() d.addIdentity("AGE-SECRET-KEY-1...") // header is the raw bytes up to and including the MAC line const fileKey = await d.decryptHeader(header) // fileKey: Uint8Array(16) — use for custom payload decryption logic ```