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

crypthold

v2.2.1

Published

Secure encrypted config store for Node.js (HKDF, key rotation, lockfile concurrency, atomic writes).

Readme

Crypthold

Secure, hardened, atomic configuration store for Node.js applications.

npm License: Apache-2.0

Crypthold is a production-grade configuration substrate designed for high-integrity environments. It provides tamper-evident storage, cross-process safety, and seamless key management.

Features

  • Hardened Security: AES-256-GCM encryption with HKDF-SHA256 key derivation.
  • Integrity First: SHA-256 content hashing prevents silent external tampering.
  • Concurrency Safe: Robust cross-process locking (.lock) with automatic stale recovery.
  • Reactive: Live configuration watching with debounced callbacks.
  • Key Lifecycle: Native rotation support and multi-key fallback decryption.
  • Production Ready: Atomic writes, fsync support, and comprehensive diagnostic reports.
  • OS Keychain: Native integration via @napi-rs/keyring.

Installation

npm install crypthold

Quick Start

import { Crypthold } from 'crypthold'

const store = new Crypthold({ appName: 'my-app' })

// Initialize (once) or Load
await store.load()

// Set and Persist
await store.set('db_password', 'secret123')

// Get with Types
const pass = store.get<string>('db_password')

Advanced Usage

Reactive Configuration

Watch for external changes (e.g., manual file edits or other processes):

store.watch(
  (data) => {
    console.log('Config updated:', data)
  },
  { debounceMs: 50 },
)

deterministicSeed is intended for tests only and now throws outside NODE_ENV=test.

Key Rotation

Transition to a new master key without data loss:

await store.rotate('new-64-char-hex-key')

Diagnostics (Doctor)

Check the health and integrity of your configuration store:

const report = await store.doctor()
// { keyPresent: true, integrityOk: true, permissionsOk: true, lockExists: false ... }

Durability

Ensures data is physically written to disk (useful for high-stakes environments):

const store = new Crypthold({
  appName: 'my-app',
  durability: 'fsync',
})

Ensures data is physically written to disk (useful for high-stakes environments):

const store = new Crypthold({
  appName: 'my-app',
  encryptionKeyEnvVar: 'CRYPTHOLD_KEY',
})
await store.load()

Examples

The examples/ directory contains detailed demonstration scripts for advanced scenarios:

  • Key Lifecycle: Demonstrates multi-key fallback decryption and atomic key rotation.
  • DX & Safety: Shows usage of the doctor() diagnostic report, watch() for live updates, and encrypted import/export.
  • Durability & Tests: Covers fsync durability modes, optimistic concurrency conflict detection, and deterministic test mode.

Run any example with:

npm run build
node --experimental-strip-types examples/filename.ts

API Reference

new Crypthold(options)

| Option | Type | Description | | :----------------------- | :----------------------- | :------------------------------------------------------- | | appName | string | Required. Service name for Keychain and AAD context. | | configPath | string | Custom path for the encrypted store file. | | encryptionKeyEnvVar | string | Env var name for the primary master key. | | encryptionKeySetEnvVar | string | Env var for multi-key sets (id1:hex,id2:hex). | | maxFileSizeBytes | number | Limit to prevent memory blow (default: 10MB). | | durability | "normal" \| "fsync" | Atomic write strategy (default: "normal"). | | lockTimeoutMs | number | Max wait time for lock acquisition (default: 5s). | | conflictDetection | "strict" \| "metadata" | Conflict check mode (strict default). |

Methods

| Method | Description | | :---------------------- | :------------------------------------------------------------ | | init() | Generates a new master key in the keychain. | | load() | Loads and decrypts the store. Supports legacy migration. | | get<T>(key) | Retrieves a value from memory cache. | | set(key, value) | Updates memory cache and persists atomically. | | rotate(newKey?) | Re-encrypts the entire store with a new key. | | watch(callback) | Starts watching for file changes. Returns unwatch function. | | doctor() | Performs diagnostic checks on keys and file integrity. | | exportEncrypted(path) | Safely clones the encrypted store. | | importEncrypted(path) | Loads an external store into the local substrate. |

Error Codes

| Code | Description | | :------------------------- | :------------------------------------------------------------ | | CRYPTHOLD_INTEGRITY_FAIL | Decryption or AAD verification failed (Tampering detected). | | CRYPTHOLD_CONFLICT | File changed externally during a write (Hash/mtime mismatch). | | CRYPTHOLD_LOCK_TIMEOUT | Failed to acquire process lock within timeout. | | CRYPTHOLD_FILE_TOO_LARGE | Store exceeds maxFileSizeBytes limit. | | CRYPTHOLD_KEY_NOT_FOUND | Master key is missing from environment/keychain. | | CRYPTHOLD_UNSAFE_OPTION | A test-only option was used in a non-test environment. |

Security

  • Encryption: AES-256-GCM with 96-bit random IV (NIST SP 800-38D).
  • Key Derivation: HKDF-SHA256 ensures key separation for every write.
  • Binding: AAD (Additional Authenticated Data) binds ciphertext to your appName.
  • Permissions: Enforces 0600 (Owner Read/Write) on Unix-like systems.

License

Apache-2.0