@omnituum/pqc-shared 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +543 -0
  3. package/dist/crypto/index.cjs +807 -0
  4. package/dist/crypto/index.d.cts +641 -0
  5. package/dist/crypto/index.d.ts +641 -0
  6. package/dist/crypto/index.js +716 -0
  7. package/dist/decrypt-eSHlbh1j.d.cts +321 -0
  8. package/dist/decrypt-eSHlbh1j.d.ts +321 -0
  9. package/dist/fs/index.cjs +1168 -0
  10. package/dist/fs/index.d.cts +400 -0
  11. package/dist/fs/index.d.ts +400 -0
  12. package/dist/fs/index.js +1091 -0
  13. package/dist/index.cjs +2160 -0
  14. package/dist/index.d.cts +282 -0
  15. package/dist/index.d.ts +282 -0
  16. package/dist/index.js +2031 -0
  17. package/dist/integrity-CCYjrap3.d.ts +31 -0
  18. package/dist/integrity-Dx9jukMH.d.cts +31 -0
  19. package/dist/types-61c7Q9ri.d.ts +134 -0
  20. package/dist/types-Ch0y-n7K.d.cts +134 -0
  21. package/dist/utils/index.cjs +129 -0
  22. package/dist/utils/index.d.cts +49 -0
  23. package/dist/utils/index.d.ts +49 -0
  24. package/dist/utils/index.js +114 -0
  25. package/dist/vault/index.cjs +713 -0
  26. package/dist/vault/index.d.cts +237 -0
  27. package/dist/vault/index.d.ts +237 -0
  28. package/dist/vault/index.js +677 -0
  29. package/dist/version-BygzPVGs.d.cts +55 -0
  30. package/dist/version-BygzPVGs.d.ts +55 -0
  31. package/package.json +86 -0
  32. package/src/crypto/dilithium.ts +233 -0
  33. package/src/crypto/hybrid.ts +358 -0
  34. package/src/crypto/index.ts +181 -0
  35. package/src/crypto/kyber.ts +199 -0
  36. package/src/crypto/nacl.ts +204 -0
  37. package/src/crypto/primitives/blake3.ts +141 -0
  38. package/src/crypto/primitives/chacha.ts +211 -0
  39. package/src/crypto/primitives/hkdf.ts +192 -0
  40. package/src/crypto/primitives/index.ts +54 -0
  41. package/src/crypto/primitives.ts +144 -0
  42. package/src/crypto/x25519.ts +134 -0
  43. package/src/fs/aes.ts +343 -0
  44. package/src/fs/argon2.ts +184 -0
  45. package/src/fs/browser.ts +408 -0
  46. package/src/fs/decrypt.ts +320 -0
  47. package/src/fs/encrypt.ts +324 -0
  48. package/src/fs/format.ts +425 -0
  49. package/src/fs/index.ts +144 -0
  50. package/src/fs/types.ts +304 -0
  51. package/src/index.ts +414 -0
  52. package/src/kdf/index.ts +311 -0
  53. package/src/runtime/crypto.ts +16 -0
  54. package/src/security/index.ts +345 -0
  55. package/src/tunnel/index.ts +39 -0
  56. package/src/tunnel/session.ts +229 -0
  57. package/src/tunnel/types.ts +115 -0
  58. package/src/utils/entropy.ts +128 -0
  59. package/src/utils/index.ts +25 -0
  60. package/src/utils/integrity.ts +95 -0
  61. package/src/vault/decrypt.ts +167 -0
  62. package/src/vault/encrypt.ts +207 -0
  63. package/src/vault/index.ts +71 -0
  64. package/src/vault/manager.ts +327 -0
  65. package/src/vault/migrate.ts +190 -0
  66. package/src/vault/types.ts +177 -0
  67. package/src/version.ts +304 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ SPDX-License-Identifier: MIT
