doc: update for latest changes

This commit is contained in:
Alpha Nerd 2026-04-01 15:15:18 +02:00
parent d9d2ec98db
commit 3b1792e613
2 changed files with 77 additions and 17 deletions

View file

@ -81,8 +81,10 @@ console.log(response.choices[0].message.content);
- **Automatic key loading**: Existing keys are loaded automatically from `client_keys/` directory (Node.js only) - **Automatic key loading**: Existing keys are loaded automatically from `client_keys/` directory (Node.js only)
- **No manual intervention required**: The library handles key management automatically - **No manual intervention required**: The library handles key management automatically
- **Optional persistence**: Keys can be saved to `client_keys/` directory for reuse across sessions (Node.js only) - **Optional persistence**: Keys can be saved to `client_keys/` directory for reuse across sessions (Node.js only)
- **Password protection**: Optional password encryption for private keys (recommended for production) - **Password protection**: Optional password encryption for private keys (minimum 8 characters required)
- **Secure permissions**: Private keys stored with restricted permissions (600 - owner-only access) - **Secure permissions**: Private keys stored with restricted permissions (600 - owner-only access)
- **Automatic key rotation**: Keys are rotated on a configurable interval (default: 24 hours) to limit fingerprint lifetime
- **Explicit lifecycle management**: Call `dispose()` to immediately zero in-memory key material and stop the rotation timer
### Secure Memory Protection ### Secure Memory Protection
@ -242,11 +244,38 @@ await client.loadKeys(
); );
``` ```
### Resource Management
Always call `dispose()` when finished to zero key material and stop the background rotation timer:
```javascript
const client = new SecureChatCompletion({
baseUrl: 'https://api.nomyo.ai:12434',
keyRotationInterval: 3600000, // rotate every hour
});
try {
const response = await client.create({ model: 'Qwen/Qwen3-0.6B', messages: [...] });
console.log(response.choices[0].message.content);
} finally {
client.dispose();
}
```
To disable key rotation entirely (e.g. short-lived scripts):
```javascript
const client = new SecureChatCompletion({
baseUrl: 'https://api.nomyo.ai:12434',
keyRotationInterval: 0, // disabled
});
```
## 🧪 Platform Support ## 🧪 Platform Support
### Node.js ### Node.js
- **Minimum version**: Node.js 15+ (for `crypto.webcrypto`) - **Minimum version**: Node.js 14.17+
- **Recommended**: Node.js 18 LTS or later - **Recommended**: Node.js 18 LTS or later
- **Key storage**: File system (`client_keys/` directory) - **Key storage**: File system (`client_keys/` directory)
- **Security**: Full implementation with automatic key persistence - **Security**: Full implementation with automatic key persistence
@ -269,10 +298,15 @@ await client.loadKeys(
```typescript ```typescript
new SecureChatCompletion(config?: { new SecureChatCompletion(config?: {
baseUrl?: string; // Default: 'https://api.nomyo.ai:12434' baseUrl?: string; // Default: 'https://api.nomyo.ai:12434'
allowHttp?: boolean; // Default: false allowHttp?: boolean; // Default: false
apiKey?: string; // Default: undefined apiKey?: string; // Default: undefined
secureMemory?: boolean; // Default: true secureMemory?: boolean; // Default: true
timeout?: number; // Request timeout ms. Default: 60000
debug?: boolean; // Enable verbose logging. Default: false
keyRotationInterval?: number; // Key rotation ms. 0 = disabled. Default: 86400000 (24h)
keyRotationDir?: string; // Directory for rotated keys. Default: 'client_keys'
keyRotationPassword?: string; // Password for rotated key files
}) })
``` ```
@ -280,6 +314,7 @@ new SecureChatCompletion(config?: {
- `create(request: ChatCompletionRequest): Promise<ChatCompletionResponse>` - `create(request: ChatCompletionRequest): Promise<ChatCompletionResponse>`
- `acreate(request: ChatCompletionRequest): Promise<ChatCompletionResponse>` (alias) - `acreate(request: ChatCompletionRequest): Promise<ChatCompletionResponse>` (alias)
- `dispose(): void` — zero key material and stop rotation timer
### SecureCompletionClient ### SecureCompletionClient
@ -289,10 +324,15 @@ Lower-level API for advanced use cases.
```typescript ```typescript
new SecureCompletionClient(config?: { new SecureCompletionClient(config?: {
routerUrl?: string; // Default: 'https://api.nomyo.ai:12434' routerUrl?: string; // Default: 'https://api.nomyo.ai:12434'
allowHttp?: boolean; // Default: false allowHttp?: boolean; // Default: false
secureMemory?: boolean; // Default: true secureMemory?: boolean; // Default: true
keySize?: 2048 | 4096; // Default: 4096 keySize?: 2048 | 4096; // Default: 4096
timeout?: number; // Request timeout ms. Default: 60000
debug?: boolean; // Enable verbose logging. Default: false
keyRotationInterval?: number; // Key rotation ms. 0 = disabled. Default: 86400000 (24h)
keyRotationDir?: string; // Directory for rotated keys. Default: 'client_keys'
keyRotationPassword?: string; // Password for rotated key files
}) })
``` ```
@ -304,6 +344,7 @@ new SecureCompletionClient(config?: {
- `encryptPayload(payload: object): Promise<ArrayBuffer>` - `encryptPayload(payload: object): Promise<ArrayBuffer>`
- `decryptResponse(encrypted: ArrayBuffer, payloadId: string): Promise<object>` - `decryptResponse(encrypted: ArrayBuffer, payloadId: string): Promise<object>`
- `sendSecureRequest(payload: object, payloadId: string, apiKey?: string): Promise<object>` - `sendSecureRequest(payload: object, payloadId: string, apiKey?: string): Promise<object>`
- `dispose(): void` — zero key material and stop rotation timer
## 🔧 Configuration ## 🔧 Configuration

View file

@ -53,18 +53,28 @@ NOMYO.js implements end-to-end encryption for OpenAI-compatible chat completions
- Automatic key generation on first use - Automatic key generation on first use
- File-based persistence (Node.js) - File-based persistence (Node.js)
- In-memory keys (browsers) - In-memory keys (browsers)
- Password protection via PBKDF2 + AES-256-CBC - Password protection via PBKDF2 + AES-256-CBC (minimum 8-character password enforced)
- Automatic periodic key rotation (default: 24 hours, configurable, or disabled with `keyRotationInterval: 0`)
- `dispose()` method severs in-memory key references and cancels the rotation timer
4. **Transport Security** 4. **Transport Security**
- HTTPS enforcement (with warnings for HTTP) - HTTPS enforcement using proper URL parsing (`new URL()`) — not string prefix matching
- Certificate validation (browsers/Node.js) - Certificate validation (browsers/Node.js)
- Optional HTTP for local development (explicit opt-in) - Optional HTTP for local development (explicit opt-in)
- API key validated to reject CR/LF characters (prevents HTTP header injection)
- Server error detail truncated to 100 printable characters (prevents log injection)
5. **Memory Protection (Pure JavaScript)** 5. **Memory Protection (Pure JavaScript)**
- Immediate zeroing of sensitive buffers - Immediate zeroing of sensitive buffers
- Context managers for automatic cleanup - Context managers for automatic cleanup (`SecureByteContext`) with guarded `finally` blocks
- Intermediate crypto buffers (password bytes, salt, IV) wrapped in `SecureByteContext` during key encryption
- HTTP request body (`ArrayBuffer`) zeroed after data is handed to the socket
- Best-effort memory management - Best-effort memory management
6. **Response Integrity**
- Decrypted response validated against required `ChatCompletionResponse` schema fields before use
- Generic error messages from all crypto operations (no internal engine details leaked)
### ⚠️ Limitations (Pure JavaScript) ### ⚠️ Limitations (Pure JavaScript)
1. **No OS-Level Memory Locking** 1. **No OS-Level Memory Locking**
@ -94,9 +104,10 @@ NOMYO.js implements end-to-end encryption for OpenAI-compatible chat completions
✅ **DO:** ✅ **DO:**
- Use HTTPS in production (enforced by default) - Use HTTPS in production (enforced by default)
- Enable secure memory protection (default: `secureMemory: true`) - Enable secure memory protection (default: `secureMemory: true`)
- Use password-protected private keys in Node.js - Use password-protected private keys in Node.js (minimum 8 characters)
- Set private key file permissions to 600 (owner-only) - Set private key file permissions to 600 (owner-only)
- Rotate keys periodically - Rely on automatic key rotation (`keyRotationInterval`, default 24h) to limit fingerprint lifetime
- Call `dispose()` when the client is no longer needed
- Validate server public key fingerprint on first use - Validate server public key fingerprint on first use
❌ **DON'T:** ❌ **DON'T:**
@ -248,9 +259,12 @@ class SecureByteContext {
try { try {
return await fn(this.data); return await fn(this.data);
} finally { } finally {
// Always zero, even if exception occurs // Always zero, even if exception occurs.
// zeroMemory failure is swallowed so it cannot mask the original error.
if (this.useSecure) { if (this.useSecure) {
new Uint8Array(this.data).fill(0); try {
this.secureMemory.zeroMemory(this.data);
} catch (_zeroErr) { /* intentional */ }
} }
} }
} }
@ -328,6 +342,11 @@ npm install nomyo-native
✅ **Timing Attacks (Partial)** ✅ **Timing Attacks (Partial)**
- Web Crypto API uses constant-time operations - Web Crypto API uses constant-time operations
- No length leakage in comparisons - No length leakage in comparisons
- Generic error messages from all crypto operations (RSA, AES) — internal engine errors not forwarded
✅ **Concurrent Key Generation Race**
- Promise-chain mutex serialises all `ensureKeys()` callers
- No risk of multiple simultaneous key generations overwriting each other
✅ **Key Compromise (Forward Secrecy)** ✅ **Key Compromise (Forward Secrecy)**
- Ephemeral AES keys - Ephemeral AES keys