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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@siwats/chronocrypt

v2.0.0

Published

Time-Based Granular Data Encryption System - A cryptographic library for temporal data access control

Downloads

265

Readme

ChronoCrypt

Asymmetric Time-Based Data Encryption System

A cryptographic library for temporal data access control with zero-knowledge authorization. ChronoCrypt uses asymmetric encryption (ECIES + AES-GCM) to enable data sources to encrypt temporal data streams while maintaining strong security properties even if the data source is compromised.

TypeScript Bun License: MIT

Security Model

ChronoCrypt implements an asymmetric three-party architecture where:

  • KeyHolder (Trusted Zone): Generates and holds the master private key, authorizes access by deriving time-specific private keys
  • DataSource (Untrusted Zone): Has only the public key, can encrypt but CANNOT decrypt
  • DataViewer (Controlled Zone): Receives time-specific private keys from KeyHolder for authorized decryption

Key Security Properties

DataSource Compromise Resistant: If the DataSource is compromised, attackers cannot decrypt any data (no private key) ✅ Temporal Binding: Timestamps are cryptographically bound via HKDF - tampering prevents decryption ✅ Authenticated Encryption: AES-256-GCM with authentication tags detect any data tampering ✅ Zero-Knowledge Authorization: KeyHolder authorizes access without seeing encrypted data content ✅ Granular Access Control: Authorization at timestamp-level precision with extensible policies ✅ Comprehensive Audit Trail: All operations logged for compliance and forensics

Features

  • Hybrid Asymmetric Encryption: ECIES (EC P-256) + AES-256-GCM
  • HKDF Temporal Binding: Timestamps cryptographically bound in key derivation
  • Three-Party Security Model: Separation between encryption, authorization, and decryption
  • Flexible Policy System: Extensible access control policies
  • Pluggable Storage: Use in-memory, filesystem, or any database (Prisma examples included)
  • Full TypeScript/Bun Support: Native async/await with Web Crypto API

Installation

bun add @siwats/chronocrypt

Quick Start

import {
  generateMasterKeypair,
  exportPublicKey,
  createDataSource,
  createKeyHolder,
  createDataViewer,
  InMemoryEncryptedRepository,
  InMemoryAuditLog,
  createAllowAllPolicy
} from '@siwats/chronocrypt';

// 1. KeyHolder: Generate master keypair (keep private key secure!)
const masterKeypair = await generateMasterKeypair();
const publicKey = await exportPublicKey(masterKeypair.publicKey);

// 2. Setup storage
const repository = new InMemoryEncryptedRepository();
const auditLog = new InMemoryAuditLog();

// 3. DataSource: Encrypt data (PUBLIC KEY ONLY - cannot decrypt!)
const dataSource = createDataSource(publicKey, repository);
const data = new TextEncoder().encode('Sensitive temporal data');
const encrypted = await dataSource.encryptData(data);

// 4. KeyHolder: Authorize access
const keyHolder = createKeyHolder(masterKeypair, auditLog, [createAllowAllPolicy()]);
const authResponse = await keyHolder.authorizeAccess({
  requesterId: 'analyst-001',
  timeRange: { startTime: encrypted.timestamp, endTime: encrypted.timestamp },
  purpose: 'Data analysis'
});

// 5. DataViewer: Decrypt with authorized time-specific keys
const dataViewer = createDataViewer('analyst-001', auditLog);
dataViewer.loadAuthorizedKeys(authResponse.privateKeys!);
const decrypted = await dataViewer.decryptFromRepository(repository, encrypted.timestamp);

console.log(new TextDecoder().decode(decrypted!.data));
// Output: "Sensitive temporal data"

Architecture Overview

┌─────────────────────────────────────────────────────────────────┐
│                         KeyHolder (Trusted)                      │
│  • Holds master private key                                     │
│  • Derives time-specific private keys                           │
│  • Enforces access control policies                             │
│  • Never sees encrypted data                                    │
└────────────────┬───────────────────────────────┬────────────────┘
                 │ Master Public Key             │ Time-Specific
                 ↓                               │ Private Keys
┌────────────────────────────┐                  ↓
│   DataSource (Untrusted)   │        ┌──────────────────────────┐
│  • Has PUBLIC key only     │        │  DataViewer (Controlled)  │
│  • Encrypts temporal data  │        │  • Receives authorized    │
│  • CANNOT decrypt          │        │    time-specific keys     │
│  • Stores encrypted data   │        │  • Decrypts only          │
└────────────────────────────┘        │    authorized data        │
                                      └──────────────────────────┘

Cryptographic Details

Encryption (DataSource)

  1. Generate random AES-256 symmetric key K
  2. Encrypt data: ciphertext = AES-256-GCM(K, data, IV)
  3. Generate ephemeral ECDH keypair (e_priv, e_pub)
  4. Perform ECDH: shared_secret = ECDH(e_priv, recipient_public)
  5. Derive wrapping key: wrap_key = HKDF(shared_secret, salt=timestamp, info='ChronoCrypt-Wrap-v1')
  6. Wrap symmetric key: wrapped_K = AES-KW(wrap_key, K)
  7. Package: {timestamp, wrapped_K, e_pub, ciphertext, IV, auth_tag}

Decryption (DataViewer)

  1. Perform ECDH: shared_secret = ECDH(time_specific_private, e_pub)
  2. Derive unwrapping key: unwrap_key = HKDF(shared_secret, salt=timestamp, info='ChronoCrypt-Wrap-v1')
  3. Unwrap symmetric key: K = AES-KW-UNWRAP(unwrap_key, wrapped_K)
  4. Decrypt data: data = AES-256-GCM-DECRYPT(K, ciphertext, IV, auth_tag)

