Cryptographic operations for CryptForge applications - supports both client and server environments
npm install @cryptforge/cryptographyCryptographic operations for CryptForge applications with support for both client (browser) and server (Node.js) environments.
- š Encryption & Decryption: Symmetric and asymmetric encryption operations
- š Cross-Platform: Separate implementations for browser and Node.js environments
- š Key Management: Utilities for key generation, derivation, and storage
- š”ļø Type-Safe: Full TypeScript support with comprehensive type definitions
- š¦ Tree-Shakeable: Optimized bundle sizes with separate entry points
``bash`
npm install @cryptforge/cryptography
The client export provides CryptoBrowser, which uses the Web Crypto API for encryption/decryption:
`typescript
import { CryptoBrowser } from '@cryptforge/cryptography';
import { createAuthClient } from '@cryptforge/auth';
// Create auth client and unlock wallet
const auth = createAuthClient();
await auth.unlock({ password: 'your-password', chainId: 'ethereum' });
// Derive encryption key from wallet
const encryptionKey = await auth.deriveDataEncryptionKey({
purpose: 'my-app-data',
version: 1,
});
// Create CryptoBrowser instance
const crypto = new CryptoBrowser();
crypto.setEncryptionKey(encryptionKey);
// Encrypt data
const encrypted = await crypto.encrypt()('Hello, World!');
console.log('Encrypted:', encrypted); // Base64-encoded string
// Decrypt data
const decrypted = await crypto.decrypt()(encrypted);
console.log('Decrypted:', decrypted); // "Hello, World!"
`
`typescript
import { CryptoBrowser } from '@cryptforge/cryptography';
// Create instance with dynamic key retrieval
const crypto = new CryptoBrowser();
// Set key when wallet is unlocked
const unlockWallet = async () => {
await auth.unlock({ password: 'password', chainId: 'ethereum' });
const key = await auth.deriveDataEncryptionKey({
purpose: 'my-app-data',
});
crypto.setEncryptionKey(key);
};
// Use encryption after unlocking
await unlockWallet();
const encrypted = await crypto.encrypt()('Secret message');
`
CryptoBrowser uses AES-256-GCM encryption:
- Algorithm: AES-GCM (Galois/Counter Mode)
- Key Size: 256 bits
- IV Size: 12 bytes (96 bits)
- Output Format: Base64-encoded (IV + ciphertext)
The initialization vector (IV) is randomly generated for each encryption operation and prepended to the ciphertext. This ensures each encryption produces a unique result, even for the same plaintext.
The server export provides both browser and server-specific functionality:
`typescript
import { CryptoServer } from '@cryptforge/cryptography/server';
// CryptoServer provides Node.js-specific crypto operations
const crypto = new CryptoServer();
// Server-side encryption/decryption
// (Implementation similar to CryptoBrowser but optimized for Node.js)
`
Note: The server implementation is currently under development. For now, you can use CryptoBrowser in Node.js environments as the Web Crypto API is available in Node.js v15+.
This package maintains strict separation between client and server environments:
- src/client/: Browser-compatible implementations using Web Crypto API
- src/server/: Node.js-specific implementations using Node's crypto module
- src/shared/: Environment-agnostic utilities and helpers
- src/types/: Shared TypeScript type definitions
- @cryptforge/cryptography: Client/browser-safe exports (default)
- @cryptforge/cryptography/server: Server-specific exports + client exports
Browser-compatible cryptographic operations using Web Crypto API.
#### Constructor
`typescript`
new CryptoBrowser()
Creates a new CryptoBrowser instance. The encryption key must be set before using encrypt/decrypt methods.
#### Methods
##### setEncryptionKey(key: CryptoKey): void
Sets the encryption key for subsequent operations. Key must be:
- Algorithm: AES-GCM
- Length: 256 bits
- Usages: ['encrypt', 'decrypt']
`typescript
const key = await auth.deriveDataEncryptionKey({
purpose: 'my-data',
algorithm: 'AES-GCM',
length: 256,
});
crypto.setEncryptionKey(key);
`
##### encrypt(): (data: string) => Promise
Returns a curried function that encrypts string data.
`typescript`
const encryptFn = crypto.encrypt();
const encrypted = await encryptFn('Hello, World!');
Returns: Base64-encoded string containing IV + ciphertext
##### decrypt(): (encryptedData: string) => Promise
Returns a curried function that decrypts encrypted string data.
`typescript`
const decryptFn = crypto.decrypt();
const decrypted = await decryptFn(encrypted);
Throws: Error if decryption fails (wrong key, corrupted data, etc.)
`typescript
import { CryptoBrowser } from '@cryptforge/cryptography';
import { createAuthClient } from '@cryptforge/auth';
// Setup
const auth = createAuthClient();
await auth.unlock({ password: 'password', chainId: 'ethereum' });
const key = await auth.deriveDataEncryptionKey({
purpose: 'user-documents',
});
const crypto = new CryptoBrowser();
crypto.setEncryptionKey(key);
// Encrypt
const data = JSON.stringify({ title: 'My Document', content: 'Secret data' });
const encrypted = await crypto.encrypt()(data);
// Store encrypted data
localStorage.setItem('myDocument', encrypted);
// Later... decrypt
const stored = localStorage.getItem('myDocument');
const decrypted = await crypto.decrypt()(stored!);
const document = JSON.parse(decrypted);
`
`typescript
const encrypt = crypto.encrypt();
const decrypt = crypto.decrypt();
// Encrypt multiple items
const items = ['Item 1', 'Item 2', 'Item 3'];
const encryptedItems = await Promise.all(
items.map(item => encrypt(item))
);
// Decrypt multiple items
const decryptedItems = await Promise.all(
encryptedItems.map(item => decrypt(item))
);
`
`typescript`
try {
const encrypted = await crypto.encrypt()('Secret data');
const decrypted = await crypto.decrypt()(encrypted);
} catch (error) {
if (error.message.includes('Encryption key not available')) {
// Key not set - unlock wallet first
await auth.unlock({ password: 'password' });
const key = await auth.deriveDataEncryptionKey({ purpose: 'data' });
crypto.setEncryptionKey(key);
} else {
// Decryption failed - wrong key or corrupted data
console.error('Decryption failed:', error);
}
}
Perfect for encrypting Automerge documents:
`typescript
import { CryptoBrowser } from '@cryptforge/cryptography';
import * as Automerge from '@automerge/automerge';
// Create Automerge document
let doc = Automerge.init();
doc = Automerge.change(doc, doc => {
doc.notes = 'Secret notes';
});
// Encrypt document
const docBytes = Automerge.save(doc);
const docString = btoa(String.fromCharCode(...docBytes));
const encrypted = await crypto.encrypt()(docString);
// Store encrypted document
await storage.save('doc_id', encrypted);
// Later... decrypt and load
const stored = await storage.load('doc_id');
const decrypted = await crypto.decrypt()(stored);
const docBytesRestored = Uint8Array.from(atob(decrypted), c => c.charCodeAt(0));
const restoredDoc = Automerge.load(docBytesRestored);
`
1. Key Management: Never hardcode encryption keys. Always derive them from user credentials or secure key storage.
2. Key Rotation: Use the version parameter in deriveDataEncryptionKey to support key rotation:
`typescript
// Old data encrypted with v1
const keyV1 = await auth.deriveDataEncryptionKey({ purpose: 'data', version: 1 });
// New data encrypted with v2
const keyV2 = await auth.deriveDataEncryptionKey({ purpose: 'data', version: 2 });
`
3. Secure Key Storage: The encryption key is kept in memory only. When the user locks their wallet, the key is cleared.
4. No Key Export: Keys are created with extractable: false by default, preventing them from being exported.
ā
Data at Rest - Encrypted data stored in IndexedDB, localStorage, or disk
ā
Data in Transit - Can encrypt before sending over network
ā
Memory Safety - Keys cleared when wallet locks
ā Data in Use - Decrypted data in application memory
ā Side Channels - Timing attacks, power analysis
ā Compromised Device - Malware, keyloggers
Always follow security best practices for your specific use case.
This package uses AES-256-GCM, which is supported across all platforms:
| Platform | Support | Notes |
|----------|---------|-------|
| Browser | ā
| Web Crypto API (all modern browsers) |
| Node.js | ā
| Native crypto module (v15+) |
| Electron | ā
| Both main and renderer processes |
| React Native | ā
| Via polyfills |
| Web Workers | ā
| Web Crypto API available |
`bashBuild the package
npm run build
Related Packages
- @cryptforge/auth - Key derivation using
deriveDataEncryptionKey()`MIT