2
+
3
+ Copyright (c) 2025–2026 Nathan Cowan
4
+ Copyright (c) 2025–2026 Omnituum
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,543 @@
1
+ # @omnituum/pqc-shared
2
+
3
+ Post-Quantum Cryptography library for hybrid encryption, identity management, and secure file handling.
4
+
5
+ ## Features
6
+
7
+ - **Hybrid Encryption** — X25519 + ML-KEM-768 (Kyber) dual-layer security
8
+ - **Post-Quantum Signatures** — ML-DSA-65 (Dilithium) via `@noble/post-quantum`
9
+ - **Identity Vault** — Encrypted storage with Argon2id key derivation
10
+ - **File Encryption** — `.oqe` format with hybrid or password-based modes
11
+ - **Cross-Platform** — Works in Node.js and modern browsers; no native bindings
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @omnituum/pqc-shared
17
+ # or
18
+ pnpm add @omnituum/pqc-shared
19
+ ```
20
+
21
+ ## Supported Environments
22
+
23
+ `@omnituum/pqc-shared` is designed to run in both Node.js and modern browsers.
24
+
25
+ - **Node.js:** 18, 20, 22
26
+ - **Browsers:** modern Chromium / Firefox / Safari with WebCrypto support
27
+
28
+ ### Cryptographic runtime behavior
29
+
30
+ - In browsers, the library uses **WebCrypto** (`globalThis.crypto`) when available.
31
+ - In Node.js, the library uses **Node built-ins** (e.g. `crypto`) as a fallback when WebCrypto globals are unavailable.
32
+
33
+ If you bundle for the browser, ensure your bundler targets web environments and does not force Node polyfills unless explicitly intended.
34
+
35
+ ## Non-Goals
36
+
37
+ This package provides **cryptographic primitives and utilities**. It does **not** provide:
38
+
39
+ - Custodial services, hosting, or key escrow
40
+ - User authentication, identity proofing, or account recovery
41
+ - Network transport, relays, or message delivery guarantees
42
+ - Compliance certification (audit/compliance is handled at the system + deployment layer)
43
+
44
+ ## Security Status
45
+
46
+ This repository is **pre-audit**. It includes golden test vectors for regression detection.
47
+ If you plan to use this library in high-stakes environments, perform an independent review and validate the threat model for your deployment.
48
+
49
+ ## API Stability
50
+
51
+ Exports are annotated with stability markers:
52
+
53
+ - **`@stable`** — Supported and semver-governed. Breaking changes only in major versions.
54
+ - **`@experimental`** — May change in minor/patch releases until stabilized.
55
+
56
+ The public API surface is the root exports (`@omnituum/pqc-shared`). Subpath exports (`/crypto`, `/vault`, `/fs`, `/utils`) may evolve faster and are intended for advanced use cases.
57
+
58
+ ## Quick Start
59
+
60
+ ### Hybrid Encryption
61
+
62
+ ```typescript
63
+ import {
64
+ generateHybridIdentity,
65
+ hybridEncrypt,
66
+ hybridDecryptToString,
67
+ getPublicKeys,
68
+ } from '@omnituum/pqc-shared';
69
+
70
+ // Generate identity with X25519 + Kyber keypairs
71
+ const alice = await generateHybridIdentity('Alice');
72
+ const bob = await generateHybridIdentity('Bob');
73
+
74
+ // Encrypt message for Bob using his public keys
75
+ const bobPublicKeys = getPublicKeys(bob);
76
+ const envelope = await hybridEncrypt(
77
+ 'Hello, Bob!',
78
+ bobPublicKeys,
79
+ { senderName: alice.name, senderId: alice.id }
80
+ );
81
+
82
+ // Bob decrypts with his secret keys
83
+ const plaintext = await hybridDecryptToString(envelope, bob);
84
+ console.log(plaintext); // "Hello, Bob!"
85
+ ```
86
+
87
+ ### Digital Signatures (Dilithium)
88
+
89
+ ```typescript
90
+ import {
91
+ generateDilithiumKeypair,
92
+ dilithiumSign,
93
+ dilithiumVerify,
94
+ } from '@omnituum/pqc-shared';
95
+
96
+ const keypair = await generateDilithiumKeypair();
97
+ const message = new TextEncoder().encode('Sign this message');
98
+
99
+ const { signature } = await dilithiumSign(message, keypair.secretB64);
100
+ const valid = await dilithiumVerify(message, signature, keypair.publicB64);
101
+ console.log(valid); // true
102
+ ```
103
+
104
+ ### Vault Management
105
+
106
+ ```typescript
107
+ import {
108
+ createEmptyVault,
109
+ generateHybridIdentity,
110
+ addIdentity,
111
+ encryptVault,
112
+ decryptVault,
113
+ } from '@omnituum/pqc-shared';
114
+
115
+ // Create and populate vault
116
+ let vault = createEmptyVault();
117
+ const identity = await generateHybridIdentity('My Identity');
118
+ vault = addIdentity(vault, identity);
119
+
120
+ // Encrypt vault with password (uses Argon2id)
121
+ const encrypted = await encryptVault(vault, 'my-password');
122
+
123
+ // Decrypt vault
124
+ const decrypted = await decryptVault(encrypted, 'my-password');
125
+ ```
126
+
127
+ ### File Encryption
128
+
129
+ > **Note:** File encryption APIs accept browser `File`/`Blob` objects. For Node.js usage, use `Uint8Array` with the underlying hybrid encryption functions directly.
130
+
131
+ ```typescript
132
+ import { encryptFile, decryptFile } from '@omnituum/pqc-shared';
133
+
134
+ // Encrypt file for recipient (browser)
135
+ const result = await encryptFile(fileData, recipientPublicKeys, senderIdentity, {
136
+ filename: 'document.pdf',
137
+ mimeType: 'application/pdf',
138
+ });
139
+ // result.encrypted contains .oqe file bytes
140
+
141
+ // Decrypt file
142
+ const decrypted = await decryptFile(oqeBytes, recipientIdentity);
143
+ console.log(decrypted.metadata.filename); // "document.pdf"
144
+ ```
145
+
146
+ ---
147
+
148
+ ## API Reference
149
+
150
+ ### Hybrid Encryption
151
+
152
+ | Function | Description |
153
+ |----------|-------------|
154
+ | `generateHybridIdentity(name)` | Create identity with X25519 + Kyber keypairs |
155
+ | `hybridEncrypt(plaintext, recipientPubKeys, meta?)` | Encrypt using hybrid encryption |
156
+ | `hybridDecrypt(envelope, recipientIdentity)` | Decrypt hybrid envelope |
157
+ | `hybridDecryptToString(envelope, recipientIdentity)` | Decrypt to UTF-8 string |
158
+ | `getPublicKeys(identity)` | Extract public keys from identity |
159
+ | `getSecretKeys(identity)` | Extract secret keys from identity |
160
+
161
+ ### ML-KEM-768 (Kyber)
162
+
163
+ | Function | Description |
164
+ |----------|-------------|
165
+ | `isKyberAvailable()` | Check if Kyber library is available |
166
+ | `generateKyberKeypair()` | Generate Kyber keypair |
167
+ | `kyberEncapsulate(publicKeyB64)` | Create shared secret + ciphertext |
168
+ | `kyberDecapsulate(ciphertextB64, secretKeyB64)` | Recover shared secret |
169
+ | `kyberWrapKey(symKey, publicKeyB64)` | Wrap symmetric key |
170
+ | `kyberUnwrapKey(wrapped, secretKeyB64)` | Unwrap symmetric key |
171
+
172
+ ### X25519
173
+
174
+ | Function | Description |
175
+ |----------|-------------|
176
+ | `generateX25519Keypair()` | Generate ECDH keypair |
177
+ | `generateX25519KeypairFromSeed(seed)` | Deterministic keypair from seed |
178
+ | `boxWrapWithX25519(symKey, recipientPubKeyHex)` | Wrap key with ECDH |
179
+ | `boxUnwrapWithX25519(wrap, secretKey)` | Unwrap key |
180
+ | `x25519SharedSecret(ourSecret, theirPublic)` | Raw scalar multiplication |
181
+ | `deriveKeyFromShared(shared, salt, info)` | HKDF derivation |
182
+
183
+ ### Dilithium ML-DSA-65
184
+
185
+ | Function | Description |
186
+ |----------|-------------|
187
+ | `isDilithiumAvailable()` | Check if Dilithium library is available |
188
+ | `generateDilithiumKeypair()` | Generate signature keypair |
189
+ | `generateDilithiumKeypairFromSeed(seed)` | Deterministic generation |
190
+ | `dilithiumSign(message, secretKeyB64)` | Sign message (base64 output) |
191
+ | `dilithiumSignRaw(message, secretKeyB64)` | Sign message (Uint8Array output) |
192
+ | `dilithiumVerify(message, signatureB64, publicKeyB64)` | Verify signature |
193
+ | `dilithiumVerifyRaw(message, signature, publicKey)` | Verify with raw bytes |
194
+
195
+ **Key Sizes:**
196
+ - Public Key: 1952 bytes
197
+ - Secret Key: 4032 bytes
198
+ - Signature: 3309 bytes
199
+
200
+ ### Vault Management
201
+
202
+ | Function | Description |
203
+ |----------|-------------|
204
+ | `createEmptyVault()` | Initialize empty vault |
205
+ | `createIdentity(name)` | Create new hybrid identity |
206
+ | `addIdentity(vault, identity)` | Add identity to vault |
207
+ | `removeIdentity(vault, identityId)` | Remove identity from vault |
208
+ | `rotateIdentityKeys(identity)` | Rotate all keys for identity |
209
+ | `setActiveIdentity(vault, identityId)` | Set default identity |
210
+ | `encryptVault(vault, password)` | Encrypt vault (Argon2id) |
211
+ | `decryptVault(encryptedVault, password)` | Decrypt vault |
212
+ | `exportVault(vault, password)` | Serialize to JSON string |
213
+ | `importVault(json, password)` | Deserialize from JSON |
214
+
215
+ ### Vault Migration
216
+
217
+ | Function | Description |
218
+ |----------|-------------|
219
+ | `needsMigration(encryptedVault)` | Check if vault uses PBKDF2 |
220
+ | `isV2Vault(encryptedVault)` | Check if vault uses Argon2id |
221
+ | `migrateEncryptedVault(vault, oldPw, newPw)` | Migrate PBKDF2 → Argon2id |
222
+ | `getVaultKdfInfo(encryptedVault)` | Get KDF metadata |
223
+
224
+ ### Key Derivation
225
+
226
+ | Function | Description |
227
+ |----------|-------------|
228
+ | `getRecommendedConfig()` | Get optimal KDF config for platform |
229
+ | `benchmarkKDF(config, iterations)` | Measure KDF performance |
230
+ | `kdfDeriveKey(password, salt, config)` | Derive key from password |
231
+ | `generateSalt(length?)` | Generate random salt |
232
+
233
+ **KDF Configurations:**
234
+ - `KDF_CONFIG_ARGON2ID` — Memory: 64MB, Time: 3, Parallelism: 4
235
+ - `KDF_CONFIG_PBKDF2` — 600,000 iterations (OWASP 2023)
236
+
237
+ ### File Encryption
238
+
239
+ | Function | Description |
240
+ |----------|-------------|
241
+ | `encryptFile(data, recipientPubKeys, sender, opts)` | Hybrid file encryption |
242
+ | `decryptFile(oqeBytes, recipientIdentity)` | Decrypt .oqe file |
243
+ | `encryptFileWithPassword(data, password, opts)` | Password-based encryption |
244
+ | `decryptFileWithPassword(oqeBytes, password)` | Password-based decryption |
245
+
246
+ ### Cryptographic Primitives
247
+
248
+ #### BLAKE3
249
+ ```typescript
250
+ import { blake3, blake3Hex, blake3Mac, blake3DeriveKey } from '@omnituum/pqc-shared';
251
+
252
+ blake3(data); // 32-byte hash
253
+ blake3Hex(data); // Hex string
254
+ blake3Mac(key, data); // Keyed MAC
255
+ blake3DeriveKey(ikm, 'context'); // Key derivation
256
+ ```
257
+
258
+ #### ChaCha20-Poly1305
259
+ ```typescript
260
+ import {
261
+ chaCha20Poly1305Encrypt,
262
+ chaCha20Poly1305Decrypt,
263
+ xChaCha20Poly1305Encrypt,
264
+ xChaCha20Poly1305Decrypt,
265
+ } from '@omnituum/pqc-shared';
266
+
267
+ // 12-byte nonce
268
+ const ciphertext = chaCha20Poly1305Encrypt(key, nonce12, plaintext, aad?);
269
+ const plaintext = chaCha20Poly1305Decrypt(key, nonce12, ciphertext, aad?);
270
+
271
+ // 24-byte nonce (extended)
272
+ const ciphertext = xChaCha20Poly1305Encrypt(key, nonce24, plaintext, aad?);
273
+ const plaintext = xChaCha20Poly1305Decrypt(key, nonce24, ciphertext, aad?);
274
+ ```
275
+
276
+ #### HKDF
277
+ ```typescript
278
+ import { hkdfDerive, hkdfExtract, hkdfExpand } from '@omnituum/pqc-shared';
279
+
280
+ const key = hkdfDerive(ikm, salt, info, 32); // Full HKDF
281
+ const prk = hkdfExtract(ikm, salt); // Extract phase
282
+ const okm = hkdfExpand(prk, info, 32); // Expand phase
283
+ ```
284
+
285
+ #### NaCl SecretBox
286
+ ```typescript
287
+ import {
288
+ secretboxEncrypt,
289
+ secretboxDecrypt,
290
+ SECRETBOX_KEY_SIZE, // 32
291
+ SECRETBOX_NONCE_SIZE, // 24
292
+ } from '@omnituum/pqc-shared';
293
+
294
+ const { nonce, ciphertext } = secretboxEncrypt(key, plaintext);
295
+ const plaintext = secretboxDecrypt(key, nonce, ciphertext);
296
+ ```
297
+
298
+ ### Security Utilities
299
+
300
+ ```typescript
301
+ import {
302
+ SecureBuffer,
303
+ zeroMemory,
304
+ zeroAll,
305
+ withSecureData,
306
+ constantTimeEqual,
307
+ } from '@omnituum/pqc-shared';
308
+
309
+ // Memory cleanup
310
+ zeroMemory(sensitiveArray);
311
+ zeroAll(array1, array2, array3);
312
+
313
+ // Secure data handling
314
+ const result = withSecureData(
315
+ () => getSensitiveKey(),
316
+ (key) => doOperation(key)
317
+ ); // Key is zeroed after callback
318
+
319
+ // Timing-safe comparison
320
+ if (constantTimeEqual(hash1, hash2)) { ... }
321
+ ```
322
+
323
+ ### Encoding Utilities
324
+
325
+ ```typescript
326
+ import { toB64, fromB64, toHex, fromHex, rand32 } from '@omnituum/pqc-shared';
327
+
328
+ toB64(bytes); // Uint8Array → base64 string
329
+ fromB64(str); // base64 string → Uint8Array
330
+ toHex(bytes); // Uint8Array → hex string
331
+ fromHex(str); // hex string → Uint8Array
332
+
333
+ rand32(); // 32 random bytes
334
+ rand24(); // 24 random bytes
335
+ rand12(); // 12 random bytes
336
+ randN(n); // n random bytes
337
+ ```
338
+
339
+ ---
340
+
341
+ ## Data Formats
342
+
343
+ ### HybridIdentity
344
+
345
+ ```typescript
346
+ interface HybridIdentity {
347
+ id: string; // Unique identifier
348
+ name: string; // Display name
349
+ x25519PubHex: string; // X25519 public key (hex)
350
+ x25519SecHex: string; // X25519 secret key (hex)
351
+ kyberPubB64: string; // Kyber public key (base64)
352
+ kyberSecB64: string; // Kyber secret key (base64)
353
+ createdAt: string; // ISO timestamp
354
+ lastRotatedAt?: string; // Key rotation timestamp
355
+ rotationCount: number; // Rotation counter
356
+ }
357
+ ```
358
+
359
+ ### HybridEnvelope
360
+
361
+ ```typescript
362
+ interface HybridEnvelope {
363
+ v: string; // "omnituum.hybrid.v1"
364
+ suite: string; // "x25519+kyber768"
365
+ aead: string; // "xsalsa20poly1305"
366
+ x25519Epk: string; // Ephemeral X25519 public key
367
+ x25519Wrap: { nonce: string; wrapped: string };
368
+ kyberKemCt: string; // Kyber KEM ciphertext
369
+ kyberWrap: { nonce: string; wrapped: string };
370
+ contentNonce: string; // Content encryption nonce
371
+ ciphertext: string; // Encrypted content
372
+ meta: {
373
+ createdAt: string;
374
+ senderName?: string;
375
+ senderId?: string;
376
+ };
377
+ }
378
+ ```
379
+
380
+ ### OQE File Format
381
+
382
+ The `.oqe` (Omnituum Quantum Encrypted) format:
383
+
384
+ ```
385
+ ┌─────────────────────────────────────┐
386
+ │ Magic: 0x4F 0x51 0x45 0x46 ("OQEF") │
387
+ │ Version: 0x01 │
388
+ │ Mode: 0x01 (hybrid) | 0x02 (password)│
389
+ ├─────────────────────────────────────┤
390
+ │ [Mode-specific key material] │
391
+ │ [Encrypted metadata] │
392
+ │ [Encrypted file content] │
393
+ └─────────────────────────────────────┘
394
+ ```
395
+
396
+ ---
397
+
398
+ ## Version Constants
399
+
400
+ ```typescript
401
+ import {
402
+ VAULT_VERSION, // "omnituum.vault.v1"
403
+ VAULT_ENCRYPTED_VERSION, // "omnituum.vault.enc.v1" (PBKDF2)
404
+ VAULT_ENCRYPTED_VERSION_V2, // "omnituum.vault.enc.v2" (Argon2id)
405
+ ENVELOPE_VERSION, // "omnituum.hybrid.v1"
406
+ ENVELOPE_SUITE, // "x25519+kyber768"
407
+ ENVELOPE_AEAD, // "xsalsa20poly1305"
408
+ } from '@omnituum/pqc-shared';
409
+ ```
410
+
411
+ ---
412
+
413
+ ## Module Imports
414
+
415
+ The package supports tree-shaking via subpath exports:
416
+
417
+ ```typescript
418
+ // Full library
419
+ import { ... } from '@omnituum/pqc-shared';
420
+
421
+ // Crypto only
422
+ import { ... } from '@omnituum/pqc-shared/crypto';
423
+
424
+ // Vault only
425
+ import { ... } from '@omnituum/pqc-shared/vault';
426
+
427
+ // File system / encryption
428
+ import { ... } from '@omnituum/pqc-shared/fs';
429
+
430
+ // Utilities
431
+ import { ... } from '@omnituum/pqc-shared/utils';
432
+ ```
433
+
434
+ ---
435
+
436
+ ## Security Considerations
437
+
438
+ ### Post-Quantum Security
439
+
440
+ This library implements post-quantum algorithms based on NIST standards:
441
+
442
+ - **ML-KEM-768** (FIPS 203) — Key encapsulation mechanism, via `kyber-crystals`
443
+ - **ML-DSA-65** (FIPS 204) — Digital signatures, via `@noble/post-quantum`
444
+
445
+ Hybrid encryption combines classical (X25519, RFC 7748) and post-quantum (ML-KEM) algorithms. Both must decrypt successfully, providing defense-in-depth.
446
+
447
+ > **Note:** This library is pre-audit. "Implements" means we use these algorithms via dependencies; it does not imply FIPS certification or compliance program participation.
448
+
449
+ ### Key Derivation
450
+
451
+ | Version | KDF | Parameters |
452
+ |---------|-----|------------|
453
+ | V1 | PBKDF2-SHA256 | 600,000 iterations |
454
+ | V2 | Argon2id | 64MB memory, 3 iterations, parallelism 4 |
455
+
456
+ New implementations should use Argon2id (V2). Use `migrateEncryptedVault()` to upgrade legacy vaults.
457
+
458
+ ### Memory Hygiene
459
+
460
+ Always zero sensitive data after use:
461
+
462
+ ```typescript
463
+ import { zeroMemory, withSecureData } from '@omnituum/pqc-shared';
464
+
465
+ // Manual cleanup
466
+ const key = deriveKey(...);
467
+ try {
468
+ // use key
469
+ } finally {
470
+ zeroMemory(key);
471
+ }
472
+
473
+ // Automatic cleanup
474
+ withSecureData(
475
+ () => deriveKey(...),
476
+ (key) => encrypt(key, data)
477
+ );
478
+ ```
479
+
480
+ ### Timing Attacks
481
+
482
+ Use `constantTimeEqual()` for comparing secrets:
483
+
484
+ ```typescript
485
+ import { constantTimeEqual } from '@omnituum/pqc-shared';
486
+
487
+ // Bad: variable-time comparison
488
+ if (hash1 === hash2) { ... }
489
+
490
+ // Good: constant-time comparison
491
+ if (constantTimeEqual(hash1, hash2)) { ... }
492
+ ```
493
+
494
+ ---
495
+
496
+ ## Dependencies
497
+
498
+ | Package | Purpose |
499
+ |---------|---------|
500
+ | `@noble/ciphers` | ChaCha20-Poly1305 AEAD |
501
+ | `@noble/hashes` | SHA-256, BLAKE3, HMAC, HKDF |
502
+ | `@noble/post-quantum` | ML-DSA-65 (Dilithium) signatures |
503
+ | `hash-wasm` | Argon2id (WebAssembly) |
504
+ | `kyber-crystals` | ML-KEM-768 (Kyber) |
505
+ | `tweetnacl` | NaCl box/secretbox, X25519 |
506
+
507
+ All dependencies are pure JavaScript/WebAssembly with no native bindings.
508
+
509
+ ---
510
+
511
+ ## Development
512
+
513
+ ```bash
514
+ # Build
515
+ pnpm build
516
+
517
+ # Watch mode
518
+ pnpm dev
519
+
520
+ # Type check
521
+ pnpm typecheck
522
+
523
+ # Run golden tests
524
+ pnpm test:golden
525
+ ```
526
+
527
+ ### Golden Tests
528
+
529
+ Test vectors in `tests/golden/` provide reproducible cryptographic test cases:
530
+
531
+ ```bash
532
+ # Generate new test vectors (run once)
533
+ pnpm test:golden:generate
534
+
535
+ # Verify test vectors (CI/pre-audit)
536
+ pnpm test:golden:verify
537
+ ```
538
+
539
+ ---
540
+
541
+ ## License
542
+
543
+ MIT