age-encryption
is a TypeScript
implementation of the age file encryption format.
It depends only on the noble cryptography libraries, and uses the Web Crypto API when available.
npm install age-encryption
age-encryption
is a modern ES Module, compatible with Node.js and Bun, with built-in types.
The whole API is documented with TypeDoc.
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)
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)
age-encryption
is compatible with modern bundlers such as esbuild.
To produce a classic library file that sets age
as a global variable, you can run
cd "$(mktemp -d)" && npm init -y && npm install esbuild age-encryption
npx esbuild --target=es6 --bundle --minify --outfile=age.js --global-name=age age-encryption
or download a pre-built one from the Releases page.
Then, you can use it like this
<script src="age.js"></script>
<script>
(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)
})()
</script>
You can use a CryptoKey as an identity. It must have an algorithm
of X25519
,
and support the deriveBits
key usage. It doesn't need to be extractable.
const keyPair = await crypto.subtle.generateKey({ name: "X25519" }, false, ["deriveBits"])
const identity = (keyPair as CryptoKeyPair).privateKey
const recipient = await age.identityToRecipient(identity)
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)
You can implement the Recipient
and Identity
interfaces to use custom types
as recipients and identities.
This lets you use use remote APIs and secrets managers to wrap files keys, and interoperate with age plugins.