npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@haskou/pigeon-swarm-crypto

v2.0.0

Published

Cryptographic primitives, key handling, and wire-format compatibility for Pigeon Swarm.

Readme

@haskou/pigeon-swarm-crypto

Cryptographic operations and serialized key formats used by Pigeon Swarm clients and relay nodes. The package owns signing, encryption, password-based key protection and digest computation. Generic value types remain in @haskou/value-objects.

Installation

yarn add @haskou/pigeon-swarm-crypto @haskou/value-objects@7

Import public APIs from the package root. Internal adapters are implementation details and are not exported.

Import the MLS lifecycle API from @haskou/pigeon-swarm-crypto/mls. That entry point provides separate ESM and bundled CommonJS builds for browser and Node.js consumers. Import UserRootKey from the package root so every component uses the same runtime constructor.

The package currently publishes CommonJS JavaScript and TypeScript declarations. It requires Node.js 20.20.2 or newer. Browser applications need a bundler with CommonJS and buffer support, and a secure context providing Web Crypto. Validate the resulting browser bundle; successful Node.js tests alone do not establish browser compatibility.

Signing and asymmetric encryption

import { KeyPair } from '@haskou/pigeon-swarm-crypto';

const recipient = await KeyPair.generate();
const signature = recipient.sign('message');
const verified = recipient.isValidSignature('message', signature);
const encrypted = recipient.encrypt('confidential message');
const plaintext = recipient.decrypt(encrypted).toString('utf8');

Keys use Ed25519 for signatures. Asymmetric encryption converts the recipient key to X25519 and combines ephemeral key agreement, HKDF-SHA-256 and AES-256-GCM. Applications must authenticate the recipient's public key and define a canonical signed message. Encryption to a public key does not authenticate the sender.

Symmetric encryption

import { SymmetricKey } from '@haskou/pigeon-swarm-crypto';

const key = SymmetricKey.generate();
const encrypted = key.encrypt('confidential message');
const plaintext = key.decrypt(encrypted).toString('utf8');

encrypt generates a fresh nonce and returns a versioned envelope. Keep the key separate from the ciphertext. When supplying application-specific authenticated data through aad, supply exactly the same bytes during decryption. Do not invent a new envelope or rename its version fields without a compatibility plan.

Protecting a private key

import {
  EncryptedPrivateKey,
  PrivateKey,
} from '@haskou/pigeon-swarm-crypto';

async function protectPrivateKey(privateKey: PrivateKey, password: string) {
  return EncryptedPrivateKey.create(privateKey, password);
}

async function unlockPrivateKey(serialized: string, password: string) {
  return new EncryptedPrivateKey(serialized).decrypt(password);
}

New protected keys use the v3 scrypt envelope. Existing supported envelopes remain readable. needsReEncryption() identifies older formats; callers decide when to replace stored data after a successful unlock. This package does not enforce an application password policy or provide account recovery.

Public API

| Responsibility | Exports | | --- | --- | | Keys and signatures | Key, PrivateKey, PublicKey, KeyPair, Signature | | Protected keys | EncryptedPrivateKey, EncryptedKeyPair, CryptoPassword | | Encrypted envelopes | EncryptedPayload, AsymmetricEncryptedPayload, SymmetricEncryptedPayload, EncryptedPayloadScheme | | Symmetric encryption | SymmetricKey, SymmetricKeyCryptOptions, SymmetricKeyDerivationOptions | | Digest computation | MD5Hash, SHA256Hash, SHA512Hash, HashPayload | | Public errors | InvalidKeyError, InvalidSignatureError, InvalidEncryptedPrivateKeyFormatError |

Digest classes expose .from(payload) for computation. The corresponding classes in value-objects validate an already-computed digest. With version 7, equality requires the same concrete type; use hasValue only when comparing the underlying digest across representations intentionally. MD5 is retained for compatibility, not for security-sensitive integrity or password storage.

Compatibility and security

See wire formats and migration before changing imports or persisted data, and SECURITY.md for security boundaries and reporting. See the key lifecycle review for current rotation gaps, the distinction between password re-encryption and key replacement, and the next integration milestone.

Moving encryption into this package does not provide forward secrecy, metadata privacy, anonymous communication or deletion of data already replicated through IPFS.

Private groups can use the MLS key lifecycle for independent device keys, epoch rotation, device removal, authenticated daily recipient HPKE schedules and root-key-protected persistence. The application must still authorize each control transition and atomically adopt its verified checkpoint with the matching MLS epoch and state commitment. Persist each one-use join package's packageId in rollback-resistant trusted state; restoration requires that exact checkpoint, and successful creation or joining must replace it with a consumed tombstone atomically with the new session.

Development

yarn install --frozen-lockfile
yarn lint
yarn test:coverage
yarn build

The test suite includes interoperability with the former UI and backend package versions, using their actual implementations. See CONTRIBUTING.md for validation and release requirements.

License

MIT. See LICENSE.txt.

Private-protocol signature verification is documented in Private operation signatures, including required application authorization and metadata-handling limits.

Private scope initialization

See private genesis signatures for the versioned, pinned-owner verification boundary shared by Node and browser clients. It does not change authorization of existing replicated data.

Subsequent private control signatures must satisfy the previous policy's quorum and sequencer before MLS processing.