Temporal Binding: The timestamp is used as salt in HKDF. Changing the timestamp in the encrypted package causes HKDF to derive a different key, making unwrapping fail.

Storage Options

ChronoCrypt provides flexible storage through simple interfaces. Choose the storage backend that fits your needs:

Built-in Storage

In-Memory (included) - Perfect for testing and development:

import { InMemoryEncryptedRepository, InMemoryAuditLog } from '@siwats/chronocrypt';

const repository = new InMemoryEncryptedRepository();
const auditLog = new InMemoryAuditLog();

Database Storage

Prisma (PostgreSQL/SQLite) - Production-ready database storage:

See examples/prisma/PRISMA_SETUP.md for complete setup guide with schema and implementation examples.

Custom Storage

Implement your own storage by following the interfaces:

import type { EncryptedDataRepository, AuditLogStorage } from '@siwats/chronocrypt';

class MyCustomRepository implements EncryptedDataRepository {
  async store(pkg: EncryptedPackage): Promise<void> { /* ... */ }
  async retrieve(timestamp: Timestamp): Promise<EncryptedPackage | null> { /* ... */ }
  async retrieveRange(range: TimeRange): Promise<EncryptedPackage[]> { /* ... */ }
  async exists(timestamp: Timestamp): Promise<boolean> { /* ... */ }
}

Access Control Policies

ChronoCrypt supports extensible access control policies. Currently implemented:

// Allow all requests (for development/testing)
createAllowAllPolicy()

// TODO: Additional policies coming soon
// - Requester whitelist
// - Time-based restrictions
// - Purpose validation
// - Maximum duration limits

Create custom policies by implementing the AccessControlPolicy interface:

const customPolicy: AccessControlPolicy = {
  id: 'my-policy',
  name: 'My Custom Policy',
  evaluate: async (request: AccessRequest) => {
    // Return true to allow, false to deny
    return request.requesterId.startsWith('trusted-');
  },
  priority: 100
};

Complete Example

See examples/complete-example.ts for a full IoT sensor data encryption workflow demonstrating:

  • Master keypair generation
  • DataSource encryption (untrusted zone)
  • KeyHolder authorization (trusted zone)
  • DataViewer decryption (controlled zone)
  • Audit log review
  • Security properties demonstration

Run the example:

bun run examples/complete-example.ts

Testing

Run the comprehensive test suite:

bun test

Test coverage includes:

  • Asymmetric key generation and derivation
  • Hybrid encryption/decryption (ECIES + AES-GCM)
  • Temporal binding via HKDF
  • Authentication failure detection
  • End-to-end workflows
  • Security property verification

API Reference

Core Cryptographic Functions

// Generate EC P-256 master keypair
generateMasterKeypair(): Promise<MasterKeypair>

// Export/import public key (JWK format)
exportPublicKey(publicKey: CryptoKey): Promise<ExportedPublicKey>
importPublicKey(jwk: ExportedPublicKey): Promise<CryptoKey>

// Derive time-specific private key
deriveTimeSpecificPrivateKey(
  masterPrivateKey: CryptoKey,
  timestamp: Timestamp
): Promise<TimeSpecificPrivateKey>

// Hybrid encryption/decryption
encryptData(
  data: Uint8Array,
  recipientPublicKey: ExportedPublicKey,
  timestamp: Timestamp,
  metadata?: Record<string, unknown>
): Promise<EncryptedPackage>

decryptData(
  pkg: EncryptedPackage,
  timeSpecificPrivateKey: TimeSpecificPrivateKey
): Promise<Uint8Array>

Entity Creation

// Create DataSource (receives public key only)
createDataSource(
  publicKey: ExportedPublicKey,
  repository: EncryptedDataRepository,
  timestampGenerator?: () => Timestamp
): DataSource

// Create KeyHolder (holds private key)
createKeyHolder(
  masterKeypair: MasterKeypair,
  auditLog: AuditLogStorage,
  policies?: AccessControlPolicy[],
  keyHolderId?: string
): KeyHolder

// Create DataViewer
createDataViewer(
  viewerId: string,
  auditLog?: AuditLogStorage
): DataViewer

Security Considerations

Key Management

  • Master Private Key: Must be stored securely (HSM, secure enclave, etc.)
  • Public Key: Can be distributed to untrusted DataSources
  • Time-Specific Keys: Temporary, can be destroyed after use
  • Key Rotation: Generate new master keypair periodically

Threat Model

Protected Against:

  • DataSource compromise (no decryption capability)
  • Timestamp tampering (KDF binding)
  • Data tampering (GCM authentication)
  • Unauthorized decryption (requires KeyHolder authorization)

⚠️ Not Protected Against:

  • Master private key compromise (grants access to all time periods)
  • KeyHolder compromise (can authorize any access)
  • Side-channel attacks (timing, power analysis)

Best Practices

  1. Separate environments: Run KeyHolder in isolated, highly secure environment
  2. Limit DataSource privileges: DataSources should only have public key and repository access
  3. Audit log review: Regularly review audit logs for suspicious access patterns
  4. Key rotation: Implement periodic master keypair rotation
  5. Policy enforcement: Use strict access control policies in production

Contributing

Contributions welcome! Please ensure:

  • All tests pass (bun test)
  • Code follows existing style
  • Security-sensitive changes include threat model analysis

License

MIT

Acknowledgments

ChronoCrypt implements industry-standard cryptographic primitives:

  • ECIES: Elliptic Curve Integrated Encryption Scheme
  • ECDH: Elliptic Curve Diffie-Hellman (P-256/secp256r1)
  • HKDF: HMAC-based Key Derivation Function (RFC 5869)
  • AES-GCM: Advanced Encryption Standard - Galois/Counter Mode
  • AES-KW: AES Key Wrap (RFC 3394)

All cryptographic operations use the Web Crypto API for security and performance.