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

@enc-protocol/core

v0.9.0

Published

ENC Protocol core — app-agnostic protocol primitives (crypto, events, RBAC, SMT, CT). No app encryption (see @enc-protocol/plugin-*).

Readme

@enc-protocol/core

ENC Protocol core cryptographic and protocol primitives — secp256k1 signatures (Schnorr + ECDSA), hashing, ECDH, AEAD encryption, Merkle trees (SMT + CT), RBAC, events, and session management. Generated from Lean 4 DSL verified specification.

Install

npm install @enc-protocol/core

API

Cryptographic Hashing

  • sha256Hash(data: Uint8Array): Uint8Array — SHA-256 digest of bytes.
  • sha256Str(str: string): Uint8Array — SHA-256 digest of a UTF-8 string.
  • domainHash(prefix: number, data: Uint8Array): Uint8Array — Domain-separated SHA-256 hash with byte prefix.
  • taggedHash(tag: string, data: Uint8Array): Uint8Array — BIP-340 style tagged hash.
  • eip191Hash(msg: string): Uint8Array — Ethereum signed message hash (EIP-191).

Merkle Tree Hashing

  • ctLeafHash(eventsRoot: Uint8Array, stateHash: Uint8Array): Uint8Array — CT leaf hash (events + state).
  • ctNodeHash(left: Uint8Array, right: Uint8Array): Uint8Array — CT inner node hash.
  • smtLeafHash(key: Uint8Array, value: Uint8Array): Uint8Array — SMT (Poseidon2) leaf hash.
  • smtNodeHash(left: Uint8Array, right: Uint8Array): Uint8Array — SMT (Poseidon2) inner node hash.
  • computeEventsRoot(eventIds: string[]): Uint8Array — Merkle root from event ID hex strings.

Commitment Hashing

  • computeContentHash(content: string): Uint8Array — SHA-256 of content string.
  • computeCommitHash(contentHash: string, enclave: string, from: string, type: string, exp: number, tags: string[][]): Uint8Array — Commit hash with CBOR encoding.
  • computeEventHash(seq: number, sequencer: string, sig1: string, timestamp: number): Uint8Array — Event hash (sequencer record).
  • computeEnclaveId(from: string, type: string, contentHash: string, tags: string[][]): Uint8Array — Enclave ID from manifest.
  • computeEventId(sig2Hex: string): Uint8Array — Event ID from seq signature.

Key Derivation & Sessions

  • derivePublicKey(privateKey: Uint8Array): Uint8Array — secp256k1 compressed public key (32 bytes, x-only).
  • derivePublicKeyCompressed(privateKey: Uint8Array): Uint8Array — secp256k1 compressed public key (33 bytes with prefix).
  • derivePublicKeyUncompressed(privateKey: Uint8Array): Uint8Array — secp256k1 uncompressed public key (65 bytes).
  • generateKeypair(): {privateKey: Uint8Array, publicKey: Uint8Array} — Generate random secp256k1 keypair.
  • deriveKey(shared: Uint8Array, label: string): Uint8Array — HKDF-SHA256 with label; returns 32 bytes.
  • generateSession(idPriv: Uint8Array, duration?: number, now: number): {session: string, sessionPriv: Uint8Array, expires: number} — Create BIP-340 delegated session.
  • verifySession(session: string, fromPubHex: string, now: number): string | null — Verify session; returns error string or null if valid.

Signing & Verification (Schnorr)

  • schnorrSign(msgHash: Uint8Array, privateKey: Uint8Array): Uint8Array — secp256k1 Schnorr (BIP-340) signature.
  • schnorrVerify(msgHash: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): boolean — Verify Schnorr signature.
  • signSTH(t: number, ts: number, rootHash: Uint8Array): string — Sign Signed Tree Head; calls globalThis.__encSequencerSigner.
  • verifySTH(t: number, ts: number, rootHash: Uint8Array, sigHex: string, seqPub: Uint8Array): boolean — Verify STH signature (requires sequencer public key).

Signing & Verification (ECDSA)

  • ecdsaSign(msgHash: Uint8Array, privateKey: Uint8Array): Uint8Array — secp256k1 ECDSA signature.
  • ecdsaVerify(msgHash: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): boolean — Verify ECDSA signature.
  • ecdsaVerifyPrehashed(msgHash: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): boolean — Verify pre-hashed ECDSA signature.
  • ecdsaRecover(msgHash: Uint8Array, signature: Uint8Array, recovery: number): Uint8Array — Recover secp256k1 public key from ECDSA sig.

