@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
@@ -0,0 +1,199 @@
1
+ /**
2
+ * Omnituum PQC Shared - Kyber ML-KEM-768
3
+ *
4
+ * Browser-compatible Kyber operations using kyber-crystals.
5
+ * NIST Level 3 security - quantum-resistant.
6
+ */
7
+
8
+ import { b64, ub64, sha256 } from './primitives';
9
+ import nacl from 'tweetnacl';
10
+
11
+ // ═══════════════════════════════════════════════════════════════════════════
12
+ // TYPES
13
+ // ═══════════════════════════════════════════════════════════════════════════
14
+
15
+ export interface KyberKeypair {
16
+ publicKey: Uint8Array;
17
+ secretKey: Uint8Array;
18
+ }
19
+
20
+ export interface KyberKeypairB64 {
21
+ publicB64: string;
22
+ secretB64: string;
23
+ }
24
+
25
+ export interface KyberEncapsulation {
26
+ ciphertext: Uint8Array;
27
+ sharedSecret: Uint8Array;
28
+ }
29
+
30
+ // ═══════════════════════════════════════════════════════════════════════════
31
+ // KYBER LIBRARY LOADING
32
+ // ═══════════════════════════════════════════════════════════════════════════
33
+
34
+ let kyberModule: any = null;
35
+
36
+ async function loadKyber(): Promise<any> {
37
+ if (kyberModule) return kyberModule;
38
+
39
+ try {
40
+ const m = await import('kyber-crystals');
41
+ const k = (m as any).default ?? m;
42
+ kyberModule = k.kyber ?? k;
43
+ return kyberModule;
44
+ } catch (e) {
45
+ console.warn('[Kyber] Failed to load kyber-crystals:', e);
46
+ return null;
47
+ }
48
+ }
49
+
50
+ // ═══════════════════════════════════════════════════════════════════════════
51
+ // AVAILABILITY CHECK
52
+ // ═══════════════════════════════════════════════════════════════════════════
53
+
54
+ export async function isKyberAvailable(): Promise<boolean> {
55
+ const mod = await loadKyber();
56
+ return mod !== null;
57
+ }
58
+
59
+ // ═══════════════════════════════════════════════════════════════════════════
60
+ // KEY GENERATION
61
+ // ═══════════════════════════════════════════════════════════════════════════
62
+
63
+ /**
64
+ * Generate a Kyber ML-KEM-768 keypair.
65
+ */
66
+ export async function generateKyberKeypair(): Promise<KyberKeypairB64 | null> {
67
+ try {
68
+ const mod = await loadKyber();
69
+ if (!mod) return null;
70
+
71
+ if (mod?.ready?.then) {
72
+ await mod.ready;
73
+ }
74
+
75
+ const fn = mod?.keypair ?? mod?.keyPair ?? mod?.generateKeyPair ?? null;
76
+ if (typeof fn !== 'function') {
77
+ console.warn('[Kyber] No keypair function found');
78
+ return null;
79
+ }
80
+
81
+ const kp = await fn.call(mod);
82
+ const pub = kp?.publicKey ?? kp?.public ?? kp?.pk;
83
+ const priv = kp?.privateKey ?? kp?.secretKey ?? kp?.secret ?? kp?.sk;
84
+
85
+ if (!pub || !priv) {
86
+ console.warn('[Kyber] Invalid keypair result');
87
+ return null;
88
+ }
89
+
90
+ return {
91
+ publicB64: b64(new Uint8Array(pub)),
92
+ secretB64: b64(new Uint8Array(priv)),
93
+ };
94
+ } catch (e) {
95
+ console.warn('[Kyber] Key generation failed:', e);
96
+ return null;
97
+ }
98
+ }
99
+
100
+ // ═══════════════════════════════════════════════════════════════════════════
101
+ // ENCAPSULATION / DECAPSULATION
102
+ // ═══════════════════════════════════════════════════════════════════════════
103
+
104
+ /**
105
+ * Encapsulate a shared secret using Kyber ML-KEM-768.
106
+ */
107
+ export async function kyberEncapsulate(pubKeyB64: string): Promise<KyberEncapsulation> {
108
+ const kyber = await loadKyber();
109
+ if (!kyber?.encrypt) {
110
+ throw new Error('Kyber encrypt not available');
111
+ }
112
+
113
+ const pk = ub64(pubKeyB64);
114
+ const r: any = await kyber.encrypt(pk);
115
+
116
+ // Normalize ciphertext
117
+ const ctRaw =
118
+ r?.ciphertext ?? r?.cyphertext ?? r?.ct ??
119
+ r?.bytes?.ciphertext ?? r?.bytes?.cyphertext ?? r?.bytes?.ct ??
120
+ (Array.isArray(r) ? r[0] : undefined);
121
+
122
+ // Normalize shared secret
123
+ const ssRaw =
124
+ r?.key ?? r?.sharedSecret ?? r?.secret ??
125
+ r?.bytes?.key ?? r?.bytes?.sharedSecret ??
126
+ (Array.isArray(r) ? r[1] : undefined);
127
+
128
+ if (!ctRaw || !ssRaw) {
129
+ throw new Error('Kyber encapsulate failed: missing ciphertext or shared secret');
130
+ }
131
+
132
+ return {
133
+ ciphertext: new Uint8Array(ctRaw),
134
+ sharedSecret: new Uint8Array(ssRaw),
135
+ };
136
+ }
137
+
138
+ /**
139
+ * Decapsulate a shared secret using Kyber ML-KEM-768.
140
+ */
141
+ export async function kyberDecapsulate(
142
+ kemCiphertextB64: string,
143
+ secretKeyB64: string
144
+ ): Promise<Uint8Array> {
145
+ const kyber = await loadKyber();
146
+ if (!kyber?.decrypt && !kyber?.decapsulate) {
147
+ throw new Error('Kyber decrypt/decapsulate not available');
148
+ }
149
+
150
+ const ct = ub64(kemCiphertextB64);
151
+ const sk = ub64(secretKeyB64);
152
+
153
+ const r: any = kyber.decrypt
154
+ ? await kyber.decrypt(ct, sk)
155
+ : await kyber.decapsulate(ct, sk);
156
+
157
+ const key = (r && (r.key ?? r.sharedSecret)) ? (r.key ?? r.sharedSecret) : r;
158
+ return new Uint8Array(key);
159
+ }
160
+
161
+ // ═══════════════════════════════════════════════════════════════════════════
162
+ // KEY WRAPPING HELPERS
163
+ // ═══════════════════════════════════════════════════════════════════════════
164
+
165
+ /**
166
+ * Wrap a message key using Kyber shared secret.
167
+ */
168
+ export function kyberWrapKey(sharedSecret: Uint8Array, msgKey32: Uint8Array): {
169
+ nonce: string;
170
+ wrapped: string;
171
+ } {
172
+ if (msgKey32.length !== 32) {
173
+ throw new Error('Message key must be 32 bytes');
174
+ }
175
+
176
+ const kek = sha256(sharedSecret); // Derive KEK from shared secret
177
+ const nonce = globalThis.crypto.getRandomValues(new Uint8Array(24));
178
+ const wrapped = nacl.secretbox(msgKey32, nonce, kek);
179
+
180
+ return {
181
+ nonce: b64(nonce),
182
+ wrapped: b64(wrapped),
183
+ };
184
+ }
185
+
186
+ /**
187
+ * Unwrap a message key using Kyber shared secret.
188
+ */
189
+ export function kyberUnwrapKey(
190
+ sharedSecret: Uint8Array,
191
+ nonceB64: string,
192
+ wrappedB64: string
193
+ ): Uint8Array | null {
194
+ const kek = sha256(sharedSecret);
195
+ const nonce = ub64(nonceB64);
196
+ const wrapped = ub64(wrappedB64);
197
+
198
+ return nacl.secretbox.open(wrapped, nonce, kek) || null;
199
+ }
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Omnituum PQC Shared - NaCl Secretbox Operations
3
+ *
4
+ * Symmetric encryption using XSalsa20-Poly1305 (NaCl secretbox).
5
+ * 32-byte key, 24-byte nonce, authenticated encryption.
6
+ */
7
+
8
+ import nacl from 'tweetnacl';
9
+ import { rand24, toB64, fromB64, assertLen } from './primitives';
10
+
11
+ // ═══════════════════════════════════════════════════════════════════════════
12
+ // TYPES
13
+ // ═══════════════════════════════════════════════════════════════════════════
14
+
15
+ export interface SecretboxPayload {
16
+ /** Scheme identifier for format detection */
17
+ scheme: 'nacl.secretbox';
18
+ /** Nonce (base64, 24 bytes) */
19
+ nonce: string;
20
+ /** Ciphertext (base64, includes auth tag) */
21
+ ciphertext: string;
22
+ }
23
+
24
+ // ═══════════════════════════════════════════════════════════════════════════
25
+ // ENCRYPTION
26
+ // ═══════════════════════════════════════════════════════════════════════════
27
+
28
+ /**
29
+ * Encrypt data using NaCl secretbox (XSalsa20-Poly1305).
30
+ *
31
+ * @param key - 32-byte symmetric key
32
+ * @param plaintext - Data to encrypt
33
+ * @param nonce - Optional 24-byte nonce (generated if not provided)
34
+ * @returns Encrypted payload with nonce and ciphertext
35
+ */
36
+ export function secretboxEncrypt(
37
+ key: Uint8Array,
38
+ plaintext: Uint8Array,
39
+ nonce?: Uint8Array
40
+ ): SecretboxPayload {
41
+ assertLen('secretbox key', key, 32);
42
+
43
+ const n = nonce ?? rand24();
44
+ assertLen('nonce', n, 24);
45
+
46
+ const ciphertext = nacl.secretbox(plaintext, n, key);
47
+
48
+ return {
49
+ scheme: 'nacl.secretbox' as const,
50
+ nonce: toB64(n),
51
+ ciphertext: toB64(ciphertext),
52
+ };
53
+ }
54
+
55
+ /**
56
+ * Encrypt a string using NaCl secretbox.
57
+ */
58
+ export function secretboxEncryptString(
59
+ key: Uint8Array,
60
+ plaintext: string,
61
+ nonce?: Uint8Array
62
+ ): SecretboxPayload {
63
+ return secretboxEncrypt(key, new TextEncoder().encode(plaintext), nonce);
64
+ }
65
+
66
+ // ═══════════════════════════════════════════════════════════════════════════
67
+ // DECRYPTION
68
+ // ═══════════════════════════════════════════════════════════════════════════
69
+
70
+ /**
71
+ * Decrypt data using NaCl secretbox.
72
+ *
73
+ * @param key - 32-byte symmetric key
74
+ * @param payload - Encrypted payload from secretboxEncrypt
75
+ * @returns Decrypted data, or null if authentication fails
76
+ */
77
+ export function secretboxDecrypt(
78
+ key: Uint8Array,
79
+ payload: SecretboxPayload
80
+ ): Uint8Array | null {
81
+ if (payload.scheme !== 'nacl.secretbox') {
82
+ return null;
83
+ }
84
+ assertLen('secretbox key', key, 32);
85
+
86
+ const nonce = fromB64(payload.nonce);
87
+ const ciphertext = fromB64(payload.ciphertext);
88
+
89
+ return nacl.secretbox.open(ciphertext, nonce, key) || null;
90
+ }
91
+
92
+ /**
93
+ * Decrypt to a string using NaCl secretbox.
94
+ */
95
+ export function secretboxDecryptString(
96
+ key: Uint8Array,
97
+ payload: SecretboxPayload
98
+ ): string | null {
99
+ const result = secretboxDecrypt(key, payload);
100
+ if (!result) return null;
101
+ return new TextDecoder().decode(result);
102
+ }
103
+
104
+ // ═══════════════════════════════════════════════════════════════════════════
105
+ // RAW OPERATIONS (for low-level use)
106
+ // ═══════════════════════════════════════════════════════════════════════════
107
+
108
+ /**
109
+ * Raw secretbox encryption (returns raw bytes).
110
+ */
111
+ export function secretboxRaw(
112
+ key: Uint8Array,
113
+ plaintext: Uint8Array,
114
+ nonce: Uint8Array
115
+ ): Uint8Array {
116
+ assertLen('secretbox key', key, 32);
117
+ assertLen('nonce', nonce, 24);
118
+ return nacl.secretbox(plaintext, nonce, key);
119
+ }
120
+
121
+ /**
122
+ * Raw secretbox decryption (returns raw bytes).
123
+ */
124
+ export function secretboxOpenRaw(
125
+ key: Uint8Array,
126
+ ciphertext: Uint8Array,
127
+ nonce: Uint8Array
128
+ ): Uint8Array | null {
129
+ assertLen('secretbox key', key, 32);
130
+ assertLen('nonce', nonce, 24);
131
+ return nacl.secretbox.open(ciphertext, nonce, key) || null;
132
+ }
133
+
134
+ // ═══════════════════════════════════════════════════════════════════════════
135
+ // BOX OPERATIONS (authenticated public-key encryption)
136
+ // ═══════════════════════════════════════════════════════════════════════════
137
+
138
+ export interface BoxPayload {
139
+ /** Nonce (base64, 24 bytes) */
140
+ nonce: string;
141
+ /** Ciphertext (base64) */
142
+ ciphertext: string;
143
+ }
144
+
145
+ /**
146
+ * Encrypt data using NaCl box (X25519 + XSalsa20-Poly1305).
147
+ *
148
+ * @param plaintext - Data to encrypt
149
+ * @param nonce - 24-byte nonce
150
+ * @param recipientPubKey - Recipient's X25519 public key (32 bytes)
151
+ * @param senderSecKey - Sender's X25519 secret key (32 bytes)
152
+ * @returns Encrypted ciphertext
153
+ */
154
+ export function boxEncrypt(
155
+ plaintext: Uint8Array,
156
+ nonce: Uint8Array,
157
+ recipientPubKey: Uint8Array,
158
+ senderSecKey: Uint8Array
159
+ ): Uint8Array {
160
+ assertLen('nonce', nonce, 24);
161
+ assertLen('recipient pubKey', recipientPubKey, 32);
162
+ assertLen('sender secKey', senderSecKey, 32);
163
+ return nacl.box(plaintext, nonce, recipientPubKey, senderSecKey);
164
+ }
165
+
166
+ /**
167
+ * Decrypt data using NaCl box.
168
+ *
169
+ * @param ciphertext - Encrypted data
170
+ * @param nonce - 24-byte nonce
171
+ * @param senderPubKey - Sender's X25519 public key (32 bytes)
172
+ * @param recipientSecKey - Recipient's X25519 secret key (32 bytes)
173
+ * @returns Decrypted data, or null if authentication fails
174
+ */
175
+ export function boxDecrypt(
176
+ ciphertext: Uint8Array,
177
+ nonce: Uint8Array,
178
+ senderPubKey: Uint8Array,
179
+ recipientSecKey: Uint8Array
180
+ ): Uint8Array | null {
181
+ assertLen('nonce', nonce, 24);
182
+ assertLen('sender pubKey', senderPubKey, 32);
183
+ assertLen('recipient secKey', recipientSecKey, 32);
184
+ return nacl.box.open(ciphertext, nonce, senderPubKey, recipientSecKey) || null;
185
+ }
186
+
187
+ // ═══════════════════════════════════════════════════════════════════════════
188
+ // CONSTANTS
189
+ // ═══════════════════════════════════════════════════════════════════════════
190
+
191
+ /** NaCl secretbox key size (32 bytes) */
192
+ export const SECRETBOX_KEY_SIZE = nacl.secretbox.keyLength;
193
+
194
+ /** NaCl secretbox nonce size (24 bytes) */
195
+ export const SECRETBOX_NONCE_SIZE = nacl.secretbox.nonceLength;
196
+
197
+ /** NaCl secretbox overhead (16 bytes auth tag) */
198
+ export const SECRETBOX_OVERHEAD = nacl.secretbox.overheadLength;
199
+
200
+ /** NaCl box key size (32 bytes) */
201
+ export const BOX_KEY_SIZE = nacl.box.publicKeyLength;
202
+
203
+ /** NaCl box nonce size (24 bytes) */
204
+ export const BOX_NONCE_SIZE = nacl.box.nonceLength;
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Omnituum PQC Shared - BLAKE3 Hash Primitive
3
+ *
4
+ * BLAKE3 is a cryptographic hash function that provides:
5
+ * - Fast performance (faster than SHA-256, SHA-3)
6
+ * - 256-bit security (collision resistance)
7
+ * - Variable output length (default 32 bytes)
8
+ *
9
+ * Used in Noise protocols for transcript hashing.
10
+ */
11
+
12
+ import { blake3 as nobleBlake3 } from '@noble/hashes/blake3';
13
+
14
+ // ═══════════════════════════════════════════════════════════════════════════
15
+ // TYPES
16
+ // ═══════════════════════════════════════════════════════════════════════════
17
+
18
+ export interface Blake3Options {
19
+ /** Output length in bytes (default: 32) */
20
+ outputLength?: number;
21
+ /** Optional key for keyed hashing (32 bytes) */
22
+ key?: Uint8Array;
23
+ /** Optional context string for domain separation */
24
+ context?: string;
25
+ }
26
+
27
+ // ═══════════════════════════════════════════════════════════════════════════
28
+ // BLAKE3 HASH
29
+ // ═══════════════════════════════════════════════════════════════════════════
30
+
31
+ /**
32
+ * Compute BLAKE3 hash of input data.
33
+ *
34
+ * @param data - Data to hash (Uint8Array or string)
35
+ * @param options - Optional configuration
36
+ * @returns BLAKE3 hash (default 32 bytes)
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * // Simple hash
41
+ * const hash = blake3(new Uint8Array([1, 2, 3]));
42
+ *
43
+ * // Hash with context (domain separation)
44
+ * const hash = blake3(data, { context: 'MyApp v1.0 signing' });
45
+ *
46
+ * // Keyed hash (requires 32-byte key)
47
+ * const hash = blake3(data, { key: keyBytes });
48
+ *
49
+ * // Variable output length
50
+ * const hash = blake3(data, { outputLength: 64 });
51
+ * ```
52
+ */
53
+ export function blake3(
54
+ data: Uint8Array | string,
55
+ options?: Blake3Options
56
+ ): Uint8Array {
57
+ const input = typeof data === 'string'
58
+ ? new TextEncoder().encode(data)
59
+ : data;
60
+
61
+ // @noble/hashes blake3 supports key and context options
62
+ const opts: { dkLen?: number; key?: Uint8Array; context?: Uint8Array } = {};
63
+
64
+ if (options?.outputLength) {
65
+ opts.dkLen = options.outputLength;
66
+ }
67
+
68
+ if (options?.key) {
69
+ if (options.key.length !== 32) {
70
+ throw new Error('BLAKE3 key must be exactly 32 bytes');
71
+ }
72
+ opts.key = options.key;
73
+ }
74
+
75
+ if (options?.context) {
76
+ opts.context = new TextEncoder().encode(options.context);
77
+ }
78
+
79
+ return nobleBlake3(input, opts);
80
+ }
81
+
82
+ /**
83
+ * Compute BLAKE3 hash and return as hex string.
84
+ */
85
+ export function blake3Hex(
86
+ data: Uint8Array | string,
87
+ options?: Blake3Options
88
+ ): string {
89
+ const hash = blake3(data, options);
90
+ return Array.from(hash)
91
+ .map(b => b.toString(16).padStart(2, '0'))
92
+ .join('');
93
+ }
94
+
95
+ /**
96
+ * Create a keyed BLAKE3 hash (MAC).
97
+ *
98
+ * @param key - 32-byte key
99
+ * @param data - Data to hash
100
+ * @returns BLAKE3-MAC (32 bytes by default)
101
+ */
102
+ export function blake3Mac(
103
+ key: Uint8Array,
104
+ data: Uint8Array,
105
+ outputLength = 32
106
+ ): Uint8Array {
107
+ if (key.length !== 32) {
108
+ throw new Error('BLAKE3 MAC key must be exactly 32 bytes');
109
+ }
110
+ return blake3(data, { key, outputLength });
111
+ }
112
+
113
+ /**
114
+ * Derive a key from a context and key material using BLAKE3.
115
+ * This uses BLAKE3's built-in KDF mode.
116
+ *
117
+ * @param context - Domain separation string
118
+ * @param keyMaterial - Input key material
119
+ * @param outputLength - Desired output length (default 32)
120
+ * @returns Derived key
121
+ */
122
+ export function blake3DeriveKey(
123
+ context: string,
124
+ keyMaterial: Uint8Array,
125
+ outputLength = 32
126
+ ): Uint8Array {
127
+ return blake3(keyMaterial, { context, outputLength });
128
+ }
129
+
130
+ // ═══════════════════════════════════════════════════════════════════════════
131
+ // CONSTANTS
132
+ // ═══════════════════════════════════════════════════════════════════════════
133
+
134
+ /** Default BLAKE3 output length (32 bytes = 256 bits) */
135
+ export const BLAKE3_OUTPUT_LENGTH = 32;
136
+
137
+ /** BLAKE3 key length for keyed mode (32 bytes) */
138
+ export const BLAKE3_KEY_LENGTH = 32;
139
+
140
+ /** BLAKE3 block size (64 bytes) */
141
+ export const BLAKE3_BLOCK_SIZE = 64;