an easy-to-use cryptography library inspired by age by Filippo Valsorda ( For non-streaming usecases where authentication is desired. A wrapper around libsodium to support encrypting to multiple recipients
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
forest b9e5accebf Update '' 1 year ago
node_modules first commit 2 years ago
readme adding Readme 2 years ago
.gitignore ignore build artifact 2 years ago Update '' 1 year ago
base58.d.ts cleaning up 1 year ago
index.ts cleaning up 1 year ago
package-lock.json first commit 2 years ago
package.json cleaning up 1 year ago
tsconfig.json first commit 2 years ago


An easy-to-use cryptography library slightly inspired by age by Filippo Valsorda (, but targeted at a different usecase:

For non-streaming encryption/decryption embedded inside an application. Usecases where the encrypted data is small, like less than a megabyte or so and it's not invoked directly on the command line by a user.

A wrapper around libsodium's functions:

The purpose of this library: to support encrypting the same file to multiple recipients using public-private-key cryptography, while also supporting the verification of the sender's signature.


getKeyPairFromPassphrase(usersPassphrase: string): libsodium.KeyPair

publicKeyToString(publicKey: Uint8Array): string

parsePublicKeyString(publicKeyString: string): Uint8Array

publicKeyToIdentityString(publicKey: Uint8Array): string

  plaintext: string, 
  senderCryptoSignKeyPair: libsodium.KeyPair, 
  recipientCryptoSignPublicKeys: Uint8Array[]
): EncryptedMessage

  message: EncryptedMessage, 
  myKeyPair: libsodium.KeyPair, 
  addressBook: AddressBook
): DecryptResult

Usage example:

  const aliceKeyPair = getKeyPairFromPassphrase("alice");
  const bobKeyPair = getKeyPairFromPassphrase("bob");
  const carolKeyPair = getKeyPairFromPassphrase("carol");
  const secretMessage = ` Yayyyy!!!! `;

  const encryptedMessage = createMessage(secretMessage, aliceKeyPair, [bobKeyPair.publicKey, carolKeyPair.publicKey]);

  console.log(JSON.stringify(encryptedMessage, null, "  "));

  const addressBook = {
    [publicKeyToIdentityString(aliceKeyPair.publicKey)]: aliceKeyPair.publicKey,
    [publicKeyToIdentityString(bobKeyPair.publicKey)]: bobKeyPair.publicKey,
    [publicKeyToIdentityString(carolKeyPair.publicKey)]: carolKeyPair.publicKey,

  const bobsDecryptedMessage = decryptMessage(encryptedMessage, bobKeyPair, addressBook);

  console.log("bob got: ", JSON.stringify(bobsDecryptedMessage, null, "  "));

  const carolsDecryptedMessage = decryptMessage(encryptedMessage, carolKeyPair, addressBook);

  console.log("carol got: ", JSON.stringify(carolsDecryptedMessage, null, "  "));

EncryptedMessage format

Alice encrypts a message for Bob and Carol.  The encrypted message has From, To, and Secret Box. From is the hash of alice's public Key. To is a list of Recipient stanzas. A recipient stanza has a Crypto Box. Only Carol's private key can open the Crypto Box in Carol's Recipient stanza. Inside the Crypto Box there is a Message Key. Alice generated the Message Key using a random number generator.  The Secret Box at the bottom of the Encrypted Message  can only be opened by the Message Key. Inside the Secret Box is Alice's Signature and the Plaintext. Alice generated this signature using her Private Key.   Carol uses her Private Key to open the Crypto Box inside her Recipient Stanza to obtain the Message Key. Then she opens the Secret Box using the Message Key. Finally, she uses Alice's Public key from her Address Book to verify Alice's Signature, and reads the Plaintext.

  "type": "authenticationage v1",
  "from": "identity_Fy8wD4wYU9mrTuoZKkL73d",
  "to": {
    "identity_L2qurUCyXj2QAnBxkWSKfq": {
      "nonce": "2XNTAPKhukOnxYIOxjYz8_toJBxJVS0S",
      "cryptoBox": "14IR-Qtt2p2IwVBK0rRAGdSrEVonpujo35sPvd9yUXy1RKJ5oB9plkib9mZKK76K"
    "identity_3iSrKmbtm9j41mARd6aAVA": {
      "nonce": "zr3iqJiAb9_u2WZIpRDXRC3OdOMu6YRN",
      "cryptoBox": "DoQ1x0ZF9BmSsxqRERgNjnJPNhJjGD4xqvHVZGcA49yMxYD9kWxEiyY6pIcCM7RA"
  "bodyNonce": "cUJZ1n3esN77cWSAjkZ6wNK9o-b2APt-",
  "bodySecretBox": [