Subkey Certificates

  • verifySubkeyCert(cert: {subkey: string, parentId: string, expiry: number, ackSig: string, authSig: string}, commitFrom: string, now: number): string | null — Verify subkey cert; returns error string or null if valid.
  • verifyDelegatedSession(sessionPub: Uint8Array, expires: number, authSig: string, recovery: number, fromPubHex: string, now: number): string | null — Verify delegated session authorization.
  • deriveSignerPriv(sessionPriv: Uint8Array, sessionPub: Uint8Array, seqPub: Uint8Array, enclaveId: string): Uint8Array — Derive signer private key from session + sequencer.
  • deriveSignerPub(sessionPub: Uint8Array, seqPub: Uint8Array, enclaveId: string): Uint8Array — Derive signer public key from session + sequencer.

ECDH & Shared Secrets

  • ecdh(privKey: Uint8Array, pubKey: Uint8Array): Uint8Array — secp256k1 ECDH; returns x-coordinate (32 bytes).

AEAD Encryption (XChaCha20-Poly1305)

  • encrypt(key: Uint8Array, plaintext: string): string — Encrypt string; returns base64 (nonce + ciphertext).
  • decrypt(key: Uint8Array, ciphertextB64: string): string — Decrypt base64; returns plaintext string.
  • encryptSeparated(key: Uint8Array, plaintext: string): {ciphertext: string, nonce: string} — Encrypt; returns hex nonce + ciphertext.
  • decryptSeparated(key: Uint8Array, ciphertextHex: string, nonceHex: string): string — Decrypt hex ciphertext + nonce.
  • encryptBytes(key: Uint8Array, plaintextBytes: Uint8Array): string — Encrypt bytes; returns hex.
  • decryptBytes(key: Uint8Array, combinedHex: string): Uint8Array — Decrypt hex to bytes.
  • encryptSeparatedBytes(key: Uint8Array, plaintextBytes: Uint8Array): {ciphertext: string, nonce: string} — Encrypt bytes; returns hex nonce + ciphertext.
  • decryptSeparatedBytes(key: Uint8Array, ciphertextHex: string, nonceHex: string): Uint8Array — Decrypt hex bytes.
  • encryptSeparatedWithNonce(key: Uint8Array, plaintext: string, nonce: Uint8Array): {ciphertext: string, nonce: string} — Deterministic encrypt with provided nonce.
  • encryptSeparatedBytesWithNonce(key: Uint8Array, plaintextBytes: Uint8Array, nonce: Uint8Array): {ciphertext: string, nonce: string} — Deterministic byte encrypt.

AEAD Encryption (ChaCha20-Poly1305)

  • aeadChachaEncrypt(key: Uint8Array, plaintextBytes: Uint8Array): {ciphertext: string, nonce: string} — Encrypt bytes with 12-byte nonce; returns hex.
  • aeadChachaDecrypt(key: Uint8Array, ciphertextHex: string, nonceHex: string): Uint8Array — Decrypt hex ciphertext + 12-byte nonce.

Stream Ciphers & MAC

  • chacha20Stream(key: Uint8Array, nonce: Uint8Array, data: Uint8Array): Uint8Array — ChaCha20 stream cipher (no auth).
  • hmacSha256(key: Uint8Array, msg: Uint8Array): Uint8Array — HMAC-SHA256.

HKDF

  • hkdfExtract(ikm: Uint8Array, salt?: Uint8Array): Uint8Array — HKDF extract phase (SHA-256).
  • hkdfExpand(prk: Uint8Array, info: Uint8Array, length: number): Uint8Array — HKDF expand phase.

Encoding & Random

  • bytesToHex(bytes: Uint8Array): string — Convert bytes to lowercase hex.
  • hexToBytes(hex: string): Uint8Array — Parse hex (with optional 0x prefix) to bytes.
  • base64Encode(bytes: Uint8Array): string — Base64 encode.
  • base64Decode(str: string): Uint8Array — Base64 decode.
  • csprngBytes(n: number): Uint8Array — Generate n random bytes.
  • reduceScalar(bytes: Uint8Array): Uint8Array — Reduce 32 bytes to valid secp256k1 scalar.
  • cborHead(major: number, n: number): Uint8Array — CBOR major type + value encoding.

Events & Commits

  • mkCommit(enclave: string, from: string, type: string, content: string, exp: number, tags: string[][]): Commit — Create unsigned commit.
  • signCommit(commit: Commit, privateKey: Uint8Array): Commit — Add Schnorr signature to commit.
  • mkManifestCommit(from: string, manifestContent: string, exp: number, tags: string[][]): Commit — Create + hash manifest commit.
  • verifyCommit(commit: Commit, now: number): boolean — Verify commit signature (Schnorr or ECDSA).
  • finalizeCommit(commit: Commit, timestamp: number, seq: number, sequencerPubHex: string): Event — Add sequencer data; calls globalThis.__encSequencerSigner.
  • verifyEvent(event: Event, now: number): boolean — Verify full event (commit + sequencer sig).
  • mkReceipt(event: Event): Receipt — Extract receipt fields from event.
  • validateCommitStructure(commit: Commit): string | null — Check commit hash matches fields.
  • isACEvent(type: string): boolean — Check if type is AC event (Grant, Revoke, etc.).
  • isLifecycleEvent(type: string): boolean — Check if type is lifecycle (Pause, Resume, Terminate, Migrate).
  • canUpdateDelete(type: string): boolean — Check if type is Update or Delete.

