@psavelis/enterprise-blockchain 0.1.0 → 1.1.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 +15 -2
- package/dist/aid-settlement/application/reconciler.d.ts +13 -0
- package/dist/aid-settlement/application/reconciler.d.ts.map +1 -0
- package/dist/aid-settlement/application/reconciler.js +77 -0
- package/dist/aid-settlement/domain/entities.d.ts +24 -0
- package/dist/aid-settlement/domain/entities.d.ts.map +1 -0
- package/dist/aid-settlement/domain/entities.js +1 -0
- package/dist/aid-settlement/domain/ports.d.ts +10 -0
- package/dist/aid-settlement/domain/ports.d.ts.map +1 -0
- package/dist/aid-settlement/domain/ports.js +1 -0
- package/dist/aid-settlement/index.d.ts +19 -0
- package/dist/aid-settlement/index.d.ts.map +1 -0
- package/dist/aid-settlement/index.js +23 -0
- package/dist/aid-settlement/infrastructure/in-memory-store.d.ts +12 -0
- package/dist/aid-settlement/infrastructure/in-memory-store.d.ts.map +1 -0
- package/dist/aid-settlement/infrastructure/in-memory-store.js +17 -0
- package/dist/credentialing/application/clearance-evaluator.d.ts +10 -0
- package/dist/credentialing/application/clearance-evaluator.d.ts.map +1 -0
- package/dist/credentialing/application/clearance-evaluator.js +63 -0
- package/dist/credentialing/domain/entities.d.ts +28 -0
- package/dist/credentialing/domain/entities.d.ts.map +1 -0
- package/dist/credentialing/domain/entities.js +1 -0
- package/dist/credentialing/domain/ports.d.ts +9 -0
- package/dist/credentialing/domain/ports.d.ts.map +1 -0
- package/dist/credentialing/domain/ports.js +1 -0
- package/dist/credentialing/index.d.ts +19 -0
- package/dist/credentialing/index.d.ts.map +1 -0
- package/dist/credentialing/index.js +23 -0
- package/dist/credentialing/infrastructure/in-memory-store.d.ts +11 -0
- package/dist/credentialing/infrastructure/in-memory-store.d.ts.map +1 -0
- package/dist/credentialing/infrastructure/in-memory-store.js +14 -0
- package/dist/hsm/application/asymmetric-key-service.d.ts +23 -0
- package/dist/hsm/application/asymmetric-key-service.d.ts.map +1 -0
- package/dist/hsm/application/asymmetric-key-service.js +109 -0
- package/dist/hsm/application/envelope-encryption-service.d.ts +18 -0
- package/dist/hsm/application/envelope-encryption-service.d.ts.map +1 -0
- package/dist/hsm/application/envelope-encryption-service.js +59 -0
- package/dist/hsm/application/symmetric-key-service.d.ts +34 -0
- package/dist/hsm/application/symmetric-key-service.d.ts.map +1 -0
- package/dist/hsm/application/symmetric-key-service.js +107 -0
- package/dist/hsm/domain/entities.d.ts +104 -0
- package/dist/hsm/domain/entities.d.ts.map +1 -0
- package/dist/hsm/domain/entities.js +10 -0
- package/dist/hsm/domain/ports.d.ts +20 -0
- package/dist/hsm/domain/ports.d.ts.map +1 -0
- package/dist/hsm/domain/ports.js +1 -0
- package/dist/hsm/index.d.ts +48 -0
- package/dist/hsm/index.d.ts.map +1 -0
- package/dist/hsm/index.js +97 -0
- package/dist/hsm/infrastructure/audit-log-factory.d.ts +59 -0
- package/dist/hsm/infrastructure/audit-log-factory.d.ts.map +1 -0
- package/dist/hsm/infrastructure/audit-log-factory.js +95 -0
- package/dist/hsm/infrastructure/audit-log.d.ts +8 -0
- package/dist/hsm/infrastructure/audit-log.d.ts.map +1 -0
- package/dist/hsm/infrastructure/audit-log.js +18 -0
- package/dist/hsm/infrastructure/file-audit-log.d.ts +55 -0
- package/dist/hsm/infrastructure/file-audit-log.d.ts.map +1 -0
- package/dist/hsm/infrastructure/file-audit-log.js +128 -0
- package/dist/hsm/infrastructure/key-store.d.ts +9 -0
- package/dist/hsm/infrastructure/key-store.d.ts.map +1 -0
- package/dist/hsm/infrastructure/key-store.js +12 -0
- package/dist/hsm/infrastructure/syslog-audit-log.d.ts +64 -0
- package/dist/hsm/infrastructure/syslog-audit-log.d.ts.map +1 -0
- package/dist/hsm/infrastructure/syslog-audit-log.js +167 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/integrations/besu-client/error-mapper.d.ts +9 -0
- package/dist/integrations/besu-client/error-mapper.d.ts.map +1 -0
- package/dist/integrations/besu-client/error-mapper.js +22 -0
- package/dist/integrations/besu-client/index.d.ts +65 -0
- package/dist/integrations/besu-client/index.d.ts.map +1 -0
- package/dist/integrations/besu-client/index.js +276 -0
- package/dist/integrations/besu-client/ports.d.ts +44 -0
- package/dist/integrations/besu-client/ports.d.ts.map +1 -0
- package/dist/integrations/besu-client/ports.js +1 -0
- package/dist/integrations/corda-gateway/index.d.ts +37 -0
- package/dist/integrations/corda-gateway/index.d.ts.map +1 -0
- package/dist/integrations/corda-gateway/index.js +234 -0
- package/dist/integrations/corda-gateway/ports.d.ts +33 -0
- package/dist/integrations/corda-gateway/ports.d.ts.map +1 -0
- package/dist/integrations/corda-gateway/ports.js +1 -0
- package/dist/integrations/fabric-gateway/index.d.ts +78 -0
- package/dist/integrations/fabric-gateway/index.d.ts.map +1 -0
- package/dist/integrations/fabric-gateway/index.js +214 -0
- package/dist/integrations/fabric-gateway/ports.d.ts +50 -0
- package/dist/integrations/fabric-gateway/ports.d.ts.map +1 -0
- package/dist/integrations/fabric-gateway/ports.js +1 -0
- package/dist/integrations/index.d.ts +19 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +19 -0
- package/dist/integrations/shared/env.d.ts +4 -0
- package/dist/integrations/shared/env.d.ts.map +1 -0
- package/dist/integrations/shared/env.js +24 -0
- package/dist/integrations/shared/retry.d.ts +79 -0
- package/dist/integrations/shared/retry.d.ts.map +1 -0
- package/dist/integrations/shared/retry.js +315 -0
- package/dist/mpc/adapters.d.ts +36 -0
- package/dist/mpc/adapters.d.ts.map +1 -0
- package/dist/mpc/adapters.js +46 -0
- package/dist/mpc/crypto.d.ts +2 -0
- package/dist/mpc/crypto.d.ts.map +1 -0
- package/dist/mpc/crypto.js +2 -0
- package/dist/mpc/dsa.d.ts +134 -0
- package/dist/mpc/dsa.d.ts.map +1 -0
- package/dist/mpc/dsa.js +127 -0
- package/dist/mpc/field.d.ts +127 -0
- package/dist/mpc/field.d.ts.map +1 -0
- package/dist/mpc/field.js +209 -0
- package/dist/mpc/hybrid-kem.d.ts +96 -0
- package/dist/mpc/hybrid-kem.d.ts.map +1 -0
- package/dist/mpc/hybrid-kem.js +136 -0
- package/dist/mpc/index.d.ts +135 -0
- package/dist/mpc/index.d.ts.map +1 -0
- package/dist/mpc/index.js +348 -0
- package/dist/mpc/kyber.d.ts +134 -0
- package/dist/mpc/kyber.d.ts.map +1 -0
- package/dist/mpc/kyber.js +143 -0
- package/dist/mpc/ports.d.ts +67 -0
- package/dist/mpc/ports.d.ts.map +1 -0
- package/dist/mpc/ports.js +9 -0
- package/dist/mpc/quantum.d.ts +80 -0
- package/dist/mpc/quantum.d.ts.map +1 -0
- package/dist/mpc/quantum.js +180 -0
- package/dist/p2mr/adapters.d.ts +31 -0
- package/dist/p2mr/adapters.d.ts.map +1 -0
- package/dist/p2mr/adapters.js +35 -0
- package/dist/p2mr/index.d.ts +63 -0
- package/dist/p2mr/index.d.ts.map +1 -0
- package/dist/p2mr/index.js +59 -0
- package/dist/p2mr/merkle-tree.d.ts +109 -0
- package/dist/p2mr/merkle-tree.d.ts.map +1 -0
- package/dist/p2mr/merkle-tree.js +239 -0
- package/dist/p2mr/p2mr-output.d.ts +142 -0
- package/dist/p2mr/p2mr-output.d.ts.map +1 -0
- package/dist/p2mr/p2mr-output.js +150 -0
- package/dist/p2mr/ports.d.ts +52 -0
- package/dist/p2mr/ports.d.ts.map +1 -0
- package/dist/p2mr/ports.js +9 -0
- package/dist/p2mr/script-interpreter.d.ts +92 -0
- package/dist/p2mr/script-interpreter.d.ts.map +1 -0
- package/dist/p2mr/script-interpreter.js +535 -0
- package/dist/p2mr/script-leaf.d.ts +70 -0
- package/dist/p2mr/script-leaf.d.ts.map +1 -0
- package/dist/p2mr/script-leaf.js +203 -0
- package/dist/p2mr/spend-proof.d.ts +95 -0
- package/dist/p2mr/spend-proof.d.ts.map +1 -0
- package/dist/p2mr/spend-proof.js +358 -0
- package/dist/p2mr/types.d.ts +209 -0
- package/dist/p2mr/types.d.ts.map +1 -0
- package/dist/p2mr/types.js +9 -0
- package/dist/privacy/application/view-projector.d.ts +13 -0
- package/dist/privacy/application/view-projector.d.ts.map +1 -0
- package/dist/privacy/application/view-projector.js +85 -0
- package/dist/privacy/domain/entities.d.ts +26 -0
- package/dist/privacy/domain/entities.d.ts.map +1 -0
- package/dist/privacy/domain/entities.js +1 -0
- package/dist/privacy/domain/ports.d.ts +7 -0
- package/dist/privacy/domain/ports.d.ts.map +1 -0
- package/dist/privacy/domain/ports.js +1 -0
- package/dist/privacy/index.d.ts +21 -0
- package/dist/privacy/index.d.ts.map +1 -0
- package/dist/privacy/index.js +25 -0
- package/dist/privacy/infrastructure/in-memory-store.d.ts +8 -0
- package/dist/privacy/infrastructure/in-memory-store.d.ts.map +1 -0
- package/dist/privacy/infrastructure/in-memory-store.js +7 -0
- package/dist/protocols/besu-port.d.ts +80 -0
- package/dist/protocols/besu-port.d.ts.map +1 -0
- package/dist/protocols/besu-port.js +1 -0
- package/dist/protocols/corda-port.d.ts +103 -0
- package/dist/protocols/corda-port.d.ts.map +1 -0
- package/dist/protocols/corda-port.js +9 -0
- package/dist/protocols/credentialing-port.d.ts +11 -0
- package/dist/protocols/credentialing-port.d.ts.map +1 -0
- package/dist/protocols/credentialing-port.js +1 -0
- package/dist/protocols/fabric-port.d.ts +89 -0
- package/dist/protocols/fabric-port.d.ts.map +1 -0
- package/dist/protocols/fabric-port.js +9 -0
- package/dist/protocols/index.d.ts +14 -0
- package/dist/protocols/index.d.ts.map +1 -0
- package/dist/protocols/index.js +7 -0
- package/dist/protocols/p2mr-port.d.ts +159 -0
- package/dist/protocols/p2mr-port.d.ts.map +1 -0
- package/dist/protocols/p2mr-port.js +12 -0
- package/dist/protocols/privacy-port.d.ts +9 -0
- package/dist/protocols/privacy-port.d.ts.map +1 -0
- package/dist/protocols/privacy-port.js +1 -0
- package/dist/protocols/traceability-port.d.ts +12 -0
- package/dist/protocols/traceability-port.d.ts.map +1 -0
- package/dist/protocols/traceability-port.js +1 -0
- package/dist/shared/collection-store.d.ts +12 -0
- package/dist/shared/collection-store.d.ts.map +1 -0
- package/dist/shared/collection-store.js +26 -0
- package/dist/shared/commit.d.ts +24 -0
- package/dist/shared/commit.d.ts.map +1 -0
- package/dist/shared/commit.js +50 -0
- package/dist/shared/crypto.d.ts +2 -0
- package/dist/shared/crypto.d.ts.map +1 -0
- package/dist/shared/crypto.js +4 -0
- package/dist/shared/date.d.ts +2 -0
- package/dist/shared/date.d.ts.map +1 -0
- package/dist/shared/date.js +3 -0
- package/dist/shared/index.d.ts +9 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +11 -0
- package/dist/shared/logger.d.ts +37 -0
- package/dist/shared/logger.d.ts.map +1 -0
- package/dist/shared/logger.js +45 -0
- package/dist/shared/store.d.ts +25 -0
- package/dist/shared/store.d.ts.map +1 -0
- package/dist/shared/store.js +18 -0
- package/dist/shared/telemetry-sdk.d.ts +26 -0
- package/dist/shared/telemetry-sdk.d.ts.map +1 -0
- package/dist/shared/telemetry-sdk.js +97 -0
- package/dist/shared/telemetry.d.ts +86 -0
- package/dist/shared/telemetry.d.ts.map +1 -0
- package/dist/shared/telemetry.js +137 -0
- package/dist/stark-settlement/application/aggregator-service.d.ts +112 -0
- package/dist/stark-settlement/application/aggregator-service.d.ts.map +1 -0
- package/dist/stark-settlement/application/aggregator-service.js +256 -0
- package/dist/stark-settlement/application/ledger-service.d.ts +114 -0
- package/dist/stark-settlement/application/ledger-service.d.ts.map +1 -0
- package/dist/stark-settlement/application/ledger-service.js +318 -0
- package/dist/stark-settlement/application/settlement-service.d.ts +104 -0
- package/dist/stark-settlement/application/settlement-service.d.ts.map +1 -0
- package/dist/stark-settlement/application/settlement-service.js +251 -0
- package/dist/stark-settlement/domain/entities.d.ts +365 -0
- package/dist/stark-settlement/domain/entities.d.ts.map +1 -0
- package/dist/stark-settlement/domain/entities.js +29 -0
- package/dist/stark-settlement/domain/ports.d.ts +485 -0
- package/dist/stark-settlement/domain/ports.d.ts.map +1 -0
- package/dist/stark-settlement/domain/ports.js +14 -0
- package/dist/stark-settlement/domain/value-objects.d.ts +268 -0
- package/dist/stark-settlement/domain/value-objects.d.ts.map +1 -0
- package/dist/stark-settlement/domain/value-objects.js +500 -0
- package/dist/stark-settlement/index.d.ts +172 -0
- package/dist/stark-settlement/index.d.ts.map +1 -0
- package/dist/stark-settlement/index.js +193 -0
- package/dist/stark-settlement/infrastructure/adapters/audit-adapter.d.ts +52 -0
- package/dist/stark-settlement/infrastructure/adapters/audit-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/audit-adapter.js +154 -0
- package/dist/stark-settlement/infrastructure/adapters/bitcoin-adapter.d.ts +88 -0
- package/dist/stark-settlement/infrastructure/adapters/bitcoin-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/bitcoin-adapter.js +187 -0
- package/dist/stark-settlement/infrastructure/adapters/clock-adapter.d.ts +59 -0
- package/dist/stark-settlement/infrastructure/adapters/clock-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/clock-adapter.js +85 -0
- package/dist/stark-settlement/infrastructure/adapters/dilithium-adapter.d.ts +60 -0
- package/dist/stark-settlement/infrastructure/adapters/dilithium-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/dilithium-adapter.js +104 -0
- package/dist/stark-settlement/infrastructure/adapters/event-emitter-adapter.d.ts +115 -0
- package/dist/stark-settlement/infrastructure/adapters/event-emitter-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/event-emitter-adapter.js +191 -0
- package/dist/stark-settlement/infrastructure/adapters/fiat-adapter.d.ts +65 -0
- package/dist/stark-settlement/infrastructure/adapters/fiat-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/fiat-adapter.js +207 -0
- package/dist/stark-settlement/infrastructure/adapters/mock-stark-adapter.d.ts +73 -0
- package/dist/stark-settlement/infrastructure/adapters/mock-stark-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/mock-stark-adapter.js +287 -0
- package/dist/stark-settlement/infrastructure/adapters/solana-adapter.d.ts +78 -0
- package/dist/stark-settlement/infrastructure/adapters/solana-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/solana-adapter.js +172 -0
- package/dist/stark-settlement/infrastructure/adapters/starknet-proof-adapter.d.ts +56 -0
- package/dist/stark-settlement/infrastructure/adapters/starknet-proof-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/starknet-proof-adapter.js +261 -0
- package/dist/stark-settlement/infrastructure/adapters/stone-proof-adapter.d.ts +125 -0
- package/dist/stark-settlement/infrastructure/adapters/stone-proof-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/stone-proof-adapter.js +416 -0
- package/dist/stark-settlement/infrastructure/persistence/ledger-store.d.ts +68 -0
- package/dist/stark-settlement/infrastructure/persistence/ledger-store.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/persistence/ledger-store.js +238 -0
- package/dist/stark-settlement/infrastructure/persistence/offset-store.d.ts +30 -0
- package/dist/stark-settlement/infrastructure/persistence/offset-store.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/persistence/offset-store.js +57 -0
- package/dist/stark-settlement/infrastructure/persistence/outbox-store.d.ts +45 -0
- package/dist/stark-settlement/infrastructure/persistence/outbox-store.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/persistence/outbox-store.js +171 -0
- package/dist/traceability/application/recall-assessor.d.ts +13 -0
- package/dist/traceability/application/recall-assessor.d.ts.map +1 -0
- package/dist/traceability/application/recall-assessor.js +74 -0
- package/dist/traceability/domain/entities.d.ts +23 -0
- package/dist/traceability/domain/entities.d.ts.map +1 -0
- package/dist/traceability/domain/entities.js +1 -0
- package/dist/traceability/domain/ports.d.ts +23 -0
- package/dist/traceability/domain/ports.d.ts.map +1 -0
- package/dist/traceability/domain/ports.js +1 -0
- package/dist/traceability/domain/recall.d.ts +12 -0
- package/dist/traceability/domain/recall.d.ts.map +1 -0
- package/dist/traceability/domain/recall.js +1 -0
- package/dist/traceability/index.d.ts +22 -0
- package/dist/traceability/index.d.ts.map +1 -0
- package/dist/traceability/index.js +26 -0
- package/dist/traceability/infrastructure/in-memory-store.d.ts +13 -0
- package/dist/traceability/infrastructure/in-memory-store.d.ts.map +1 -0
- package/dist/traceability/infrastructure/in-memory-store.js +24 -0
- package/package.json +12 -9
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ML-KEM (Kyber) — Key Encapsulation Mechanism
|
|
3
|
+
*
|
|
4
|
+
* Classical key exchange (ECDH, RSA) relies on the hardness of the discrete
|
|
5
|
+
* logarithm and integer factorisation problems. Shor's algorithm, running on
|
|
6
|
+
* a sufficiently large cryptographically-relevant quantum computer (CRQC),
|
|
7
|
+
* solves both in polynomial time — meaning today's encrypted traffic could be
|
|
8
|
+
* recorded now and decrypted later once CRQCs mature ("harvest-now,
|
|
9
|
+
* decrypt-later" attacks).
|
|
10
|
+
*
|
|
11
|
+
* ML-KEM is the NIST-standardised Key Encapsulation Mechanism designed to
|
|
12
|
+
* replace ECDH in key exchange. It is based on the Module-Lattice problem
|
|
13
|
+
* (MLWE), which has no known quantum speedup beyond Grover's algorithm
|
|
14
|
+
* (affecting only symmetric-key security, and only by halving the bit level).
|
|
15
|
+
*
|
|
16
|
+
* Standard: NIST FIPS 203 (finalised August 2024)
|
|
17
|
+
* Reference: https://csrc.nist.gov/pubs/fips/203/final
|
|
18
|
+
*
|
|
19
|
+
* This module wraps @noble/post-quantum, a pure-TypeScript implementation with
|
|
20
|
+
* zero native-code dependencies, which makes it platform-portable and easy to
|
|
21
|
+
* audit.
|
|
22
|
+
*/
|
|
23
|
+
import { hkdfSync } from "node:crypto";
|
|
24
|
+
import { ml_kem1024, ml_kem512, ml_kem768, } from "@noble/post-quantum/ml-kem.js";
|
|
25
|
+
import { sha256hex } from "./crypto.js";
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Wire-format byte lengths (from FIPS 203, §7)
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
/**
|
|
30
|
+
* Public key, secret key, and ciphertext lengths (in bytes) for each
|
|
31
|
+
* parameter set. Useful for validation and test assertions.
|
|
32
|
+
*/
|
|
33
|
+
export const ML_KEM_SIZES = {
|
|
34
|
+
"ml-kem-512": {
|
|
35
|
+
publicKey: 800,
|
|
36
|
+
secretKey: 1632,
|
|
37
|
+
ciphertext: 768,
|
|
38
|
+
sharedSecret: 32,
|
|
39
|
+
},
|
|
40
|
+
"ml-kem-768": {
|
|
41
|
+
publicKey: 1184,
|
|
42
|
+
secretKey: 2400,
|
|
43
|
+
ciphertext: 1088,
|
|
44
|
+
sharedSecret: 32,
|
|
45
|
+
},
|
|
46
|
+
"ml-kem-1024": {
|
|
47
|
+
publicKey: 1568,
|
|
48
|
+
secretKey: 3168,
|
|
49
|
+
ciphertext: 1568,
|
|
50
|
+
sharedSecret: 32,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// KyberKem class
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
export class KyberKem {
|
|
57
|
+
/**
|
|
58
|
+
* Generate a new ML-KEM keypair.
|
|
59
|
+
*
|
|
60
|
+
* The public key is shared with anyone who needs to send you an encrypted
|
|
61
|
+
* session key. The secret key must be stored securely — ideally in an HSM
|
|
62
|
+
* or hardware-backed key store.
|
|
63
|
+
*/
|
|
64
|
+
generateKeyPair(params) {
|
|
65
|
+
const kem = this.#suite(params);
|
|
66
|
+
const { publicKey, secretKey } = kem.keygen();
|
|
67
|
+
return { publicKey, secretKey, params };
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Sender-side operation: encapsulate a fresh random shared secret using
|
|
71
|
+
* the recipient's public key.
|
|
72
|
+
*
|
|
73
|
+
* Returns the ciphertext (to send) and the sharedSecret (to use locally for
|
|
74
|
+
* key derivation). The sharedSecret is never transmitted.
|
|
75
|
+
*/
|
|
76
|
+
encapsulate(publicKey, params) {
|
|
77
|
+
const kem = this.#suite(params);
|
|
78
|
+
const { cipherText: ciphertext, sharedSecret } = kem.encapsulate(publicKey);
|
|
79
|
+
return {
|
|
80
|
+
ciphertext,
|
|
81
|
+
sharedSecret,
|
|
82
|
+
auditCommitment: sha256hex(Buffer.from(ciphertext).toString("hex")),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Receiver-side operation: recover the sharedSecret from a ciphertext using
|
|
87
|
+
* the secret key.
|
|
88
|
+
*
|
|
89
|
+
* If the ciphertext was produced with a different public key, ML-KEM
|
|
90
|
+
* returns a pseudorandom value instead of the real shared secret — this is
|
|
91
|
+
* the implicit rejection property that prevents chosen-ciphertext attacks.
|
|
92
|
+
*/
|
|
93
|
+
decapsulate(ciphertext, secretKey, params) {
|
|
94
|
+
const kem = this.#suite(params);
|
|
95
|
+
return kem.decapsulate(ciphertext, secretKey);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Derive a symmetric key from an ML-KEM shared secret using HKDF-SHA256.
|
|
99
|
+
*
|
|
100
|
+
* The shared secret from ML-KEM is already 32 bytes of uniform randomness,
|
|
101
|
+
* but running it through HKDF lets you bind context (e.g., session IDs,
|
|
102
|
+
* party identifiers) into the derived key — useful for domain separation.
|
|
103
|
+
*
|
|
104
|
+
* @param sharedSecret - Raw 32-byte output from encapsulate/decapsulate
|
|
105
|
+
* @param info - Optional context string bound into the derived key
|
|
106
|
+
* @param salt - Optional random salt (defaults to 32 zero bytes if omitted)
|
|
107
|
+
*/
|
|
108
|
+
deriveAesKey(sharedSecret, info = "ml-kem-aes-key-v1", salt) {
|
|
109
|
+
const saltBytes = salt ?? Buffer.alloc(32, 0);
|
|
110
|
+
// HKDF-SHA256 producing 32 bytes → suitable for AES-256-GCM.
|
|
111
|
+
// RFC 5869 (HKDF): https://datatracker.ietf.org/doc/html/rfc5869
|
|
112
|
+
// NIST SP 800-38D (GCM): https://csrc.nist.gov/pubs/sp/800/38/d/final
|
|
113
|
+
return Buffer.from(hkdfSync("sha256", sharedSecret, saltBytes, Buffer.from(info, "utf8"), 32));
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Build an audit record for a completed encapsulation round.
|
|
117
|
+
* Suitable for writing to an immutable ledger (Fabric, Besu, Corda) as
|
|
118
|
+
* proof that a particular key exchange occurred without revealing the
|
|
119
|
+
* shared secret.
|
|
120
|
+
*/
|
|
121
|
+
auditRecord(encap, publicKey, params) {
|
|
122
|
+
return {
|
|
123
|
+
params,
|
|
124
|
+
publicKeyHash: sha256hex(Buffer.from(publicKey).toString("hex")),
|
|
125
|
+
ciphertextHash: encap.auditCommitment,
|
|
126
|
+
timestamp: new Date().toISOString(),
|
|
127
|
+
derivedKeyLength: 32,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
// Private helpers
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
#suite(params) {
|
|
134
|
+
switch (params) {
|
|
135
|
+
case "ml-kem-512":
|
|
136
|
+
return ml_kem512;
|
|
137
|
+
case "ml-kem-768":
|
|
138
|
+
return ml_kem768;
|
|
139
|
+
case "ml-kem-1024":
|
|
140
|
+
return ml_kem1024;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MPC Module Ports (Hexagonal Architecture)
|
|
3
|
+
*
|
|
4
|
+
* These ports define the boundaries between the MPC domain and infrastructure.
|
|
5
|
+
* Domain code MUST only depend on these interfaces, never on concrete implementations.
|
|
6
|
+
*
|
|
7
|
+
* @see docs/adr/ADR-0001-hexagonal-architecture.md
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Port for cryptographically secure random number generation.
|
|
11
|
+
*
|
|
12
|
+
* The MPC domain requires randomness for:
|
|
13
|
+
* - Generating polynomial coefficients in Shamir sharing
|
|
14
|
+
* - Creating nonces for share commitments
|
|
15
|
+
* - Producing random shares in additive sharing
|
|
16
|
+
*
|
|
17
|
+
* Implementations MUST provide cryptographically secure randomness.
|
|
18
|
+
* Using Math.random() or other weak PRNGs is a CRITICAL security vulnerability.
|
|
19
|
+
*/
|
|
20
|
+
export interface RandomnessProvider {
|
|
21
|
+
/**
|
|
22
|
+
* Generate random bytes.
|
|
23
|
+
* @param length Number of bytes to generate.
|
|
24
|
+
* @returns Buffer containing cryptographically secure random bytes.
|
|
25
|
+
*/
|
|
26
|
+
randomBytes(length: number): Buffer;
|
|
27
|
+
/**
|
|
28
|
+
* Generate a random integer in range [min, max).
|
|
29
|
+
* @param min Minimum value (inclusive).
|
|
30
|
+
* @param max Maximum value (exclusive).
|
|
31
|
+
* @returns Cryptographically secure random integer.
|
|
32
|
+
*/
|
|
33
|
+
randomInt(min: number, max: number): number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Port for commitment and hashing operations.
|
|
37
|
+
*
|
|
38
|
+
* The MPC domain uses commitments to:
|
|
39
|
+
* - Bind parties to their shares before revealing
|
|
40
|
+
* - Detect tampering during computation
|
|
41
|
+
* - Provide audit trails with integrity proofs
|
|
42
|
+
*/
|
|
43
|
+
export interface CommitmentProvider {
|
|
44
|
+
/**
|
|
45
|
+
* Create a commitment for a secret share.
|
|
46
|
+
* @param partyId The party identifier.
|
|
47
|
+
* @param shareIndex The share's index in the sharing scheme.
|
|
48
|
+
* @param value The share value.
|
|
49
|
+
* @param nonce Random nonce for binding.
|
|
50
|
+
* @returns Commitment string (typically a hash).
|
|
51
|
+
*/
|
|
52
|
+
commitShare(partyId: string, shareIndex: number, value: number | bigint, nonce: string): string;
|
|
53
|
+
/**
|
|
54
|
+
* Compute SHA-256 hash of a string.
|
|
55
|
+
* @param data Input string to hash.
|
|
56
|
+
* @returns Hex-encoded hash.
|
|
57
|
+
*/
|
|
58
|
+
sha256hex(data: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* Compare two strings in constant time.
|
|
61
|
+
* @param a First string.
|
|
62
|
+
* @param b Second string.
|
|
63
|
+
* @returns True if equal, false otherwise.
|
|
64
|
+
*/
|
|
65
|
+
timingSafeCompare(a: string, b: string): boolean;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=ports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../src/mpc/ports.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IAEpC;;;;;OAKG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CAC7C;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;;;OAOG;IACH,WAAW,CACT,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,KAAK,EAAE,MAAM,GACZ,MAAM,CAAC;IAEV;;;;OAIG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAEhC;;;;;OAKG;IACH,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAClD"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MPC Module Ports (Hexagonal Architecture)
|
|
3
|
+
*
|
|
4
|
+
* These ports define the boundaries between the MPC domain and infrastructure.
|
|
5
|
+
* Domain code MUST only depend on these interfaces, never on concrete implementations.
|
|
6
|
+
*
|
|
7
|
+
* @see docs/adr/ADR-0001-hexagonal-architecture.md
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { type FieldConfig, type FieldMode } from "./field.js";
|
|
2
|
+
export interface ThresholdShare {
|
|
3
|
+
partyId: string;
|
|
4
|
+
shareIndex: number;
|
|
5
|
+
/** Share value as bigint for production mode compatibility. */
|
|
6
|
+
value: bigint;
|
|
7
|
+
/** Legacy number value for backward compatibility (demo mode only). */
|
|
8
|
+
valueNumber?: number | undefined;
|
|
9
|
+
nonce: string;
|
|
10
|
+
commitment: string;
|
|
11
|
+
}
|
|
12
|
+
export interface HashLadderKey {
|
|
13
|
+
publicRoot: string;
|
|
14
|
+
depth: number;
|
|
15
|
+
scheme: "sha256-chain";
|
|
16
|
+
}
|
|
17
|
+
export interface QuantumResistantAnchor {
|
|
18
|
+
dataHash: string;
|
|
19
|
+
ladderRoot: string;
|
|
20
|
+
depth: number;
|
|
21
|
+
timestamp: string;
|
|
22
|
+
scheme: "hash-ladder";
|
|
23
|
+
}
|
|
24
|
+
export interface VaultConfig {
|
|
25
|
+
/** Field mode: "demo" (default) or "production". */
|
|
26
|
+
fieldMode?: FieldMode;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Quantum-resistant secret sharing vault using Shamir's Secret Sharing.
|
|
30
|
+
*
|
|
31
|
+
* Supports two field sizes:
|
|
32
|
+
* - Demo mode (default): 2^31-1 prime, fast but NOT secure for production
|
|
33
|
+
* - Production mode: 256-bit prime, cryptographically secure
|
|
34
|
+
*
|
|
35
|
+
* Set MPC_FIELD_MODE=production or pass { fieldMode: "production" } for
|
|
36
|
+
* production deployments.
|
|
37
|
+
*
|
|
38
|
+
* @see skills/mpc-secret-sharing.md for security guidance
|
|
39
|
+
*/
|
|
40
|
+
export declare class QuantumResistantVault {
|
|
41
|
+
private readonly field;
|
|
42
|
+
constructor(config?: VaultConfig);
|
|
43
|
+
/**
|
|
44
|
+
* Get the current field configuration.
|
|
45
|
+
*/
|
|
46
|
+
getFieldConfig(): FieldConfig;
|
|
47
|
+
/**
|
|
48
|
+
* Check if the vault is configured for production-grade security.
|
|
49
|
+
*/
|
|
50
|
+
isProductionSecure(): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Distribute `secret` across `parties` using Shamir's Secret Sharing.
|
|
53
|
+
* Any `threshold` shares reconstruct the secret; fewer reveal nothing.
|
|
54
|
+
*
|
|
55
|
+
* @param secret - The secret to share (must be within field range)
|
|
56
|
+
* @param parties - Party identifiers to receive shares
|
|
57
|
+
* @param threshold - Minimum shares needed for reconstruction
|
|
58
|
+
*/
|
|
59
|
+
distributeSecret(secret: number | bigint, parties: string[], threshold: number): Map<string, ThresholdShare>;
|
|
60
|
+
/**
|
|
61
|
+
* Reconstruct the secret from a set of shares via Lagrange interpolation.
|
|
62
|
+
* Returns `null` when fewer than `threshold` shares are supplied.
|
|
63
|
+
*
|
|
64
|
+
* @returns The reconstructed secret as bigint, or null if insufficient shares.
|
|
65
|
+
* In demo mode, also returns as number for backward compatibility.
|
|
66
|
+
*/
|
|
67
|
+
reconstructSecret(shares: ThresholdShare[], threshold: number): number | bigint | null;
|
|
68
|
+
/**
|
|
69
|
+
* Reconstruct the secret and always return as bigint.
|
|
70
|
+
* Use this for production mode or when bigint precision is required.
|
|
71
|
+
*/
|
|
72
|
+
reconstructSecretBigint(shares: ThresholdShare[], threshold: number): bigint | null;
|
|
73
|
+
/** Build a SHA-256 hash chain of `depth` iterations from a random seed. */
|
|
74
|
+
createHashLadder(depth: number): HashLadderKey;
|
|
75
|
+
/** Anchor data with a hash-ladder proof (no asymmetric key involved). */
|
|
76
|
+
anchorWithPostQuantumProof(data: string): QuantumResistantAnchor;
|
|
77
|
+
private evalPoly;
|
|
78
|
+
private lagrangeInterpolate;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=quantum.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quantum.d.ts","sourceRoot":"","sources":["../../src/mpc/quantum.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,oDAAoD;IACpD,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkB;gBAE5B,MAAM,CAAC,EAAE,WAAW;IAKhC;;OAEG;IACH,cAAc,IAAI,WAAW;IAI7B;;OAEG;IACH,kBAAkB,IAAI,OAAO;IAG7B;;;;;;;OAOG;IACH,gBAAgB,CACd,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,MAAM,GAChB,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC;IAqE9B;;;;;;OAMG;IACH,iBAAiB,CACf,MAAM,EAAE,cAAc,EAAE,EACxB,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,MAAM,GAAG,IAAI;IAuBzB;;;OAGG;IACH,uBAAuB,CACrB,MAAM,EAAE,cAAc,EAAE,EACxB,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI;IAahB,2EAA2E;IAC3E,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa;IAU9C,yEAAyE;IACzE,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,sBAAsB;IAchE,OAAO,CAAC,QAAQ;IAUhB,OAAO,CAAC,mBAAmB;CAoB5B"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { commitShare, sha256hex } from "./crypto.js";
|
|
3
|
+
import { FieldArithmetic, getFieldConfig, } from "./field.js";
|
|
4
|
+
/**
|
|
5
|
+
* Quantum-resistant secret sharing vault using Shamir's Secret Sharing.
|
|
6
|
+
*
|
|
7
|
+
* Supports two field sizes:
|
|
8
|
+
* - Demo mode (default): 2^31-1 prime, fast but NOT secure for production
|
|
9
|
+
* - Production mode: 256-bit prime, cryptographically secure
|
|
10
|
+
*
|
|
11
|
+
* Set MPC_FIELD_MODE=production or pass { fieldMode: "production" } for
|
|
12
|
+
* production deployments.
|
|
13
|
+
*
|
|
14
|
+
* @see skills/mpc-secret-sharing.md for security guidance
|
|
15
|
+
*/
|
|
16
|
+
export class QuantumResistantVault {
|
|
17
|
+
field;
|
|
18
|
+
constructor(config) {
|
|
19
|
+
const fieldConfig = getFieldConfig(config?.fieldMode);
|
|
20
|
+
this.field = new FieldArithmetic(fieldConfig);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get the current field configuration.
|
|
24
|
+
*/
|
|
25
|
+
getFieldConfig() {
|
|
26
|
+
return { mode: this.field.mode, prime: this.field.prime };
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Check if the vault is configured for production-grade security.
|
|
30
|
+
*/
|
|
31
|
+
isProductionSecure() {
|
|
32
|
+
return this.field.isProductionSecure();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Distribute `secret` across `parties` using Shamir's Secret Sharing.
|
|
36
|
+
* Any `threshold` shares reconstruct the secret; fewer reveal nothing.
|
|
37
|
+
*
|
|
38
|
+
* @param secret - The secret to share (must be within field range)
|
|
39
|
+
* @param parties - Party identifiers to receive shares
|
|
40
|
+
* @param threshold - Minimum shares needed for reconstruction
|
|
41
|
+
*/
|
|
42
|
+
distributeSecret(secret, parties, threshold) {
|
|
43
|
+
// Input validation to prevent security issues
|
|
44
|
+
if (parties.length === 0) {
|
|
45
|
+
throw new Error("At least one party is required");
|
|
46
|
+
}
|
|
47
|
+
if (threshold < 2) {
|
|
48
|
+
throw new Error("Threshold must be at least 2");
|
|
49
|
+
}
|
|
50
|
+
if (threshold > parties.length) {
|
|
51
|
+
throw new Error("Threshold cannot exceed party count");
|
|
52
|
+
}
|
|
53
|
+
// Validate party ID uniqueness - duplicate IDs would break t-of-n security
|
|
54
|
+
const uniqueParties = new Set(parties);
|
|
55
|
+
if (uniqueParties.size !== parties.length) {
|
|
56
|
+
throw new Error("Duplicate party IDs detected. Each party must have a unique identifier.");
|
|
57
|
+
}
|
|
58
|
+
// Validate party ID format - prevent injection and excessively long IDs
|
|
59
|
+
const MAX_PARTY_ID_LENGTH = 256;
|
|
60
|
+
for (const partyId of parties) {
|
|
61
|
+
if (!partyId || partyId.trim().length === 0) {
|
|
62
|
+
throw new Error("Party ID cannot be empty or whitespace-only");
|
|
63
|
+
}
|
|
64
|
+
if (partyId.length > MAX_PARTY_ID_LENGTH) {
|
|
65
|
+
throw new Error(`Party ID exceeds maximum length of ${MAX_PARTY_ID_LENGTH} characters`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const secretBigint = BigInt(secret);
|
|
69
|
+
if (secretBigint < 0n || secretBigint >= this.field.prime) {
|
|
70
|
+
throw new Error(`Secret must be in range [0, ${this.field.prime}). ` +
|
|
71
|
+
`Current field mode: ${this.field.mode}`);
|
|
72
|
+
}
|
|
73
|
+
// Random polynomial of degree (threshold − 1) with secret as constant term.
|
|
74
|
+
const coeffs = [secretBigint];
|
|
75
|
+
for (let i = 1; i < threshold; i++) {
|
|
76
|
+
coeffs.push(this.field.random());
|
|
77
|
+
}
|
|
78
|
+
const shares = new Map();
|
|
79
|
+
for (let i = 0; i < parties.length; i++) {
|
|
80
|
+
const x = BigInt(i + 1);
|
|
81
|
+
const y = this.evalPoly(coeffs, x);
|
|
82
|
+
const nonce = randomBytes(16).toString("hex");
|
|
83
|
+
// For commitment, use number if in demo mode for backward compatibility
|
|
84
|
+
const commitValue = this.field.mode === "demo" ? Number(y) : y;
|
|
85
|
+
shares.set(parties[i], {
|
|
86
|
+
partyId: parties[i],
|
|
87
|
+
shareIndex: i,
|
|
88
|
+
value: y,
|
|
89
|
+
valueNumber: this.field.mode === "demo" ? Number(y) : undefined,
|
|
90
|
+
nonce,
|
|
91
|
+
commitment: commitShare(parties[i], i, commitValue, nonce),
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return shares;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Reconstruct the secret from a set of shares via Lagrange interpolation.
|
|
98
|
+
* Returns `null` when fewer than `threshold` shares are supplied.
|
|
99
|
+
*
|
|
100
|
+
* @returns The reconstructed secret as bigint, or null if insufficient shares.
|
|
101
|
+
* In demo mode, also returns as number for backward compatibility.
|
|
102
|
+
*/
|
|
103
|
+
reconstructSecret(shares, threshold) {
|
|
104
|
+
if (shares.length < threshold) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
const points = shares.map((s) => [
|
|
108
|
+
BigInt(s.shareIndex + 1),
|
|
109
|
+
BigInt(s.value),
|
|
110
|
+
]);
|
|
111
|
+
const result = this.lagrangeInterpolate(points);
|
|
112
|
+
// Return number for backward compatibility in demo mode
|
|
113
|
+
if (this.field.mode === "demo" &&
|
|
114
|
+
result <= BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
115
|
+
return Number(result);
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Reconstruct the secret and always return as bigint.
|
|
121
|
+
* Use this for production mode or when bigint precision is required.
|
|
122
|
+
*/
|
|
123
|
+
reconstructSecretBigint(shares, threshold) {
|
|
124
|
+
if (shares.length < threshold) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
const points = shares.map((s) => [
|
|
128
|
+
BigInt(s.shareIndex + 1),
|
|
129
|
+
BigInt(s.value),
|
|
130
|
+
]);
|
|
131
|
+
return this.lagrangeInterpolate(points);
|
|
132
|
+
}
|
|
133
|
+
/** Build a SHA-256 hash chain of `depth` iterations from a random seed. */
|
|
134
|
+
createHashLadder(depth) {
|
|
135
|
+
let current = sha256hex(randomBytes(32).toString("hex"));
|
|
136
|
+
for (let i = 0; i < depth; i++) {
|
|
137
|
+
current = sha256hex(current);
|
|
138
|
+
}
|
|
139
|
+
return { publicRoot: current, depth, scheme: "sha256-chain" };
|
|
140
|
+
}
|
|
141
|
+
/** Anchor data with a hash-ladder proof (no asymmetric key involved). */
|
|
142
|
+
anchorWithPostQuantumProof(data) {
|
|
143
|
+
const ladder = this.createHashLadder(256);
|
|
144
|
+
return {
|
|
145
|
+
dataHash: sha256hex(data),
|
|
146
|
+
ladderRoot: ladder.publicRoot,
|
|
147
|
+
depth: ladder.depth,
|
|
148
|
+
timestamp: new Date().toISOString(),
|
|
149
|
+
scheme: "hash-ladder",
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
// --- Shamir arithmetic using configurable field ---
|
|
153
|
+
evalPoly(coeffs, x) {
|
|
154
|
+
let result = 0n;
|
|
155
|
+
let power = 1n;
|
|
156
|
+
for (const c of coeffs) {
|
|
157
|
+
result = this.field.add(result, this.field.mul(c, power));
|
|
158
|
+
power = this.field.mul(power, x);
|
|
159
|
+
}
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
162
|
+
lagrangeInterpolate(points) {
|
|
163
|
+
let result = 0n;
|
|
164
|
+
for (let i = 0; i < points.length; i++) {
|
|
165
|
+
const [xi, yi] = points[i];
|
|
166
|
+
let num = 1n;
|
|
167
|
+
let den = 1n;
|
|
168
|
+
for (let j = 0; j < points.length; j++) {
|
|
169
|
+
if (i === j)
|
|
170
|
+
continue;
|
|
171
|
+
const xj = points[j][0];
|
|
172
|
+
num = this.field.mul(num, this.field.mod(-xj));
|
|
173
|
+
den = this.field.mul(den, this.field.sub(xi, xj));
|
|
174
|
+
}
|
|
175
|
+
const inv = this.field.inverse(den);
|
|
176
|
+
result = this.field.add(result, this.field.mul(yi, this.field.mul(num, inv)));
|
|
177
|
+
}
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* P2MR Module Infrastructure Adapters
|
|
3
|
+
*
|
|
4
|
+
* These adapters implement the ports defined in ports.ts.
|
|
5
|
+
* They live in the infrastructure layer and are injected into domain services.
|
|
6
|
+
*
|
|
7
|
+
* @see modules/p2mr/src/ports.ts
|
|
8
|
+
*/
|
|
9
|
+
import type { SignatureVerificationPort, HashingPort, SignatureAlgorithm } from "./ports.js";
|
|
10
|
+
/**
|
|
11
|
+
* ML-DSA implementation of SignatureVerificationPort.
|
|
12
|
+
*
|
|
13
|
+
* Uses the MlDsaSigner from the MPC module for post-quantum signature verification.
|
|
14
|
+
*/
|
|
15
|
+
export declare class MlDsaSignatureVerifier implements SignatureVerificationPort {
|
|
16
|
+
private readonly signer;
|
|
17
|
+
verify(message: Uint8Array, signature: Uint8Array, publicKey: Uint8Array, algorithm: SignatureAlgorithm): boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* SHA-256 implementation of HashingPort.
|
|
21
|
+
*/
|
|
22
|
+
export declare class Sha256Hasher implements HashingPort {
|
|
23
|
+
sha256hex(data: string): string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Default instances for convenience.
|
|
27
|
+
* Domain code should prefer dependency injection over these singletons.
|
|
28
|
+
*/
|
|
29
|
+
export declare const defaultSignatureVerifier: MlDsaSignatureVerifier;
|
|
30
|
+
export declare const defaultHasher: Sha256Hasher;
|
|
31
|
+
//# sourceMappingURL=adapters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../../src/p2mr/adapters.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EACV,yBAAyB,EACzB,WAAW,EACX,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAEpB;;;;GAIG;AACH,qBAAa,sBAAuB,YAAW,yBAAyB;IACtE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAE5C,MAAM,CACJ,OAAO,EAAE,UAAU,EACnB,SAAS,EAAE,UAAU,EACrB,SAAS,EAAE,UAAU,EACrB,SAAS,EAAE,kBAAkB,GAC5B,OAAO;CAGX;AAED;;GAEG;AACH,qBAAa,YAAa,YAAW,WAAW;IAC9C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAGhC;AAED;;;GAGG;AACH,eAAO,MAAM,wBAAwB,wBAA+B,CAAC;AACrE,eAAO,MAAM,aAAa,cAAqB,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* P2MR Module Infrastructure Adapters
|
|
3
|
+
*
|
|
4
|
+
* These adapters implement the ports defined in ports.ts.
|
|
5
|
+
* They live in the infrastructure layer and are injected into domain services.
|
|
6
|
+
*
|
|
7
|
+
* @see modules/p2mr/src/ports.ts
|
|
8
|
+
*/
|
|
9
|
+
import { MlDsaSigner } from "../mpc/dsa.js";
|
|
10
|
+
import { sha256hex } from "../shared/crypto.js";
|
|
11
|
+
/**
|
|
12
|
+
* ML-DSA implementation of SignatureVerificationPort.
|
|
13
|
+
*
|
|
14
|
+
* Uses the MlDsaSigner from the MPC module for post-quantum signature verification.
|
|
15
|
+
*/
|
|
16
|
+
export class MlDsaSignatureVerifier {
|
|
17
|
+
signer = new MlDsaSigner();
|
|
18
|
+
verify(message, signature, publicKey, algorithm) {
|
|
19
|
+
return this.signer.verify(message, signature, publicKey, algorithm);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* SHA-256 implementation of HashingPort.
|
|
24
|
+
*/
|
|
25
|
+
export class Sha256Hasher {
|
|
26
|
+
sha256hex(data) {
|
|
27
|
+
return sha256hex(data);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Default instances for convenience.
|
|
32
|
+
* Domain code should prefer dependency injection over these singletons.
|
|
33
|
+
*/
|
|
34
|
+
export const defaultSignatureVerifier = new MlDsaSignatureVerifier();
|
|
35
|
+
export const defaultHasher = new Sha256Hasher();
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @psavelis/enterprise-blockchain/p2mr
|
|
3
|
+
*
|
|
4
|
+
* BIP-360-inspired Pay-to-Merkle-Root quantum-safe outputs.
|
|
5
|
+
*
|
|
6
|
+
* P2MR eliminates the "harvest now, decrypt later" quantum threat by:
|
|
7
|
+
* 1. Storing ONLY a Merkle root on-chain (no public keys exposed)
|
|
8
|
+
* 2. Using post-quantum ML-DSA-65 signatures for spending
|
|
9
|
+
* 3. Revealing public keys only at spend time (minimizing exposure window)
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* import {
|
|
14
|
+
* createP2MROutput,
|
|
15
|
+
* createSingleSigLeaf,
|
|
16
|
+
* createTimelockLeaf,
|
|
17
|
+
* buildSpendProof,
|
|
18
|
+
* verifySpendProofStructure,
|
|
19
|
+
* } from "@psavelis/enterprise-blockchain/p2mr";
|
|
20
|
+
*
|
|
21
|
+
* // Create an output with two spending paths
|
|
22
|
+
* const { output, tree } = createP2MROutput({
|
|
23
|
+
* leaves: [
|
|
24
|
+
* createSingleSigLeaf(primaryKeyHash), // Path 0: primary key
|
|
25
|
+
* createTimelockLeaf(backupKeyHash, locktime), // Path 1: backup after locktime
|
|
26
|
+
* ],
|
|
27
|
+
* value: 1_000_000n,
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // Store `output` on-chain (only merkleRoot exposed)
|
|
31
|
+
* // Keep `tree` off-chain for generating spend proofs
|
|
32
|
+
*
|
|
33
|
+
* // Later, spend via path 0:
|
|
34
|
+
* const proof = buildSpendProof({
|
|
35
|
+
* outputId: output.outputId,
|
|
36
|
+
* tree,
|
|
37
|
+
* leafIndex: 0,
|
|
38
|
+
* witness: {
|
|
39
|
+
* publicKeys: [primaryKey],
|
|
40
|
+
* signatures: [signature],
|
|
41
|
+
* },
|
|
42
|
+
* });
|
|
43
|
+
*
|
|
44
|
+
* // Verify proof structure and Merkle path
|
|
45
|
+
* const result = verifySpendProofStructure(proof, output);
|
|
46
|
+
* console.log(result.valid); // true
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @packageDocumentation
|
|
50
|
+
*/
|
|
51
|
+
export type { ScriptLeafType, ScriptLeaf, P2MROutput, MerkleProofNode, SpendWitness, SpendProof, SpendVerificationResult, VerificationStep, ScriptVerificationResult, } from "./types.js";
|
|
52
|
+
export { MerkleTree, canonicalJSON, hashScriptLeaf } from "./merkle-tree.js";
|
|
53
|
+
export type { ValidationResult } from "./script-leaf.js";
|
|
54
|
+
export { validateScriptLeaf, createSingleSigLeaf, createTimelockLeaf, createMultisigLeaf, createHsmAttestedLeaf, } from "./script-leaf.js";
|
|
55
|
+
export type { CreateP2MROutputOptions, CreateP2MROutputResult, } from "./p2mr-output.js";
|
|
56
|
+
export { createP2MROutput, P2MROutputStore } from "./p2mr-output.js";
|
|
57
|
+
export type { BuildSpendProofOptions } from "./spend-proof.js";
|
|
58
|
+
export { buildSpendProof, validateSpendProofStructure, verifyMerkleProof, verifySpendProofStructure, } from "./spend-proof.js";
|
|
59
|
+
export type { InterpretScriptOptions, InterpretScriptResult, } from "./script-interpreter.js";
|
|
60
|
+
export { interpretScript, hashPublicKey, configureInterpreter, resetInterpreter, } from "./script-interpreter.js";
|
|
61
|
+
export type { SignatureVerificationPort, HashingPort, SignatureAlgorithm, } from "./ports.js";
|
|
62
|
+
export { MlDsaSignatureVerifier, Sha256Hasher, defaultSignatureVerifier, defaultHasher, } from "./adapters.js";
|
|
63
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/p2mr/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAMH,YAAY,EACV,cAAc,EACd,UAAU,EACV,UAAU,EACV,eAAe,EACf,YAAY,EACZ,UAAU,EACV,uBAAuB,EACvB,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,YAAY,CAAC;AAMpB,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAM7E,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAM1B,YAAY,EACV,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAMrE,YAAY,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE/D,OAAO,EACL,eAAe,EACf,2BAA2B,EAC3B,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,kBAAkB,CAAC;AAM1B,YAAY,EACV,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AAMjC,YAAY,EACV,yBAAyB,EACzB,WAAW,EACX,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,wBAAwB,EACxB,aAAa,GACd,MAAM,eAAe,CAAC"}
|