@f0rest8/metamorphic-crypto 0.6.0 → 0.7.1
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 +44 -1
- package/metamorphic_crypto.d.ts +49 -3
- package/metamorphic_crypto.js +246 -17
- 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-512/768/1024 + X25519).
|
|
3
|
+
Zero-knowledge end-to-end encryption with post-quantum hybrid KEM (ML-KEM-512/768/1024 + X25519), hybrid PQ signatures (ML-DSA + Ed25519), and an opt-in CNSA 2.0 suite axis.
|
|
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
|
|
|
@@ -218,6 +218,49 @@ across native Rust, WASM, and the Elixir NIF.
|
|
|
218
218
|
> composite remains at least as strong as Ed25519 even if a flaw is found in the
|
|
219
219
|
> young post-quantum implementation. Pinned and tracked for the FIPS-mode roadmap.
|
|
220
220
|
|
|
221
|
+
### CNSA 2.0 suite axis (opt-in)
|
|
222
|
+
|
|
223
|
+
Everything above is the default **`hybrid`** suite (classical+PQ strict-AND). If
|
|
224
|
+
you have no specific mandate, that is the recommended choice. For deployments
|
|
225
|
+
that must follow the NSA's **CNSA 2.0** suite (NIST IR 8547), a `suite` argument
|
|
226
|
+
raises the posture. It is **orthogonal** to the `"cat1"`/`"cat3"`/`"cat5"` level,
|
|
227
|
+
so you have two independent knobs.
|
|
228
|
+
|
|
229
|
+
| `suite` string | What it is | Status |
|
|
230
|
+
|----------------|------------|--------|
|
|
231
|
+
| `"hybrid"` | Existing classical+PQ strict-AND. Byte-for-byte unchanged. | **Default, recommended** |
|
|
232
|
+
| `"hybridMatched"` | Classical partner matched to the PQ category (KEM: Cat-3→X448, Cat-5→P-521 · Sign: Cat-3→Ed448, Cat-5→ECDSA-P-521) | Opt-in |
|
|
233
|
+
| `"pureCnsa2"` | Pure post-quantum, no classical half (ML-KEM-1024 / AES-256-GCM; ML-DSA-87) | Opt-in, **Cat-5 only** |
|
|
234
|
+
|
|
235
|
+
```js
|
|
236
|
+
import {
|
|
237
|
+
generateHybridKeyPairSuite, hybridSealSuite, hybridOpenWithContext,
|
|
238
|
+
generateSigningKeyPairSuite, sign, verify,
|
|
239
|
+
} from "@f0rest8/metamorphic-crypto";
|
|
240
|
+
|
|
241
|
+
// Pure CNSA-2.0 KEM box (ML-KEM-1024 + AES-256-GCM)
|
|
242
|
+
const kp = generateHybridKeyPairSuite("pureCnsa2", "cat5"); // { publicKey, secretKey }
|
|
243
|
+
const sealed = hybridSealSuite(plaintextBase64, kp.publicKey, "pureCnsa2", "cat5");
|
|
244
|
+
// Open with the context label used at seal time (default "metamorphic/seal/v1"):
|
|
245
|
+
const opened = hybridOpenWithContext(sealed, kp.secretKey, "metamorphic/seal/v1"); // base64
|
|
246
|
+
|
|
247
|
+
// Pure ML-DSA-87 signatures — sign/verify auto-detect the suite from the tag
|
|
248
|
+
const sk = generateSigningKeyPairSuite("pureCnsa2", "cat5");
|
|
249
|
+
const sig = sign(btoa("checkpoint"), "metamorphic/sign/v1", sk.secretKey);
|
|
250
|
+
const ok = verify(btoa("checkpoint"), "metamorphic/sign/v1", sig, sk.publicKey); // true
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
The new suites bind a versioned **context label** (`"<namespace>/<purpose>/v<major>"`)
|
|
254
|
+
into the seal — use `hybridSealSuiteWithContext(..., "mosslet/seal/v1")` for a
|
|
255
|
+
custom per-tenant namespace and open with the same label. `sealForUserWithSuite`
|
|
256
|
+
mirrors `sealForUser` with the suite/level appended (legacy X25519 fallback when
|
|
257
|
+
no PQ key is present).
|
|
258
|
+
|
|
259
|
+
> **Honest claims.** "CNSA 2.0 algorithm suite, NCC-audited components,
|
|
260
|
+
> pure-Rust, memory-safe (`forbid-unsafe`)" — **not** "FIPS 140-3 validated."
|
|
261
|
+
> `pureCnsa2` drops the classical backstop, so the strict-AND `hybrid` default
|
|
262
|
+
> stays recommended until the lattice implementations are independently audited.
|
|
263
|
+
|
|
221
264
|
## Security levels
|
|
222
265
|
|
|
223
266
|
| Level | ML-KEM | NIST Category | Equivalent | Default |
|
package/metamorphic_crypto.d.ts
CHANGED
|
@@ -77,6 +77,11 @@ export function generateHybridKeyPair1024(): any;
|
|
|
77
77
|
*/
|
|
78
78
|
export function generateHybridKeyPair512(): any;
|
|
79
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Generate a keypair for `(suite, level)`. Returns JSON: `{ publicKey, secretKey }`.
|
|
82
|
+
*/
|
|
83
|
+
export function generateHybridKeyPairSuite(suite: string, level: string): any;
|
|
84
|
+
|
|
80
85
|
/**
|
|
81
86
|
* Generate a random 32-byte symmetric key (base64).
|
|
82
87
|
*/
|
|
@@ -105,6 +110,35 @@ export function generateSalt(): string;
|
|
|
105
110
|
*/
|
|
106
111
|
export function generateSigningKeyPair(level: string): any;
|
|
107
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
|
+
|
|
108
142
|
/**
|
|
109
143
|
* Check if a base64 ciphertext is hybrid (v2/v3) format.
|
|
110
144
|
*/
|
|
@@ -134,6 +168,12 @@ export function sealForUser(plaintext_b64: string, public_key_b64: string, pq_pu
|
|
|
134
168
|
*/
|
|
135
169
|
export function sealForUserWithLevel(plaintext_b64: string, public_key_b64: string, pq_public_key_b64: string | null | undefined, level: string): string;
|
|
136
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
|
+
|
|
137
177
|
/**
|
|
138
178
|
* SHA-256 (SHA-2) digest of base64-encoded `data`. Returns the 32-byte digest as base64.
|
|
139
179
|
*/
|
|
@@ -202,6 +242,11 @@ export interface InitOutput {
|
|
|
202
242
|
readonly generateHybridKeyPair: () => number;
|
|
203
243
|
readonly generateHybridKeyPair1024: () => number;
|
|
204
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;
|
|
205
250
|
readonly generateKey: (a: number) => void;
|
|
206
251
|
readonly generateKeyPair: () => number;
|
|
207
252
|
readonly generateSalt: (a: number) => void;
|
|
@@ -216,13 +261,14 @@ export interface InitOutput {
|
|
|
216
261
|
readonly sha256: (a: number, b: number, c: number) => void;
|
|
217
262
|
readonly sha512: (a: number, b: number, c: number) => void;
|
|
218
263
|
readonly generateSigningKeyPair: (a: number, b: number, c: number) => void;
|
|
264
|
+
readonly generateSigningKeyPairSuite: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
219
265
|
readonly deriveSigningPublicKey: (a: number, b: number, c: number) => void;
|
|
220
266
|
readonly sign: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
221
267
|
readonly verify: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void;
|
|
222
|
-
readonly decryptPrivateKeyWithRecovery: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
223
|
-
readonly decryptSecretboxToString: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
224
|
-
readonly encryptSecretboxString: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
225
268
|
readonly encryptPrivateKeyForRecovery: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
269
|
+
readonly encryptSecretboxString: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
270
|
+
readonly decryptSecretboxToString: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
271
|
+
readonly decryptPrivateKeyWithRecovery: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
226
272
|
readonly __wbindgen_export: (a: number, b: number) => number;
|
|
227
273
|
readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
|
|
228
274
|
readonly __wbindgen_export3: (a: number) => void;
|
package/metamorphic_crypto.js
CHANGED
|
@@ -448,6 +448,32 @@ export function generateHybridKeyPair512() {
|
|
|
448
448
|
return takeObject(ret);
|
|
449
449
|
}
|
|
450
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
|
+
|
|
451
477
|
/**
|
|
452
478
|
* Generate a random 32-byte symmetric key (base64).
|
|
453
479
|
* @returns {string}
|
|
@@ -545,6 +571,164 @@ export function generateSigningKeyPair(level) {
|
|
|
545
571
|
}
|
|
546
572
|
}
|
|
547
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
|
+
|
|
548
732
|
/**
|
|
549
733
|
* Check if a base64 ciphertext is hybrid (v2/v3) format.
|
|
550
734
|
* @param {string} ciphertext_b64
|
|
@@ -704,6 +888,51 @@ export function sealForUserWithLevel(plaintext_b64, public_key_b64, pq_public_ke
|
|
|
704
888
|
}
|
|
705
889
|
}
|
|
706
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
|
+
|
|
707
936
|
/**
|
|
708
937
|
* SHA-256 (SHA-2) digest of base64-encoded `data`. Returns the 32-byte digest as base64.
|
|
709
938
|
* @param {string} data_b64
|
|
@@ -992,34 +1221,34 @@ export function verify(message_b64, context, signature_b64, public_key_b64) {
|
|
|
992
1221
|
function __wbg_get_imports() {
|
|
993
1222
|
const import0 = {
|
|
994
1223
|
__proto__: null,
|
|
995
|
-
|
|
1224
|
+
__wbg___wbindgen_debug_string_c25d447a39f5578f: function(arg0, arg1) {
|
|
996
1225
|
const ret = debugString(getObject(arg1));
|
|
997
1226
|
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
998
1227
|
const len1 = WASM_VECTOR_LEN;
|
|
999
1228
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
|
1000
1229
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
|
1001
1230
|
},
|
|
1002
|
-
|
|
1231
|
+
__wbg___wbindgen_is_function_1ff95bcc5517c252: function(arg0) {
|
|
1003
1232
|
const ret = typeof(getObject(arg0)) === 'function';
|
|
1004
1233
|
return ret;
|
|
1005
1234
|
},
|
|
1006
|
-
|
|
1235
|
+
__wbg___wbindgen_is_object_a27215656b807791: function(arg0) {
|
|
1007
1236
|
const val = getObject(arg0);
|
|
1008
1237
|
const ret = typeof(val) === 'object' && val !== null;
|
|
1009
1238
|
return ret;
|
|
1010
1239
|
},
|
|
1011
|
-
|
|
1240
|
+
__wbg___wbindgen_is_string_ea5e6cc2e4141dfe: function(arg0) {
|
|
1012
1241
|
const ret = typeof(getObject(arg0)) === 'string';
|
|
1013
1242
|
return ret;
|
|
1014
1243
|
},
|
|
1015
|
-
|
|
1244
|
+
__wbg___wbindgen_is_undefined_c05833b95a3cf397: function(arg0) {
|
|
1016
1245
|
const ret = getObject(arg0) === undefined;
|
|
1017
1246
|
return ret;
|
|
1018
1247
|
},
|
|
1019
|
-
|
|
1248
|
+
__wbg___wbindgen_throw_344f42d3211c4765: function(arg0, arg1) {
|
|
1020
1249
|
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
1021
1250
|
},
|
|
1022
|
-
|
|
1251
|
+
__wbg_call_a6e5c5dce5018821: function() { return handleError(function (arg0, arg1, arg2) {
|
|
1023
1252
|
const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
|
|
1024
1253
|
return addHeapObject(ret);
|
|
1025
1254
|
}, arguments); },
|
|
@@ -1030,7 +1259,7 @@ function __wbg_get_imports() {
|
|
|
1030
1259
|
__wbg_getRandomValues_c44a50d8cfdaebeb: function() { return handleError(function (arg0, arg1) {
|
|
1031
1260
|
getObject(arg0).getRandomValues(getObject(arg1));
|
|
1032
1261
|
}, arguments); },
|
|
1033
|
-
|
|
1262
|
+
__wbg_length_1f0964f4a5e2c6d8: function(arg0) {
|
|
1034
1263
|
const ret = getObject(arg0).length;
|
|
1035
1264
|
return ret;
|
|
1036
1265
|
},
|
|
@@ -1038,11 +1267,11 @@ function __wbg_get_imports() {
|
|
|
1038
1267
|
const ret = getObject(arg0).msCrypto;
|
|
1039
1268
|
return addHeapObject(ret);
|
|
1040
1269
|
},
|
|
1041
|
-
|
|
1270
|
+
__wbg_new_da52cf8fe3429cb2: function() {
|
|
1042
1271
|
const ret = new Object();
|
|
1043
1272
|
return addHeapObject(ret);
|
|
1044
1273
|
},
|
|
1045
|
-
|
|
1274
|
+
__wbg_new_with_length_e6785c33c8e4cce8: function(arg0) {
|
|
1046
1275
|
const ret = new Uint8Array(arg0 >>> 0);
|
|
1047
1276
|
return addHeapObject(ret);
|
|
1048
1277
|
},
|
|
@@ -1054,7 +1283,7 @@ function __wbg_get_imports() {
|
|
|
1054
1283
|
const ret = getObject(arg0).process;
|
|
1055
1284
|
return addHeapObject(ret);
|
|
1056
1285
|
},
|
|
1057
|
-
|
|
1286
|
+
__wbg_prototypesetcall_4770620bbe4688a0: function(arg0, arg1, arg2) {
|
|
1058
1287
|
Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), getObject(arg2));
|
|
1059
1288
|
},
|
|
1060
1289
|
__wbg_randomFillSync_6c25eac9869eb53c: function() { return handleError(function (arg0, arg1) {
|
|
@@ -1064,27 +1293,27 @@ function __wbg_get_imports() {
|
|
|
1064
1293
|
const ret = module.require;
|
|
1065
1294
|
return addHeapObject(ret);
|
|
1066
1295
|
}, arguments); },
|
|
1067
|
-
|
|
1296
|
+
__wbg_set_8535240470bf2500: function() { return handleError(function (arg0, arg1, arg2) {
|
|
1068
1297
|
const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2));
|
|
1069
1298
|
return ret;
|
|
1070
1299
|
}, arguments); },
|
|
1071
|
-
|
|
1300
|
+
__wbg_static_accessor_GLOBAL_4ef717fb391d88b7: function() {
|
|
1072
1301
|
const ret = typeof global === 'undefined' ? null : global;
|
|
1073
1302
|
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
|
1074
1303
|
},
|
|
1075
|
-
|
|
1304
|
+
__wbg_static_accessor_GLOBAL_THIS_8d1badc68b5a74f4: function() {
|
|
1076
1305
|
const ret = typeof globalThis === 'undefined' ? null : globalThis;
|
|
1077
1306
|
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
|
1078
1307
|
},
|
|
1079
|
-
|
|
1308
|
+
__wbg_static_accessor_SELF_146583524fe1469b: function() {
|
|
1080
1309
|
const ret = typeof self === 'undefined' ? null : self;
|
|
1081
1310
|
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
|
1082
1311
|
},
|
|
1083
|
-
|
|
1312
|
+
__wbg_static_accessor_WINDOW_f2829a2234d7819e: function() {
|
|
1084
1313
|
const ret = typeof window === 'undefined' ? null : window;
|
|
1085
1314
|
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
|
1086
1315
|
},
|
|
1087
|
-
|
|
1316
|
+
__wbg_subarray_3ed232c8a6baee09: function(arg0, arg1, arg2) {
|
|
1088
1317
|
const ret = getObject(arg0).subarray(arg1 >>> 0, arg2 >>> 0);
|
|
1089
1318
|
return addHeapObject(ret);
|
|
1090
1319
|
},
|
|
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.1",
|
|
6
6
|
"license": "MIT OR Apache-2.0",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|