@f0rest8/metamorphic-crypto 0.5.0 → 0.7.0
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/README.md +14 -3
- package/metamorphic_crypto.d.ts +56 -3
- package/metamorphic_crypto.js +240 -1
- package/metamorphic_crypto_bg.wasm +0 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @f0rest8/metamorphic-crypto
|
|
2
2
|
|
|
3
|
-
Zero-knowledge end-to-end encryption with post-quantum hybrid KEM (ML-KEM-768/1024 + X25519).
|
|
3
|
+
Zero-knowledge end-to-end encryption with post-quantum hybrid KEM (ML-KEM-512/768/1024 + X25519).
|
|
4
4
|
|
|
5
5
|
Built for [Metamorphic](https://metamorphic.app) and [Mosslet](https://mosslet.com) — privacy-first apps by [Moss Piglet Corporation](https://mosspiglet.dev) where all user data is encrypted client-side and the server only stores opaque ciphertext.
|
|
6
6
|
|
|
@@ -103,7 +103,17 @@ import { generateHybridKeyPair1024, sealForUserWithLevel } from "@f0rest8/metamo
|
|
|
103
103
|
|
|
104
104
|
const pq5 = generateHybridKeyPair1024(); // { publicKey, secretKey } (ML-KEM-1024)
|
|
105
105
|
const sealed = sealForUserWithLevel(plaintextBase64, x25519.publicKey, pq5.publicKey, "cat5");
|
|
106
|
-
// unsealFromUser auto-detects Cat-3 vs Cat-5, no level param needed
|
|
106
|
+
// unsealFromUser auto-detects Cat-1 vs Cat-3 vs Cat-5, no level param needed
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Cat-1 (ML-KEM-512, opt-in)
|
|
110
|
+
|
|
111
|
+
```js
|
|
112
|
+
import { generateHybridKeyPair512, sealForUserWithLevel } from "@f0rest8/metamorphic-crypto";
|
|
113
|
+
|
|
114
|
+
const pq1 = generateHybridKeyPair512(); // { publicKey, secretKey } (ML-KEM-512)
|
|
115
|
+
const sealed = sealForUserWithLevel(plaintextBase64, x25519.publicKey, pq1.publicKey, "cat1");
|
|
116
|
+
// unsealFromUser auto-detects the level from the version tag, no level param needed
|
|
107
117
|
```
|
|
108
118
|
|
|
109
119
|
### Private key management
|
|
@@ -212,10 +222,11 @@ across native Rust, WASM, and the Elixir NIF.
|
|
|
212
222
|
|
|
213
223
|
| Level | ML-KEM | NIST Category | Equivalent | Default |
|
|
214
224
|
|-------|--------|---------------|------------|---------|
|
|
225
|
+
| Cat-1 | 512 | 1 | ~AES-128 | No |
|
|
215
226
|
| Cat-3 | 768 | 3 | ~AES-192 | Yes |
|
|
216
227
|
| Cat-5 | 1024 | 5 | ~AES-256 | No |
|
|
217
228
|
|
|
218
|
-
Decryption always auto-detects the level from the ciphertext version tag.
|
|
229
|
+
Decryption always auto-detects the level from the ciphertext version tag. NIST (FIPS 203) standardizes ML-KEM only at categories 1/3/5 — there is no category-2/4 set. The classical half is X25519 (~Cat-1 classical) at every tier; at Cat-3/Cat-5 the post-quantum half dominates and X25519 is the classical floor (standard hybrid-KEM practice).
|
|
219
230
|
|
|
220
231
|
## Security properties
|
|
221
232
|
|
package/metamorphic_crypto.d.ts
CHANGED
|
@@ -72,6 +72,16 @@ export function generateHybridKeyPair(): any;
|
|
|
72
72
|
*/
|
|
73
73
|
export function generateHybridKeyPair1024(): any;
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Generate a ML-KEM-512 + X25519 keypair (Cat-1). Returns JSON: `{ publicKey, secretKey }`.
|
|
77
|
+
*/
|
|
78
|
+
export function generateHybridKeyPair512(): any;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Generate a keypair for `(suite, level)`. Returns JSON: `{ publicKey, secretKey }`.
|
|
82
|
+
*/
|
|
83
|
+
export function generateHybridKeyPairSuite(suite: string, level: string): any;
|
|
84
|
+
|
|
75
85
|
/**
|
|
76
86
|
* Generate a random 32-byte symmetric key (base64).
|
|
77
87
|
*/
|
|
@@ -100,6 +110,35 @@ export function generateSalt(): string;
|
|
|
100
110
|
*/
|
|
101
111
|
export function generateSigningKeyPair(level: string): any;
|
|
102
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Generate a signing keypair for a full CNSA-2.0 `(suite, level)`.
|
|
115
|
+
*
|
|
116
|
+
* `suite` is `"hybrid"` (default), `"hybridMatched"` (Cat-3→Ed448,
|
|
117
|
+
* Cat-5→ECDSA-P-521), or `"pureCnsa2"` (ML-DSA-87 only, Cat-5). `level` is
|
|
118
|
+
* `"cat2"`/`"cat3"`/`"cat5"`. `sign` / `verify` / `deriveSigningPublicKey`
|
|
119
|
+
* auto-detect the suite from the key/signature version tag, so no suite
|
|
120
|
+
* argument is needed there. Returns JSON: `{ publicKey, secretKey }`.
|
|
121
|
+
*/
|
|
122
|
+
export function generateSigningKeyPairSuite(suite: string, level: string): any;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Open a CNSA-2.0 (or legacy) hybrid ciphertext, supplying the context label
|
|
126
|
+
* used at seal time for the new suites. Returns base64-encoded plaintext.
|
|
127
|
+
*/
|
|
128
|
+
export function hybridOpenWithContext(ciphertext_b64: string, seed_b64: string, context_label: string): string;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Seal plaintext (base64) to a `(suite, level)` combined public key, binding
|
|
132
|
+
* the default `"metamorphic/seal/v1"` context label. Returns base64 ciphertext.
|
|
133
|
+
*/
|
|
134
|
+
export function hybridSealSuite(plaintext_b64: string, combined_pk_b64: string, suite: string, level: string): string;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Seal plaintext (base64) to a `(suite, level)` combined public key, binding a
|
|
138
|
+
* custom `context_label`. Returns base64 ciphertext.
|
|
139
|
+
*/
|
|
140
|
+
export function hybridSealSuiteWithContext(plaintext_b64: string, combined_pk_b64: string, suite: string, level: string, context_label: string): string;
|
|
141
|
+
|
|
103
142
|
/**
|
|
104
143
|
* Check if a base64 ciphertext is hybrid (v2/v3) format.
|
|
105
144
|
*/
|
|
@@ -123,11 +162,18 @@ export function sealForUser(plaintext_b64: string, public_key_b64: string, pq_pu
|
|
|
123
162
|
/**
|
|
124
163
|
* Seal plaintext bytes (base64) to a user's key(s) at a specific security level.
|
|
125
164
|
*
|
|
126
|
-
* `level` must be `"
|
|
165
|
+
* `level` must be `"cat1"` (ML-KEM-512), `"cat3"` (ML-KEM-768, default), or
|
|
166
|
+
* `"cat5"` (ML-KEM-1024).
|
|
127
167
|
* If `pq_public_key_b64` is absent or empty, falls back to legacy X25519.
|
|
128
168
|
*/
|
|
129
169
|
export function sealForUserWithLevel(plaintext_b64: string, public_key_b64: string, pq_public_key_b64: string | null | undefined, level: string): string;
|
|
130
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Seal plaintext (base64) to a user's key(s) under a full `(suite, level)`.
|
|
173
|
+
* Falls back to legacy X25519 if `pq_public_key_b64` is absent/empty.
|
|
174
|
+
*/
|
|
175
|
+
export function sealForUserWithSuite(plaintext_b64: string, public_key_b64: string, pq_public_key_b64: string | null | undefined, suite: string, level: string): string;
|
|
176
|
+
|
|
131
177
|
/**
|
|
132
178
|
* SHA-256 (SHA-2) digest of base64-encoded `data`. Returns the 32-byte digest as base64.
|
|
133
179
|
*/
|
|
@@ -192,9 +238,15 @@ export interface InitOutput {
|
|
|
192
238
|
readonly sealForUser: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
193
239
|
readonly unsealFromUser: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void;
|
|
194
240
|
readonly sealForUserWithLevel: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void;
|
|
241
|
+
readonly generateHybridKeyPair512: () => number;
|
|
195
242
|
readonly generateHybridKeyPair: () => number;
|
|
196
243
|
readonly generateHybridKeyPair1024: () => number;
|
|
197
244
|
readonly isHybridCiphertext: (a: number, b: number) => number;
|
|
245
|
+
readonly generateHybridKeyPairSuite: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
246
|
+
readonly hybridSealSuite: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void;
|
|
247
|
+
readonly hybridSealSuiteWithContext: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number) => void;
|
|
248
|
+
readonly hybridOpenWithContext: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
249
|
+
readonly sealForUserWithSuite: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number) => void;
|
|
198
250
|
readonly generateKey: (a: number) => void;
|
|
199
251
|
readonly generateKeyPair: () => number;
|
|
200
252
|
readonly generateSalt: (a: number) => void;
|
|
@@ -209,13 +261,14 @@ export interface InitOutput {
|
|
|
209
261
|
readonly sha256: (a: number, b: number, c: number) => void;
|
|
210
262
|
readonly sha512: (a: number, b: number, c: number) => void;
|
|
211
263
|
readonly generateSigningKeyPair: (a: number, b: number, c: number) => void;
|
|
264
|
+
readonly generateSigningKeyPairSuite: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
212
265
|
readonly deriveSigningPublicKey: (a: number, b: number, c: number) => void;
|
|
213
266
|
readonly sign: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
214
267
|
readonly verify: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void;
|
|
268
|
+
readonly decryptPrivateKeyWithRecovery: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
269
|
+
readonly decryptSecretboxToString: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
215
270
|
readonly encryptSecretboxString: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
216
271
|
readonly encryptPrivateKeyForRecovery: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
217
|
-
readonly decryptSecretboxToString: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
218
|
-
readonly decryptPrivateKeyWithRecovery: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
219
272
|
readonly __wbindgen_export: (a: number, b: number) => number;
|
|
220
273
|
readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
|
|
221
274
|
readonly __wbindgen_export3: (a: number) => void;
|
package/metamorphic_crypto.js
CHANGED
|
@@ -439,6 +439,41 @@ export function generateHybridKeyPair1024() {
|
|
|
439
439
|
return takeObject(ret);
|
|
440
440
|
}
|
|
441
441
|
|
|
442
|
+
/**
|
|
443
|
+
* Generate a ML-KEM-512 + X25519 keypair (Cat-1). Returns JSON: `{ publicKey, secretKey }`.
|
|
444
|
+
* @returns {any}
|
|
445
|
+
*/
|
|
446
|
+
export function generateHybridKeyPair512() {
|
|
447
|
+
const ret = wasm.generateHybridKeyPair512();
|
|
448
|
+
return takeObject(ret);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Generate a keypair for `(suite, level)`. Returns JSON: `{ publicKey, secretKey }`.
|
|
453
|
+
* @param {string} suite
|
|
454
|
+
* @param {string} level
|
|
455
|
+
* @returns {any}
|
|
456
|
+
*/
|
|
457
|
+
export function generateHybridKeyPairSuite(suite, level) {
|
|
458
|
+
try {
|
|
459
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
460
|
+
const ptr0 = passStringToWasm0(suite, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
461
|
+
const len0 = WASM_VECTOR_LEN;
|
|
462
|
+
const ptr1 = passStringToWasm0(level, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
463
|
+
const len1 = WASM_VECTOR_LEN;
|
|
464
|
+
wasm.generateHybridKeyPairSuite(retptr, ptr0, len0, ptr1, len1);
|
|
465
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
466
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
467
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
468
|
+
if (r2) {
|
|
469
|
+
throw takeObject(r1);
|
|
470
|
+
}
|
|
471
|
+
return takeObject(r0);
|
|
472
|
+
} finally {
|
|
473
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
442
477
|
/**
|
|
443
478
|
* Generate a random 32-byte symmetric key (base64).
|
|
444
479
|
* @returns {string}
|
|
@@ -536,6 +571,164 @@ export function generateSigningKeyPair(level) {
|
|
|
536
571
|
}
|
|
537
572
|
}
|
|
538
573
|
|
|
574
|
+
/**
|
|
575
|
+
* Generate a signing keypair for a full CNSA-2.0 `(suite, level)`.
|
|
576
|
+
*
|
|
577
|
+
* `suite` is `"hybrid"` (default), `"hybridMatched"` (Cat-3→Ed448,
|
|
578
|
+
* Cat-5→ECDSA-P-521), or `"pureCnsa2"` (ML-DSA-87 only, Cat-5). `level` is
|
|
579
|
+
* `"cat2"`/`"cat3"`/`"cat5"`. `sign` / `verify` / `deriveSigningPublicKey`
|
|
580
|
+
* auto-detect the suite from the key/signature version tag, so no suite
|
|
581
|
+
* argument is needed there. Returns JSON: `{ publicKey, secretKey }`.
|
|
582
|
+
* @param {string} suite
|
|
583
|
+
* @param {string} level
|
|
584
|
+
* @returns {any}
|
|
585
|
+
*/
|
|
586
|
+
export function generateSigningKeyPairSuite(suite, level) {
|
|
587
|
+
try {
|
|
588
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
589
|
+
const ptr0 = passStringToWasm0(suite, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
590
|
+
const len0 = WASM_VECTOR_LEN;
|
|
591
|
+
const ptr1 = passStringToWasm0(level, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
592
|
+
const len1 = WASM_VECTOR_LEN;
|
|
593
|
+
wasm.generateSigningKeyPairSuite(retptr, ptr0, len0, ptr1, len1);
|
|
594
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
595
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
596
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
597
|
+
if (r2) {
|
|
598
|
+
throw takeObject(r1);
|
|
599
|
+
}
|
|
600
|
+
return takeObject(r0);
|
|
601
|
+
} finally {
|
|
602
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Open a CNSA-2.0 (or legacy) hybrid ciphertext, supplying the context label
|
|
608
|
+
* used at seal time for the new suites. Returns base64-encoded plaintext.
|
|
609
|
+
* @param {string} ciphertext_b64
|
|
610
|
+
* @param {string} seed_b64
|
|
611
|
+
* @param {string} context_label
|
|
612
|
+
* @returns {string}
|
|
613
|
+
*/
|
|
614
|
+
export function hybridOpenWithContext(ciphertext_b64, seed_b64, context_label) {
|
|
615
|
+
let deferred5_0;
|
|
616
|
+
let deferred5_1;
|
|
617
|
+
try {
|
|
618
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
619
|
+
const ptr0 = passStringToWasm0(ciphertext_b64, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
620
|
+
const len0 = WASM_VECTOR_LEN;
|
|
621
|
+
const ptr1 = passStringToWasm0(seed_b64, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
622
|
+
const len1 = WASM_VECTOR_LEN;
|
|
623
|
+
const ptr2 = passStringToWasm0(context_label, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
624
|
+
const len2 = WASM_VECTOR_LEN;
|
|
625
|
+
wasm.hybridOpenWithContext(retptr, ptr0, len0, ptr1, len1, ptr2, len2);
|
|
626
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
627
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
628
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
629
|
+
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
|
630
|
+
var ptr4 = r0;
|
|
631
|
+
var len4 = r1;
|
|
632
|
+
if (r3) {
|
|
633
|
+
ptr4 = 0; len4 = 0;
|
|
634
|
+
throw takeObject(r2);
|
|
635
|
+
}
|
|
636
|
+
deferred5_0 = ptr4;
|
|
637
|
+
deferred5_1 = len4;
|
|
638
|
+
return getStringFromWasm0(ptr4, len4);
|
|
639
|
+
} finally {
|
|
640
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
641
|
+
wasm.__wbindgen_export4(deferred5_0, deferred5_1, 1);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* Seal plaintext (base64) to a `(suite, level)` combined public key, binding
|
|
647
|
+
* the default `"metamorphic/seal/v1"` context label. Returns base64 ciphertext.
|
|
648
|
+
* @param {string} plaintext_b64
|
|
649
|
+
* @param {string} combined_pk_b64
|
|
650
|
+
* @param {string} suite
|
|
651
|
+
* @param {string} level
|
|
652
|
+
* @returns {string}
|
|
653
|
+
*/
|
|
654
|
+
export function hybridSealSuite(plaintext_b64, combined_pk_b64, suite, level) {
|
|
655
|
+
let deferred6_0;
|
|
656
|
+
let deferred6_1;
|
|
657
|
+
try {
|
|
658
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
659
|
+
const ptr0 = passStringToWasm0(plaintext_b64, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
660
|
+
const len0 = WASM_VECTOR_LEN;
|
|
661
|
+
const ptr1 = passStringToWasm0(combined_pk_b64, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
662
|
+
const len1 = WASM_VECTOR_LEN;
|
|
663
|
+
const ptr2 = passStringToWasm0(suite, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
664
|
+
const len2 = WASM_VECTOR_LEN;
|
|
665
|
+
const ptr3 = passStringToWasm0(level, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
666
|
+
const len3 = WASM_VECTOR_LEN;
|
|
667
|
+
wasm.hybridSealSuite(retptr, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3);
|
|
668
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
669
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
670
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
671
|
+
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
|
672
|
+
var ptr5 = r0;
|
|
673
|
+
var len5 = r1;
|
|
674
|
+
if (r3) {
|
|
675
|
+
ptr5 = 0; len5 = 0;
|
|
676
|
+
throw takeObject(r2);
|
|
677
|
+
}
|
|
678
|
+
deferred6_0 = ptr5;
|
|
679
|
+
deferred6_1 = len5;
|
|
680
|
+
return getStringFromWasm0(ptr5, len5);
|
|
681
|
+
} finally {
|
|
682
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
683
|
+
wasm.__wbindgen_export4(deferred6_0, deferred6_1, 1);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* Seal plaintext (base64) to a `(suite, level)` combined public key, binding a
|
|
689
|
+
* custom `context_label`. Returns base64 ciphertext.
|
|
690
|
+
* @param {string} plaintext_b64
|
|
691
|
+
* @param {string} combined_pk_b64
|
|
692
|
+
* @param {string} suite
|
|
693
|
+
* @param {string} level
|
|
694
|
+
* @param {string} context_label
|
|
695
|
+
* @returns {string}
|
|
696
|
+
*/
|
|
697
|
+
export function hybridSealSuiteWithContext(plaintext_b64, combined_pk_b64, suite, level, context_label) {
|
|
698
|
+
let deferred7_0;
|
|
699
|
+
let deferred7_1;
|
|
700
|
+
try {
|
|
701
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
702
|
+
const ptr0 = passStringToWasm0(plaintext_b64, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
703
|
+
const len0 = WASM_VECTOR_LEN;
|
|
704
|
+
const ptr1 = passStringToWasm0(combined_pk_b64, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
705
|
+
const len1 = WASM_VECTOR_LEN;
|
|
706
|
+
const ptr2 = passStringToWasm0(suite, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
707
|
+
const len2 = WASM_VECTOR_LEN;
|
|
708
|
+
const ptr3 = passStringToWasm0(level, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
709
|
+
const len3 = WASM_VECTOR_LEN;
|
|
710
|
+
const ptr4 = passStringToWasm0(context_label, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
711
|
+
const len4 = WASM_VECTOR_LEN;
|
|
712
|
+
wasm.hybridSealSuiteWithContext(retptr, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, ptr4, len4);
|
|
713
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
714
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
715
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
716
|
+
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
|
717
|
+
var ptr6 = r0;
|
|
718
|
+
var len6 = r1;
|
|
719
|
+
if (r3) {
|
|
720
|
+
ptr6 = 0; len6 = 0;
|
|
721
|
+
throw takeObject(r2);
|
|
722
|
+
}
|
|
723
|
+
deferred7_0 = ptr6;
|
|
724
|
+
deferred7_1 = len6;
|
|
725
|
+
return getStringFromWasm0(ptr6, len6);
|
|
726
|
+
} finally {
|
|
727
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
728
|
+
wasm.__wbindgen_export4(deferred7_0, deferred7_1, 1);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
|
|
539
732
|
/**
|
|
540
733
|
* Check if a base64 ciphertext is hybrid (v2/v3) format.
|
|
541
734
|
* @param {string} ciphertext_b64
|
|
@@ -653,7 +846,8 @@ export function sealForUser(plaintext_b64, public_key_b64, pq_public_key_b64) {
|
|
|
653
846
|
/**
|
|
654
847
|
* Seal plaintext bytes (base64) to a user's key(s) at a specific security level.
|
|
655
848
|
*
|
|
656
|
-
* `level` must be `"
|
|
849
|
+
* `level` must be `"cat1"` (ML-KEM-512), `"cat3"` (ML-KEM-768, default), or
|
|
850
|
+
* `"cat5"` (ML-KEM-1024).
|
|
657
851
|
* If `pq_public_key_b64` is absent or empty, falls back to legacy X25519.
|
|
658
852
|
* @param {string} plaintext_b64
|
|
659
853
|
* @param {string} public_key_b64
|
|
@@ -694,6 +888,51 @@ export function sealForUserWithLevel(plaintext_b64, public_key_b64, pq_public_ke
|
|
|
694
888
|
}
|
|
695
889
|
}
|
|
696
890
|
|
|
891
|
+
/**
|
|
892
|
+
* Seal plaintext (base64) to a user's key(s) under a full `(suite, level)`.
|
|
893
|
+
* Falls back to legacy X25519 if `pq_public_key_b64` is absent/empty.
|
|
894
|
+
* @param {string} plaintext_b64
|
|
895
|
+
* @param {string} public_key_b64
|
|
896
|
+
* @param {string | null | undefined} pq_public_key_b64
|
|
897
|
+
* @param {string} suite
|
|
898
|
+
* @param {string} level
|
|
899
|
+
* @returns {string}
|
|
900
|
+
*/
|
|
901
|
+
export function sealForUserWithSuite(plaintext_b64, public_key_b64, pq_public_key_b64, suite, level) {
|
|
902
|
+
let deferred7_0;
|
|
903
|
+
let deferred7_1;
|
|
904
|
+
try {
|
|
905
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
906
|
+
const ptr0 = passStringToWasm0(plaintext_b64, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
907
|
+
const len0 = WASM_VECTOR_LEN;
|
|
908
|
+
const ptr1 = passStringToWasm0(public_key_b64, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
909
|
+
const len1 = WASM_VECTOR_LEN;
|
|
910
|
+
var ptr2 = isLikeNone(pq_public_key_b64) ? 0 : passStringToWasm0(pq_public_key_b64, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
911
|
+
var len2 = WASM_VECTOR_LEN;
|
|
912
|
+
const ptr3 = passStringToWasm0(suite, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
913
|
+
const len3 = WASM_VECTOR_LEN;
|
|
914
|
+
const ptr4 = passStringToWasm0(level, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
915
|
+
const len4 = WASM_VECTOR_LEN;
|
|
916
|
+
wasm.sealForUserWithSuite(retptr, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, ptr4, len4);
|
|
917
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
918
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
919
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
920
|
+
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
|
921
|
+
var ptr6 = r0;
|
|
922
|
+
var len6 = r1;
|
|
923
|
+
if (r3) {
|
|
924
|
+
ptr6 = 0; len6 = 0;
|
|
925
|
+
throw takeObject(r2);
|
|
926
|
+
}
|
|
927
|
+
deferred7_0 = ptr6;
|
|
928
|
+
deferred7_1 = len6;
|
|
929
|
+
return getStringFromWasm0(ptr6, len6);
|
|
930
|
+
} finally {
|
|
931
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
932
|
+
wasm.__wbindgen_export4(deferred7_0, deferred7_1, 1);
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
|
|
697
936
|
/**
|
|
698
937
|
* SHA-256 (SHA-2) digest of base64-encoded `data`. Returns the 32-byte digest as base64.
|
|
699
938
|
* @param {string} data_b64
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@f0rest8/metamorphic-crypto",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"description": "Zero-knowledge end-to-end encryption with post-quantum hybrid KEM (ML-KEM
|
|
5
|
-
"version": "0.
|
|
4
|
+
"description": "Zero-knowledge end-to-end encryption with post-quantum hybrid KEM (ML-KEM + X25519) and an opt-in CNSA 2.0 suite axis (matched-strength hybrid + pure ML-KEM-1024 / ML-DSA-87 / AES-256-GCM)",
|
|
5
|
+
"version": "0.7.0",
|
|
6
6
|
"license": "MIT OR Apache-2.0",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|