Role-Based Access Control (RBAC)

  • getState(bitmask: bigint): number — Extract state bits (0–255).
  • setState(bitmask: bigint, stateValue: number): bigint — Set state bits.
  • isOutsider(bitmask: bigint): boolean — State is 0 (no membership).
  • hasTrait(bitmask: bigint, traitBit: number): boolean — Check if trait bit is set.
  • setTrait(bitmask: bigint, traitBit: number): bigint — Set trait bit.
  • clearTrait(bitmask: bigint, traitBit: number): bigint — Clear trait bit.
  • isOwner(mask: bigint): boolean — Check owner trait (bit 8).
  • bestRank(mask: bigint, traitRanks: [number, number][]): number — Find best rank from trait + rank tuples.
  • clearAllTraits(bitmask: bigint): bigint — Keep state, clear all traits.
  • isAuthorized(schema: RBACRule[], bitmask: bigint, eventType: string, op: string, isSelf?: boolean, isSender?: boolean, stateNames?: string[], traitNames?: string[]): boolean — Check if bitmask+role permits operation.
  • getCustomRoleNames(schema: RBACRule[]): string[] — Extract non-context roles from schema.
  • roleBitFromName(name: string, customRoles: string[]): number | null — Get trait bit for custom role.
  • RBACState.getRoles(identity: string): bigint — Get role bitmask for identity.
  • RBACState.setRoles(identity: string, mask: bigint): void — Set role bitmask.
  • RBACState.grantRole(identity: string, bit: number): void — Set trait bit.
  • RBACState.revokeRole(identity: string, bit: number): void — Clear trait bit.
  • RBACState.revokeAll(identity: string): void — Delete all roles.
  • RBACState.markDeleted(eventId: string): void — Mark event as deleted.
  • RBACState.markUpdated(targetId: string, updateId: string): void — Mark as updated by updateId.
  • RBACState.getEventStatus(eventId: string): string — Get status: 'Active' | 'Deleted' | updateId.
  • RBACState.applyInitialState(initialState: object, schema: RBACRule[], stateNames: string[], traitNames: string[]): void — Populate roles from initialState object.

Sparse Merkle Tree (SMT)

  • buildSMTKey(namespace: number, rawKey: Uint8Array): Uint8Array — Build 21-byte SMT key (1-byte namespace + 20-byte hash).
  • buildRBACKey(identityHex: string): Uint8Array — SMT key for RBAC (namespace 0).
  • buildEventStatusKey(eventIdHex: string): Uint8Array — SMT key for event status (namespace 1).
  • buildKVKey(kvKey: string, identity?: string): Uint8Array — SMT key for KV state (namespace 2).
  • encodeRoleBitmask(bitmask: bigint): Uint8Array — Encode bitmask as 32 bytes.
  • decodeRoleBitmask(bytes: Uint8Array): bigint — Decode 32 bytes to bitmask.
  • encodeEventStatus(status: string): Uint8Array — Encode status string/hex.
  • proofToWire(proof: SMTProof): object — Convert proof to JSON wire format.
  • wireToProof(wire: object): SMTProof — Parse wire format to proof.
  • SparseMerkleTree.verify(proof: SMTProof, expectedRoot: Uint8Array): boolean — Verify 168-bit SMT inclusion proof.
  • SparseMerkleTree.getRoot(): Uint8Array — Get current Merkle root.
  • SparseMerkleTree.getRootHex(): string — Get root as hex.
  • SparseMerkleTree.insert(key: Uint8Array, value: Uint8Array): void — Insert/update leaf.
  • SparseMerkleTree.remove(key: Uint8Array): void — Remove leaf.
  • SparseMerkleTree.get(key: Uint8Array): Uint8Array | null — Fetch leaf value.
  • SparseMerkleTree.prove(key: Uint8Array): SMTProof — Generate inclusion proof.
  • SparseMerkleTree.serialize(): object — Serialize to JSON.
  • SparseMerkleTree.deserialize(data: object): void — Restore from JSON.

