Skip to content

Commit fd0c1c1

Browse files
Merge branch 'master' into master
2 parents 04feb93 + 090db3f commit fd0c1c1

9 files changed

Lines changed: 502 additions & 101 deletions

File tree

service/README.md

Lines changed: 116 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,123 @@ setConfig({
8383
});
8484
```
8585

86-
### `createChatInstance(config?: Partial<ConfigType>): IChatE2EE`
87-
Factory function to create a new chat session instance. Accepts an optional config to set `baseUrl` and `settings` inline, as an alternative to calling `setConfig()` separately.
86+
### `createChatInstance(config?, encryptionStrategy?): IChatE2EE`
87+
Factory function to create a new chat session instance.
8888

89-
```javascript
90-
const chat = createChatInstance({
91-
baseUrl: 'https://your-api.example.com',
92-
settings: { disableLog: true },
93-
});
89+
| Parameter | Type | Description |
90+
| :--- | :--- | :--- |
91+
| `config` | `Partial<ConfigType>` | Optional. Sets `baseUrl` and `settings` inline. |
92+
| `encryptionStrategy` | `EncryptionStrategy` | Optional. Plug in custom symmetric / asymmetric ciphers. Use `EncryptionFactory.create()` to produce this value (see [Pluggable Encryption](#pluggable-encryption)). |
93+
94+
```typescript
95+
import { createChatInstance, EncryptionFactory } from '@chat-e2ee/service';
96+
97+
// Default — AES-256-GCM + RSA-OAEP
98+
const chat = createChatInstance({ baseUrl: 'https://your-api.example.com' });
99+
100+
// Explicit strategy via factory
101+
const chat = createChatInstance(config, EncryptionFactory.create({ symmetric: 'AES-GCM' }));
102+
```
103+
104+
---
105+
106+
## Pluggable Encryption
107+
108+
The SDK ships with two built-in ciphers:
109+
110+
| Layer | Default | Purpose |
111+
| :--- | :--- | :--- |
112+
| Asymmetric | `RSA-OAEP` (2048-bit, SHA-256) | Key-pair generation, message encryption, symmetric key wrapping |
113+
| Symmetric | `AES-GCM` (256-bit) | Frame-by-frame WebRTC audio/video encryption |
114+
115+
Both are swappable at construction time via `EncryptionFactory`.
116+
117+
### EncryptionFactory
118+
119+
`EncryptionFactory` is a registry-based singleton. Register a cipher once under a name, then reference it by that name anywhere.
120+
121+
#### Built-in strategies
122+
123+
| Name | Type |
124+
| :--- | :--- |
125+
| `'AES-GCM'` | symmetric |
126+
| `'RSA-OAEP'` | asymmetric |
127+
128+
#### `EncryptionFactory.create(config?)`
129+
130+
Returns an `EncryptionStrategy` ready to pass to `createChatInstance`. Omit either field to keep its built-in default.
131+
132+
```typescript
133+
// Both defaults
134+
EncryptionFactory.create()
135+
136+
// Override one layer, keep the other default
137+
EncryptionFactory.create({ symmetric: 'ChaCha20' })
138+
EncryptionFactory.create({ asymmetric: 'X25519' })
139+
140+
// Override both
141+
EncryptionFactory.create({ symmetric: 'ChaCha20', asymmetric: 'X25519' })
142+
```
143+
144+
Requesting an unregistered name throws immediately:
145+
> `Unknown symmetric strategy: "ChaCha20". Register it first with EncryptionFactory.registerSymmetric().`
146+
147+
#### `EncryptionFactory.registerSymmetric(name, factory)`
148+
#### `EncryptionFactory.registerAsymmetric(name, factory)`
149+
150+
Register a custom implementation under a name. Both methods return `this` for chaining.
151+
152+
```typescript
153+
EncryptionFactory
154+
.registerSymmetric('ChaCha20', () => new ChaCha20Encryption())
155+
.registerAsymmetric('X25519', () => new X25519Exchange());
156+
```
157+
158+
### Implementing a custom strategy
159+
160+
#### `ISymmetricEncryption`
161+
162+
```typescript
163+
import type { ISymmetricEncryption } from '@chat-e2ee/service';
164+
165+
class ChaCha20Encryption implements ISymmetricEncryption {
166+
async init(): Promise<void> { /* generate local key */ }
167+
async encryptData(data: ArrayBuffer): Promise<{ encryptedData: Uint8Array<ArrayBuffer>; iv: Uint8Array<ArrayBuffer> }> { /**/ }
168+
async decryptData(data: BufferSource, iv: BufferSource): Promise<ArrayBuffer> { /**/ }
169+
async exportKey(): Promise<string> { /* serialise local key for transmission */ }
170+
async importRemoteKey(key: string): Promise<void> { /* import peer's key */ }
171+
}
172+
```
173+
174+
#### `IAsymmetricEncryption`
175+
176+
```typescript
177+
import type { IAsymmetricEncryption } from '@chat-e2ee/service';
178+
179+
class X25519Exchange implements IAsymmetricEncryption {
180+
async generateKeypairs(): Promise<{ privateKey: string; publicKey: string }> { /**/ }
181+
async encryptMessage(plaintext: string, publicKey: string): Promise<string> { /**/ }
182+
async decryptMessage(ciphertext: string, privateKey: string): Promise<string> { /**/ }
183+
}
184+
```
185+
186+
#### Full example
187+
188+
```typescript
189+
import { createChatInstance, EncryptionFactory } from '@chat-e2ee/service';
190+
191+
// 1. Register at app startup
192+
EncryptionFactory
193+
.registerSymmetric('ChaCha20', () => new ChaCha20Encryption())
194+
.registerAsymmetric('X25519', () => new X25519Exchange());
195+
196+
// 2. Use by name
197+
const chat = createChatInstance(config, EncryptionFactory.create({
198+
symmetric: 'ChaCha20',
199+
asymmetric: 'X25519',
200+
}));
201+
202+
await chat.init();
94203
```
95204

96205
---

service/package-lock.json

Lines changed: 28 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)