Skip to content

Repository files navigation

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.

About

Time Slice Based Encryption

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages