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

@darkbio/crypto

v0.19.1

Published

Cryptography primitives and wrappers

Readme

Post-Quantum Cryptography in TypeScript

npm tests License: BSD-3-Clause

This repository is parameter selection and lightweight wrapper around a number of (WASM wrapped) Rust cryptographic libraries. Its purpose isn't to implement primitives, rather to unify the API surface of existing libraries; limited to the tiny subset needed by the Dark Bio project.

The library is opinionated. Parameters and primitives were selected to provide matching levels of security in a post-quantum world. APIs were designed to make the library easy to use and hard to misuse. Flexibility will always be rejected in favor of safety.

  • Digital signatures
  • Encryption
    • xHPKE (RFC-9180): X-WING, HKDF, SHA256, ChaCha20, Poly1305, dark-bio-v1: domain prefix
    • STREAM (RFC N/A, Rage): ChaCha20, Poly1305, 16B tag, 64KB chunk
  • Key derivation
  • Serialization
    • CBOR² (RFC-8949): restricted to bool,null, integer, text, bytes, array, map[int], option
    • COSE (RFC-9052): COSE_Sign1, COSE_Encrypt0, dark-bio-v1: domain prefix
  • Credential / Attestation

¹ Whilst RSA is used in the Dark Bio project for secure boot signatures on pre-quantum hardware, there was no reason to expose that in the TypeScript wrappers. It's available in Rust so anyone needing it can expose it easily themselves.

² CBOR encoding and decoding is delegated to cborg, a full reimplementation in TypeScript being out of scope. To ensure correctness, this package provides a type system. cbor codecs declare the shape of a value the way a Rust type deriving Cbor does, cose and cwt functions take values bound to their codec, and the canonical form of every byte crossing the WASM boundary is checked by the Rust validator, which cbor.verify also exposes.

Quick start

Signatures come from xdsa, encryption from xhpke, and cose wraps both into COSE envelopes using the Dark Bio wire profile. Payloads and authenticated messages are bound to a cbor codec, which declares their shape.

npm install @darkbio/crypto

COSE signing and verification and xHPKE encryption and decryption use an application domain that both sides must agree on. It is prefixed with dark-bio-v1: internally and binds the operation to one purpose. Choose distinct domains for distinct purposes. Raw xdsa signatures carry no such application domain, which is why the cose envelopes are the recommended entry point.

import { cbor, cose, xdsa, xhpke } from "@darkbio/crypto";

// Long term identities, one for signing and one for receiving
const signer = await xdsa.SecretKey.generate();
const recipient = await xhpke.SecretKey.generate();
const domain = new TextEncoder().encode("example");

// A detached signature over a message that travels separately
const signature = await cose.signDetached(cbor.text.value("payload"), signer, domain);
await cose.verifyDetached(signature, cbor.text.value("payload"), signer.publicKey(), domain, 60);

// Sign and encrypt a payload to the recipient, then open and verify it back.
// The second argument is authenticated but must be supplied separately.
const metadata = cbor.text.value("metadata");
const sealed = await cose.seal(cbor.text.value("payload"), metadata, signer, recipient.publicKey(), domain);
const opened = await cose.open(cbor.text.bytes(sealed), metadata, recipient, signer.publicKey(), domain, 60);

Native packages

The underlying implementation exists in two sibling repos, which track the same feature set and API surfaces, released at corresponding version points.

Sibling wrapper exists in one other repo:

Acknowledgements

Shoutout to Filippo Valsorda (@filosottile) for lots of tips and nudges on what kind of cryptographic primitives to use and how to combine them properly; and also for his work in general on cryptography standards.

Naturally, many thanks to the authors of all the libraries this project depends on.

License

This library is licensed under the BSD 3-Clause License.