Certificate Transparency (CT)

  • verifyInclusionProof(leafHash: Uint8Array, leafIndex: number, treeSize: number, path: Uint8Array[], expectedRoot: Uint8Array): boolean — Verify RFC 9162 inclusion proof.
  • verifyConsistencyProof(size1: number, size2: number, path: Uint8Array[], firstRoot: Uint8Array, secondRoot: Uint8Array): boolean — Verify RFC 9162 consistency proof.
  • bundleMembershipProof(eventIds: string[], eventIndex: number): {ei: number, s: string[]} — Generate bundle proof (binary tree siblings in hex).
  • verifyBundleMembership(eventIdHex: string, proof: {ei: number, s: string[]}, expectedRootHex: string): boolean — Verify event in bundle.
  • CTTree.getRoot(): Uint8Array — Get current tree root.
  • CTTree.getRootHex(): string — Get root as hex.
  • CTTree.append(eventsRoot: Uint8Array, stateHash: Uint8Array): number — Add leaf; returns index.
  • CTTree.inclusionProof(leafIndex: number): {ts: number, li: number, p: string[]} — Generate inclusion proof.
  • CTTree.consistencyProof(size1: number, size2?: number): {ts1: number, ts2: number, p: string[]} — Generate consistency proof.
  • CTTree.serialize(): string[] — Serialize to hex strings.
  • CTTree.deserialize(data: string[]): void — Restore from hex strings.

Type Constants

  • Context — Object with context role values: Self, Sender, Public.
  • Op — Enum of CRUD operations: C, R, U, D, P, N and negations _C, _R, _U, _D, _P, _N.
  • ACEventType — Array of AC event type strings: Manifest, Grant, Revoke, Move, Transfer, Gate, Shared, Own, AC_Bundle, Pause, Resume, Terminate, Migrate.
  • EventStatus — Enum: Active, Deleted, Updated.
  • SMTNamespace — Enum: RBAC (0), EventStatus (1), KVState (2).
  • LifecycleState — Enum: Active, Paused, Terminated, Migrating.

Constants

  • DOMAIN_CT_LEAF, DOMAIN_CT_NODE, DOMAIN_COMMIT, DOMAIN_EVENT, DOMAIN_ENCLAVE, DOMAIN_SMT_LEAF, DOMAIN_SMT_NODE — Domain separators for hashing.
  • SMT_EMPTY_HASH — Pre-computed empty leaf hash (SMT root for no entries).
  • MAX_EXP_WINDOW, CLOCK_SKEW_TOLERANCE — Event timing constants (milliseconds).

Additional Modules (via subpath exports)

  • @enc-protocol/core/dm-ratchet.js — Double-ratchet message key derivation + NIP-44 compatibility (padding, HMAC).
  • @enc-protocol/core/ecdh-envelope.js — One-shot sender→recipient confidentiality for personal notices and group invites.
  • @enc-protocol/core/identity-aead.js — Deterministic identity-based AEAD for personal private content.
  • @enc-protocol/core/mls-lazy.js — Binary ratchet tree group crypto (O(log N) epoch distribution).

Example

import {
  generateKeypair,
  schnorrSign,
  schnorrVerify,
  sha256Hash,
  bytesToHex,
  hexToBytes,
  mkCommit,
  signCommit,
  verifyCommit,
  deriveKey,
  encrypt,
  decrypt,
  SparseMerkleTree,
  buildRBACKey,
  RBACState,
  encodeRoleBitmask,
  CTTree
} from '@enc-protocol/core'

// Generate a keypair
const { privateKey, publicKey } = generateKeypair()

// Create and sign a commit
const commit = mkCommit(
  'enclave123',
  bytesToHex(publicKey),
  'Manifest',
  'some policy content',
  Math.floor(Date.now() / 1000) + 3600,
  [['env', 'prod']]
)
const signed = signCommit(commit, privateKey)

// Verify the signature
const now = Math.floor(Date.now() / 1000)
const isValid = verifyCommit(signed, now)
console.log('Commit valid:', isValid)

// Derive an encryption key and encrypt
const shared = new Uint8Array(32)
crypto.getRandomValues(shared)
const key = deriveKey(shared, 'my-label')
const encrypted = encrypt(key, 'secret message')
const decrypted = decrypt(key, encrypted)
console.log('Decrypted:', decrypted)

// Use Sparse Merkle Tree for RBAC state
const smt = new SparseMerkleTree()
const identityKey = buildRBACKey(bytesToHex(publicKey))
const roleMask = encodeRoleBitmask(0x0103n) // state=3, owner bit set
smt.insert(identityKey, roleMask)

const proof = smt.prove(identityKey)
const isIncluded = SparseMerkleTree.verify(proof, smt.getRoot())
console.log('SMT proof verified:', isIncluded)

// Build a Certificate Transparency tree
const ct = new CTTree()
const eventsRoot = sha256Hash(new TextEncoder().encode('events'))
const stateHash = sha256Hash(new TextEncoder().encode('state'))
const leafIndex = ct.append(eventsRoot, stateHash)
console.log('CT leaf index:', leafIndex)
console.log('CT root:', ct.getRootHex())