@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.
- package/LICENSE +22 -0
- package/README.md +543 -0
- package/dist/crypto/index.cjs +807 -0
- package/dist/crypto/index.d.cts +641 -0
- package/dist/crypto/index.d.ts +641 -0
- package/dist/crypto/index.js +716 -0
- package/dist/decrypt-eSHlbh1j.d.cts +321 -0
- package/dist/decrypt-eSHlbh1j.d.ts +321 -0
- package/dist/fs/index.cjs +1168 -0
- package/dist/fs/index.d.cts +400 -0
- package/dist/fs/index.d.ts +400 -0
- package/dist/fs/index.js +1091 -0
- package/dist/index.cjs +2160 -0
- package/dist/index.d.cts +282 -0
- package/dist/index.d.ts +282 -0
- package/dist/index.js +2031 -0
- package/dist/integrity-CCYjrap3.d.ts +31 -0
- package/dist/integrity-Dx9jukMH.d.cts +31 -0
- package/dist/types-61c7Q9ri.d.ts +134 -0
- package/dist/types-Ch0y-n7K.d.cts +134 -0
- package/dist/utils/index.cjs +129 -0
- package/dist/utils/index.d.cts +49 -0
- package/dist/utils/index.d.ts +49 -0
- package/dist/utils/index.js +114 -0
- package/dist/vault/index.cjs +713 -0
- package/dist/vault/index.d.cts +237 -0
- package/dist/vault/index.d.ts +237 -0
- package/dist/vault/index.js +677 -0
- package/dist/version-BygzPVGs.d.cts +55 -0
- package/dist/version-BygzPVGs.d.ts +55 -0
- package/package.json +86 -0
- package/src/crypto/dilithium.ts +233 -0
- package/src/crypto/hybrid.ts +358 -0
- package/src/crypto/index.ts +181 -0
- package/src/crypto/kyber.ts +199 -0
- package/src/crypto/nacl.ts +204 -0
- package/src/crypto/primitives/blake3.ts +141 -0
- package/src/crypto/primitives/chacha.ts +211 -0
- package/src/crypto/primitives/hkdf.ts +192 -0
- package/src/crypto/primitives/index.ts +54 -0
- package/src/crypto/primitives.ts +144 -0
- package/src/crypto/x25519.ts +134 -0
- package/src/fs/aes.ts +343 -0
- package/src/fs/argon2.ts +184 -0
- package/src/fs/browser.ts +408 -0
- package/src/fs/decrypt.ts +320 -0
- package/src/fs/encrypt.ts +324 -0
- package/src/fs/format.ts +425 -0
- package/src/fs/index.ts +144 -0
- package/src/fs/types.ts +304 -0
- package/src/index.ts +414 -0
- package/src/kdf/index.ts +311 -0
- package/src/runtime/crypto.ts +16 -0
- package/src/security/index.ts +345 -0
- package/src/tunnel/index.ts +39 -0
- package/src/tunnel/session.ts +229 -0
- package/src/tunnel/types.ts +115 -0
- package/src/utils/entropy.ts +128 -0
- package/src/utils/index.ts +25 -0
- package/src/utils/integrity.ts +95 -0
- package/src/vault/decrypt.ts +167 -0
- package/src/vault/encrypt.ts +207 -0
- package/src/vault/index.ts +71 -0
- package/src/vault/manager.ts +327 -0
- package/src/vault/migrate.ts +190 -0
- package/src/vault/types.ts +177 -0
- package/src/version.ts +304 -0
package/src/version.ts
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Omnituum PQC Shared - Version Constants & Guards
|
|
3
|
+
*
|
|
4
|
+
* FROZEN CONTRACTS: These version strings define the wire format.
|
|
5
|
+
* Breaking changes require a version bump.
|
|
6
|
+
*
|
|
7
|
+
* @see pqc-docs/specs/envelope.v1.md
|
|
8
|
+
* @see pqc-docs/specs/vault.v1.md
|
|
9
|
+
* @see pqc-docs/specs/identity.v1.md
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
13
|
+
// VERSION CONSTANTS (FROZEN)
|
|
14
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
15
|
+
|
|
16
|
+
/** HybridEnvelope version - hybrid encryption format */
|
|
17
|
+
export const ENVELOPE_VERSION = 'omnituum.hybrid.v1' as const;
|
|
18
|
+
|
|
19
|
+
/** Legacy envelope version for backwards compatibility */
|
|
20
|
+
export const ENVELOPE_VERSION_LEGACY = 'pqc-demo.hybrid.v1' as const;
|
|
21
|
+
|
|
22
|
+
/** OmnituumVault version - decrypted vault format */
|
|
23
|
+
export const VAULT_VERSION = 'omnituum.vault.v1' as const;
|
|
24
|
+
|
|
25
|
+
/** EncryptedVaultFile version - encrypted vault format (PBKDF2) */
|
|
26
|
+
export const VAULT_ENCRYPTED_VERSION = 'omnituum.vault.enc.v1' as const;
|
|
27
|
+
|
|
28
|
+
/** EncryptedVaultFile v2 - encrypted vault format (Argon2id) */
|
|
29
|
+
export const VAULT_ENCRYPTED_VERSION_V2 = 'omnituum.vault.enc.v2' as const;
|
|
30
|
+
|
|
31
|
+
/** Algorithm suite for hybrid encryption */
|
|
32
|
+
export const ENVELOPE_SUITE = 'x25519+kyber768' as const;
|
|
33
|
+
|
|
34
|
+
/** AEAD algorithm for envelope content */
|
|
35
|
+
export const ENVELOPE_AEAD = 'xsalsa20poly1305' as const;
|
|
36
|
+
|
|
37
|
+
/** KDF for vault encryption (v1) */
|
|
38
|
+
export const VAULT_KDF = 'PBKDF2-SHA256' as const;
|
|
39
|
+
|
|
40
|
+
/** KDF for vault encryption (v2) */
|
|
41
|
+
export const VAULT_KDF_V2 = 'Argon2id' as const;
|
|
42
|
+
|
|
43
|
+
/** Encryption algorithm for vault */
|
|
44
|
+
export const VAULT_ALGORITHM = 'AES-256-GCM' as const;
|
|
45
|
+
|
|
46
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
47
|
+
// SUPPORTED VERSIONS (for reading)
|
|
48
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
49
|
+
|
|
50
|
+
/** Envelope versions we can read */
|
|
51
|
+
export const SUPPORTED_ENVELOPE_VERSIONS = [
|
|
52
|
+
ENVELOPE_VERSION,
|
|
53
|
+
ENVELOPE_VERSION_LEGACY,
|
|
54
|
+
] as const;
|
|
55
|
+
|
|
56
|
+
/** Vault versions we can read */
|
|
57
|
+
export const SUPPORTED_VAULT_VERSIONS = [
|
|
58
|
+
VAULT_VERSION,
|
|
59
|
+
] as const;
|
|
60
|
+
|
|
61
|
+
/** Encrypted vault versions we can read */
|
|
62
|
+
export const SUPPORTED_VAULT_ENCRYPTED_VERSIONS = [
|
|
63
|
+
VAULT_ENCRYPTED_VERSION,
|
|
64
|
+
VAULT_ENCRYPTED_VERSION_V2,
|
|
65
|
+
] as const;
|
|
66
|
+
|
|
67
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
68
|
+
// VERSION GUARD ERRORS
|
|
69
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
70
|
+
|
|
71
|
+
export class VersionMismatchError extends Error {
|
|
72
|
+
constructor(
|
|
73
|
+
public readonly type: 'envelope' | 'vault' | 'vault_encrypted',
|
|
74
|
+
public readonly expected: readonly string[],
|
|
75
|
+
public readonly received: string
|
|
76
|
+
) {
|
|
77
|
+
super(
|
|
78
|
+
`Version mismatch for ${type}: expected one of [${expected.join(', ')}], got "${received}". ` +
|
|
79
|
+
`This may indicate data corruption or a newer format. ` +
|
|
80
|
+
`See pqc-docs/specs/ for format specifications.`
|
|
81
|
+
);
|
|
82
|
+
this.name = 'VersionMismatchError';
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
87
|
+
// VERSION GUARDS
|
|
88
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Assert envelope version is supported.
|
|
92
|
+
* Throws VersionMismatchError if not.
|
|
93
|
+
*/
|
|
94
|
+
export function assertEnvelopeVersion(version: string): void {
|
|
95
|
+
if (!SUPPORTED_ENVELOPE_VERSIONS.includes(version as typeof SUPPORTED_ENVELOPE_VERSIONS[number])) {
|
|
96
|
+
throw new VersionMismatchError('envelope', SUPPORTED_ENVELOPE_VERSIONS, version);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Assert vault version is supported.
|
|
102
|
+
* Throws VersionMismatchError if not.
|
|
103
|
+
*/
|
|
104
|
+
export function assertVaultVersion(version: string): void {
|
|
105
|
+
if (!SUPPORTED_VAULT_VERSIONS.includes(version as typeof SUPPORTED_VAULT_VERSIONS[number])) {
|
|
106
|
+
throw new VersionMismatchError('vault', SUPPORTED_VAULT_VERSIONS, version);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Assert encrypted vault version is supported.
|
|
112
|
+
* Throws VersionMismatchError if not.
|
|
113
|
+
*/
|
|
114
|
+
export function assertVaultEncryptedVersion(version: string): void {
|
|
115
|
+
if (!SUPPORTED_VAULT_ENCRYPTED_VERSIONS.includes(version as typeof SUPPORTED_VAULT_ENCRYPTED_VERSIONS[number])) {
|
|
116
|
+
throw new VersionMismatchError('vault_encrypted', SUPPORTED_VAULT_ENCRYPTED_VERSIONS, version);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Check if envelope version is supported (non-throwing).
|
|
122
|
+
*/
|
|
123
|
+
export function isEnvelopeVersionSupported(version: string): boolean {
|
|
124
|
+
return SUPPORTED_ENVELOPE_VERSIONS.includes(version as typeof SUPPORTED_ENVELOPE_VERSIONS[number]);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Check if vault version is supported (non-throwing).
|
|
129
|
+
*/
|
|
130
|
+
export function isVaultVersionSupported(version: string): boolean {
|
|
131
|
+
return SUPPORTED_VAULT_VERSIONS.includes(version as typeof SUPPORTED_VAULT_VERSIONS[number]);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Check if encrypted vault version is supported (non-throwing).
|
|
136
|
+
*/
|
|
137
|
+
export function isVaultEncryptedVersionSupported(version: string): boolean {
|
|
138
|
+
return SUPPORTED_VAULT_ENCRYPTED_VERSIONS.includes(version as typeof SUPPORTED_VAULT_ENCRYPTED_VERSIONS[number]);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
142
|
+
// ENVELOPE VALIDATION
|
|
143
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Validate envelope structure and version.
|
|
147
|
+
* Returns detailed validation result.
|
|
148
|
+
*/
|
|
149
|
+
export function validateEnvelope(envelope: unknown): {
|
|
150
|
+
valid: boolean;
|
|
151
|
+
version?: string;
|
|
152
|
+
errors: string[];
|
|
153
|
+
} {
|
|
154
|
+
const errors: string[] = [];
|
|
155
|
+
|
|
156
|
+
if (!envelope || typeof envelope !== 'object') {
|
|
157
|
+
return { valid: false, errors: ['Envelope must be an object'] };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const env = envelope as Record<string, unknown>;
|
|
161
|
+
|
|
162
|
+
// Version check
|
|
163
|
+
if (typeof env.v !== 'string') {
|
|
164
|
+
errors.push('Missing or invalid version field "v"');
|
|
165
|
+
} else if (!isEnvelopeVersionSupported(env.v)) {
|
|
166
|
+
errors.push(`Unsupported envelope version: ${env.v}`);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Suite check
|
|
170
|
+
if (env.suite !== ENVELOPE_SUITE) {
|
|
171
|
+
errors.push(`Invalid suite: expected "${ENVELOPE_SUITE}", got "${env.suite}"`);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// AEAD check
|
|
175
|
+
if (env.aead !== ENVELOPE_AEAD) {
|
|
176
|
+
errors.push(`Invalid aead: expected "${ENVELOPE_AEAD}", got "${env.aead}"`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Required fields
|
|
180
|
+
const required = ['x25519Epk', 'x25519Wrap', 'kyberKemCt', 'kyberWrap', 'contentNonce', 'ciphertext', 'meta'];
|
|
181
|
+
for (const field of required) {
|
|
182
|
+
if (!(field in env)) {
|
|
183
|
+
errors.push(`Missing required field: ${field}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return {
|
|
188
|
+
valid: errors.length === 0,
|
|
189
|
+
version: typeof env.v === 'string' ? env.v : undefined,
|
|
190
|
+
errors,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Validate vault structure and version.
|
|
196
|
+
*/
|
|
197
|
+
export function validateVault(vault: unknown): {
|
|
198
|
+
valid: boolean;
|
|
199
|
+
version?: string;
|
|
200
|
+
errors: string[];
|
|
201
|
+
} {
|
|
202
|
+
const errors: string[] = [];
|
|
203
|
+
|
|
204
|
+
if (!vault || typeof vault !== 'object') {
|
|
205
|
+
return { valid: false, errors: ['Vault must be an object'] };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const v = vault as Record<string, unknown>;
|
|
209
|
+
|
|
210
|
+
// Version check
|
|
211
|
+
if (typeof v.version !== 'string') {
|
|
212
|
+
errors.push('Missing or invalid version field');
|
|
213
|
+
} else if (!isVaultVersionSupported(v.version)) {
|
|
214
|
+
errors.push(`Unsupported vault version: ${v.version}`);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Required fields
|
|
218
|
+
if (!Array.isArray(v.identities)) {
|
|
219
|
+
errors.push('Missing or invalid identities array');
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (!v.settings || typeof v.settings !== 'object') {
|
|
223
|
+
errors.push('Missing or invalid settings object');
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (typeof v.integrityHash !== 'string') {
|
|
227
|
+
errors.push('Missing or invalid integrityHash');
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (typeof v.createdAt !== 'string') {
|
|
231
|
+
errors.push('Missing or invalid createdAt timestamp');
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (typeof v.modifiedAt !== 'string') {
|
|
235
|
+
errors.push('Missing or invalid modifiedAt timestamp');
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
valid: errors.length === 0,
|
|
240
|
+
version: typeof v.version === 'string' ? v.version : undefined,
|
|
241
|
+
errors,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Validate encrypted vault structure and version.
|
|
247
|
+
*/
|
|
248
|
+
export function validateEncryptedVault(encVault: unknown): {
|
|
249
|
+
valid: boolean;
|
|
250
|
+
version?: string;
|
|
251
|
+
errors: string[];
|
|
252
|
+
} {
|
|
253
|
+
const errors: string[] = [];
|
|
254
|
+
|
|
255
|
+
if (!encVault || typeof encVault !== 'object') {
|
|
256
|
+
return { valid: false, errors: ['Encrypted vault must be an object'] };
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const v = encVault as Record<string, unknown>;
|
|
260
|
+
|
|
261
|
+
// Version check
|
|
262
|
+
if (typeof v.version !== 'string') {
|
|
263
|
+
errors.push('Missing or invalid version field');
|
|
264
|
+
} else if (!isVaultEncryptedVersionSupported(v.version)) {
|
|
265
|
+
errors.push(`Unsupported encrypted vault version: ${v.version}`);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// KDF check (v1 uses PBKDF2, v2 uses Argon2id)
|
|
269
|
+
if (v.version === VAULT_ENCRYPTED_VERSION && v.kdf !== VAULT_KDF) {
|
|
270
|
+
errors.push(`Invalid kdf for v1: expected "${VAULT_KDF}", got "${v.kdf}"`);
|
|
271
|
+
} else if (v.version === VAULT_ENCRYPTED_VERSION_V2 && v.kdf !== VAULT_KDF_V2) {
|
|
272
|
+
errors.push(`Invalid kdf for v2: expected "${VAULT_KDF_V2}", got "${v.kdf}"`);
|
|
273
|
+
} else if (v.kdf !== VAULT_KDF && v.kdf !== VAULT_KDF_V2) {
|
|
274
|
+
errors.push(`Unsupported kdf: ${v.kdf}`);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Algorithm check
|
|
278
|
+
if (v.algorithm !== VAULT_ALGORITHM) {
|
|
279
|
+
errors.push(`Invalid algorithm: expected "${VAULT_ALGORITHM}", got "${v.algorithm}"`);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Required fields
|
|
283
|
+
if (typeof v.iterations !== 'number' || v.iterations < 1) {
|
|
284
|
+
errors.push('Missing or invalid iterations');
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (typeof v.salt !== 'string') {
|
|
288
|
+
errors.push('Missing or invalid salt');
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (typeof v.iv !== 'string') {
|
|
292
|
+
errors.push('Missing or invalid iv');
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (typeof v.ciphertext !== 'string') {
|
|
296
|
+
errors.push('Missing or invalid ciphertext');
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return {
|
|
300
|
+
valid: errors.length === 0,
|
|
301
|
+
version: typeof v.version === 'string' ? v.version : undefined,
|
|
302
|
+
errors,
|
|
303
|
+
};
|
|
304
|
+
}
|