This repository contains two main packages for end-to-end encryption (E2EE):
- @trelent/e2ee-core (the “Core” library)
- @trelent/e2ee-react (the “React” integration)
Both packages are TypeScript-based and manage the build outputs with their own tsconfig settings. Below is an overview of how these packages are structured and how they interact.
The “Core” library provides the fundamental end-to-end encryption functionality. It is completely framework-independent and focuses on cryptographic operations and passphrase handling. You can use this library to encrypt and decrypt data in any JavaScript or TypeScript environment (e.g., Node.js, Bun, browser).
-
Cryptographic Routines
Located inside thecrypto/
directory.- Encryption and decryption use AES-GCM.
- Salt and IV (“initialization vector”) are generated via the Web Crypto API.
- A PBKDF2-based (Password-Based Key Derivation Function 2) approach is used to derive AES keys from a passphrase.
- The “config” file (
crypto/config.ts
) centralizes all cryptographic parameters (salt size, IV size, PBKDF2 iteration count, encryption algorithm, etc.).
-
Passphrase Logic
Located inside thepassphrase/
directory.- The passphrase is generated using a BIP39 mnemonic approach. This includes a set of words (
bip39/words.ts
) and logic to transform random bytes to/from a mnemonic. - The passphrase is associated with a salt, which is required for PBKDF2 derivation.
- The passphrase is generated using a BIP39 mnemonic approach. This includes a set of words (
-
E2EEService Class
Exposed via the package’s root index (src/index.ts
).- The class wraps all cryptographic routines and passphrase logic into a user-friendly interface.
- Methods:
- encrypt / decrypt → Serialize data (via SuperJSON), encrypt or decrypt, and return typed data.
- encryptRaw / decryptRaw → Work directly with raw Buffers.
-
Subtle
- The
subtle
subpackage contains the cryptographic primitives used by the core library. These typically do not need to be exposed to the user.
- The
-
Tests
- All folders contain a
tests
sub-folder for unit tests that cover the functionality of the package.
- All folders contain a
Below is a high-level example of how the Core library is typically used:
import { E2EEService, subtle } from "@trelent/e2ee-core";
(async () => {
const passphrase = await subtle.generateSecurePassphrase();
const service = new E2EEService(passphrase);
const sensitiveObject = { foo: "bar", secret: 42 };
const encrypted = await service.encrypt(sensitiveObject);
// 'encrypted' is a Buffer containing salt, IV, and ciphertext
const decrypted = await service.decrypt<typeof sensitiveObject>(encrypted);
console.log(decrypted); // -> { foo: "bar", secret: 42 }
})();
The “React” integration library builds on top of @trelent/e2ee-core
to provide a convenient interface for React applications. It wraps the core encryption/decryption and passphrase generation logic into React Hooks and a Provider for easy consumption in your application’s React tree.
-
Provider (
TrelentE2EEProvider
)- Manages the passphrase in React state.
- Offers methods to generate or set a passphrase, which then creates an instance of
E2EEService
from the Core library. - Supplies context to child components so they can easily encrypt and decrypt data.
-
Hooks
useE2EEPassphraseTools
: Allows generating and setting a passphrase.useE2EECryptoTools
: Provides functions to encrypt/decrypt typed data and raw buffers without manually creating a newE2EEService
.useE2EE
: Accesses the context’s overall state (passphrase, encryption availability, etc.).isE2EEReady
: Simple check that returns true if a passphrase is set (i.e., encryption is ready).
-
Tests
- The
tests/
directory (e.g.,access.test.ts
) shows how to integrate@trelent/e2ee-core
in typical usage scenarios. These tests confirm that encryption/decryption logic is consistent in a React environment.
- The
A simplified example of how to use the React library:
import React, { useEffect } from "react";
import {
TrelentE2EEProvider,
useE2EEPassphraseTools,
useE2EECryptoTools
} from "@trelent/e2ee-react";
function MySecureComponent() {
const { passphrase, generatePassphrase, setPassphrase } = useE2EEPassphraseTools();
const { encrypt, decrypt } = useE2EECryptoTools();
useEffect(() => {
if (!passphrase) {
// Generate a new passphrase.
generatePassphrase().then(newPass => setPassphrase(newPass));
} else {
// Sample encryption usage
(async () => {
const secret: string = "Hello World";
const encrypted = await encrypt(secret);
const decrypted = await decrypt<string>(encrypted);
console.log("Original:", secret, "Decrypted:", decrypted);
})();
}
}, [passphrase, generatePassphrase, setPassphrase, encrypt, decrypt]);
return <div>Check console for encryption logs</div>;
}
export default function App() {
return (
<TrelentE2EEProvider>
<MySecureComponent />
</TrelentE2EEProvider>
);
}
-
Monorepo Structure
Each package has its own folder underpackages/
. Both have independentpackage.json
andtsconfig.json
files.- The
scripts
section often includes “build” (for TypeScript compilation) and “pb” (a convenience script to build and publish).
- The
-
Build Output
- The Core library compiles to
dist/
with type declarations. - The React library compiles to its own
dist/
. - Both are set to produce ES modules by default (
"type": "module"
inpackage.json
).
- The Core library compiles to
-
Testing
- Tests are written using Bun’s test runner.
- Each package has tests that cover its primary functionality.
- The
*.test.ts
files are excluded from build output.
-
Publishing
- The packages are published to npm with the “public” access level on the
@trelent
scope. - A typical publish flow combines building and publishing:
cd packages/core bun run pb cd ../react bun run pb
- The packages are published to npm with the “public” access level on the
The @trelent/e2ee-core package provides the foundational encryption/decryption routines via E2EEService
and BIP39 passphrase functionality. The @trelent/e2ee-react package leverages the “Core” library’s features, wrapping them in a set of React Hooks and a Provider for secure, end-to-end encrypted workflows in React applications. This separation ensures:
- Minimal dependencies for the Core library (pure cryptography).
- A React-focused interface that simplifies usage for frontend scenarios.
For more detailed usage, consult each package’s respective README and source code.