signet-protocol 0.1.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.
Files changed (156) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +112 -0
  3. package/dist/anomaly.d.ts +42 -0
  4. package/dist/anomaly.d.ts.map +1 -0
  5. package/dist/anomaly.js +209 -0
  6. package/dist/anomaly.js.map +1 -0
  7. package/dist/badge.d.ts +56 -0
  8. package/dist/badge.d.ts.map +1 -0
  9. package/dist/badge.js +171 -0
  10. package/dist/badge.js.map +1 -0
  11. package/dist/bonds.d.ts +39 -0
  12. package/dist/bonds.d.ts.map +1 -0
  13. package/dist/bonds.js +149 -0
  14. package/dist/bonds.js.map +1 -0
  15. package/dist/challenges.d.ts +18 -0
  16. package/dist/challenges.d.ts.map +1 -0
  17. package/dist/challenges.js +145 -0
  18. package/dist/challenges.js.map +1 -0
  19. package/dist/cold-call.d.ts +74 -0
  20. package/dist/cold-call.d.ts.map +1 -0
  21. package/dist/cold-call.js +176 -0
  22. package/dist/cold-call.js.map +1 -0
  23. package/dist/compliance.d.ts +82 -0
  24. package/dist/compliance.d.ts.map +1 -0
  25. package/dist/compliance.js +478 -0
  26. package/dist/compliance.js.map +1 -0
  27. package/dist/connections.d.ts +63 -0
  28. package/dist/connections.d.ts.map +1 -0
  29. package/dist/connections.js +170 -0
  30. package/dist/connections.js.map +1 -0
  31. package/dist/constants.d.ts +86 -0
  32. package/dist/constants.d.ts.map +1 -0
  33. package/dist/constants.js +124 -0
  34. package/dist/constants.js.map +1 -0
  35. package/dist/credentials.d.ts +190 -0
  36. package/dist/credentials.d.ts.map +1 -0
  37. package/dist/credentials.js +686 -0
  38. package/dist/credentials.js.map +1 -0
  39. package/dist/crypto.d.ts +27 -0
  40. package/dist/crypto.d.ts.map +1 -0
  41. package/dist/crypto.js +75 -0
  42. package/dist/crypto.js.map +1 -0
  43. package/dist/errors.d.ts +17 -0
  44. package/dist/errors.d.ts.map +1 -0
  45. package/dist/errors.js +29 -0
  46. package/dist/errors.js.map +1 -0
  47. package/dist/i18n.d.ts +98 -0
  48. package/dist/i18n.d.ts.map +1 -0
  49. package/dist/i18n.js +1118 -0
  50. package/dist/i18n.js.map +1 -0
  51. package/dist/identity-bridge.d.ts +52 -0
  52. package/dist/identity-bridge.d.ts.map +1 -0
  53. package/dist/identity-bridge.js +228 -0
  54. package/dist/identity-bridge.js.map +1 -0
  55. package/dist/identity-tree.d.ts +47 -0
  56. package/dist/identity-tree.d.ts.map +1 -0
  57. package/dist/identity-tree.js +69 -0
  58. package/dist/identity-tree.js.map +1 -0
  59. package/dist/index.d.ts +55 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +86 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/key-derivation.d.ts +43 -0
  64. package/dist/key-derivation.d.ts.map +1 -0
  65. package/dist/key-derivation.js +212 -0
  66. package/dist/key-derivation.js.map +1 -0
  67. package/dist/lsag.d.ts +23 -0
  68. package/dist/lsag.d.ts.map +1 -0
  69. package/dist/lsag.js +35 -0
  70. package/dist/lsag.js.map +1 -0
  71. package/dist/merkle.d.ts +19 -0
  72. package/dist/merkle.d.ts.map +1 -0
  73. package/dist/merkle.js +155 -0
  74. package/dist/merkle.js.map +1 -0
  75. package/dist/policies.d.ts +22 -0
  76. package/dist/policies.d.ts.map +1 -0
  77. package/dist/policies.js +123 -0
  78. package/dist/policies.js.map +1 -0
  79. package/dist/range-proof.d.ts +6 -0
  80. package/dist/range-proof.d.ts.map +1 -0
  81. package/dist/range-proof.js +45 -0
  82. package/dist/range-proof.js.map +1 -0
  83. package/dist/relay.d.ts +106 -0
  84. package/dist/relay.d.ts.map +1 -0
  85. package/dist/relay.js +336 -0
  86. package/dist/relay.js.map +1 -0
  87. package/dist/ring-signature.d.ts +35 -0
  88. package/dist/ring-signature.d.ts.map +1 -0
  89. package/dist/ring-signature.js +56 -0
  90. package/dist/ring-signature.js.map +1 -0
  91. package/dist/shamir.d.ts +55 -0
  92. package/dist/shamir.d.ts.map +1 -0
  93. package/dist/shamir.js +253 -0
  94. package/dist/shamir.js.map +1 -0
  95. package/dist/signet-words.d.ts +42 -0
  96. package/dist/signet-words.d.ts.map +1 -0
  97. package/dist/signet-words.js +82 -0
  98. package/dist/signet-words.js.map +1 -0
  99. package/dist/store.d.ts +65 -0
  100. package/dist/store.d.ts.map +1 -0
  101. package/dist/store.js +290 -0
  102. package/dist/store.js.map +1 -0
  103. package/dist/trust-score.d.ts +9 -0
  104. package/dist/trust-score.d.ts.map +1 -0
  105. package/dist/trust-score.js +186 -0
  106. package/dist/trust-score.js.map +1 -0
  107. package/dist/types.d.ts +358 -0
  108. package/dist/types.d.ts.map +1 -0
  109. package/dist/types.js +15 -0
  110. package/dist/types.js.map +1 -0
  111. package/dist/utils.d.ts +11 -0
  112. package/dist/utils.d.ts.map +1 -0
  113. package/dist/utils.js +21 -0
  114. package/dist/utils.js.map +1 -0
  115. package/dist/validation.d.ts +33 -0
  116. package/dist/validation.d.ts.map +1 -0
  117. package/dist/validation.js +312 -0
  118. package/dist/validation.js.map +1 -0
  119. package/dist/verifiers.d.ts +18 -0
  120. package/dist/verifiers.d.ts.map +1 -0
  121. package/dist/verifiers.js +118 -0
  122. package/dist/verifiers.js.map +1 -0
  123. package/dist/vouches.d.ts +14 -0
  124. package/dist/vouches.d.ts.map +1 -0
  125. package/dist/vouches.js +103 -0
  126. package/dist/vouches.js.map +1 -0
  127. package/package.json +76 -0
  128. package/src/anomaly.ts +307 -0
  129. package/src/badge.ts +208 -0
  130. package/src/bonds.ts +203 -0
  131. package/src/challenges.ts +187 -0
  132. package/src/cold-call.ts +238 -0
  133. package/src/compliance.ts +612 -0
  134. package/src/connections.ts +216 -0
  135. package/src/constants.ts +146 -0
  136. package/src/credentials.ts +908 -0
  137. package/src/crypto.ts +85 -0
  138. package/src/errors.ts +31 -0
  139. package/src/i18n.ts +1347 -0
  140. package/src/identity-bridge.ts +262 -0
  141. package/src/identity-tree.ts +90 -0
  142. package/src/index.ts +452 -0
  143. package/src/lsag.ts +53 -0
  144. package/src/merkle.ts +176 -0
  145. package/src/policies.ts +154 -0
  146. package/src/range-proof.ts +66 -0
  147. package/src/relay.ts +433 -0
  148. package/src/ring-signature.ts +76 -0
  149. package/src/signet-words.ts +122 -0
  150. package/src/store.ts +336 -0
  151. package/src/trust-score.ts +208 -0
  152. package/src/types.ts +482 -0
  153. package/src/utils.ts +20 -0
  154. package/src/validation.ts +391 -0
  155. package/src/verifiers.ts +156 -0
  156. package/src/vouches.ts +141 -0
package/dist/index.js ADDED
@@ -0,0 +1,86 @@
1
+ // Signet Protocol — TypeScript Library
2
+ // Decentralised identity verification for Nostr
3
+ // Entity display labels (value export from types)
4
+ export { ENTITY_DISPLAY_LABELS } from './types.js';
5
+ // Constants
6
+ export { ATTESTATION_KIND, APP_DATA_KIND, ATTESTATION_TYPES, SIGNET_KINDS, SIGNET_LABEL, DEFAULT_VOUCH_THRESHOLD, DEFAULT_VOUCHER_MIN_TIER, DEFAULT_CREDENTIAL_EXPIRY_SECONDS, DEFAULT_REVOCATION_THRESHOLD, VERIFIER_ACTIVATION, TRUST_WEIGHTS, MAX_TRUST_SCORE, SIGNAL_PRIORITY, MIN_BRIDGE_RING_SIZE, ENTITY_TYPES, DELEGATION_CONSTRAINTS, ENTITY_LABELS, DEFAULT_CRYPTO_ALGORITHM,
7
+ // Bond constants
8
+ BOND_DOMAIN_SEPARATOR, DEFAULT_BOND_MAX_AGE_SECS, VALID_BOND_ADDRESS_TYPES, } from './constants.js';
9
+ // Crypto
10
+ export { generateKeyPair, getPublicKey, signEvent, verifyEvent, getEventId, hash, hashString, } from './crypto.js';
11
+ // Credentials (attestation type: credential)
12
+ export { buildCredentialEvent, createSelfDeclaredCredential, createPeerVouchedCredential, createProfessionalCredential, createChildSafetyCredential, verifyCredential, isCredentialExpired, parseCredential,
13
+ // Ring-signature protected credentials
14
+ createRingProtectedCredential, createRingProtectedChildCredential, verifyRingProtectedContent,
15
+ // Credential renewal
16
+ renewCredential, needsRenewal,
17
+ // Two-credential ceremony
18
+ createTwoCredentialCeremony,
19
+ // Credential chains
20
+ supersedeCredential, resolveCredentialChain, isSuperseded,
21
+ // Nullifier utilities
22
+ computeNullifier, checkNullifierDuplicate, buildNullifierChainTag,
23
+ // Multi-document nullifier families
24
+ computeNullifierFamily, buildNullifierFamilyTags, checkNullifierFamilyDuplicate,
25
+ // Guardian delegation
26
+ createGuardianDelegation, } from './credentials.js';
27
+ // Vouches (attestation type: vouch)
28
+ export { buildVouchEvent, createVouch, parseVouch, countQualifyingVouches, hasEnoughVouches, getVouchers, } from './vouches.js';
29
+ // Policies (NIP-78 kind 30078)
30
+ export { buildPolicyEvent, createPolicy, parsePolicy, checkPolicyCompliance, PolicyChecker, } from './policies.js';
31
+ // Verifiers (attestation type: verifier)
32
+ export { buildVerifierEvent, createVerifierCredential, parseVerifier, checkCrossVerification, isVerifierRevoked, } from './verifiers.js';
33
+ // Bonds (proof-of-reserve bond attestation)
34
+ export { buildBondMessage, createBondProof, verifyBondProof, isBondStale, bondProofToTags, parseBondProof, checkBondCompliance, } from './bonds.js';
35
+ // Challenges & Revocations (attestation types: challenge, revocation)
36
+ export { buildChallengeEvent, createChallenge, parseChallenge, buildRevocationEvent, createRevocation, parseRevocation, countChallengeConfirmations, hasReachedRevocationThreshold, } from './challenges.js';
37
+ // Signet Score
38
+ export { computeTrustScore, formatTrustDisplay, verifySignalOrdering, } from './trust-score.js';
39
+ // Merkle Tree
40
+ export { MerkleTree, verifyMerkleProof, verifySelectiveDisclosure, } from './merkle.js';
41
+ // Ring Signatures
42
+ export { MAX_RING_SIZE, ringSign, ringVerify, signCredentialRing, verifyCredentialRing, } from './ring-signature.js';
43
+ // LSAG (Linkable Ring Signatures)
44
+ export { MAX_RING_SIZE as LSAG_MAX_RING_SIZE, computeKeyImage, lsagSign, lsagVerify, hasDuplicateKeyImage, } from './lsag.js';
45
+ // Identity Bridge (attestation type: identity-bridge)
46
+ export { createIdentityBridge, verifyIdentityBridge, parseIdentityBridge, selectDecoyRing, computeBridgeWeight, } from './identity-bridge.js';
47
+ // Range Proofs (Pedersen Commitments)
48
+ export { commit, verifyCommitment, createRangeProof, verifyRangeProof, createAgeRangeProof, verifyAgeRangeProof, serializeRangeProof, deserializeRangeProof, } from './range-proof.js';
49
+ // Relay Client
50
+ export { RelayClient, publishToRelays, fetchFromRelay, } from './relay.js';
51
+ // Event Store
52
+ export { SignetStore } from './store.js';
53
+ // Anomaly Detection
54
+ export { detectAnomalies, scanForAnomalies, } from './anomaly.js';
55
+ // Jurisdictions (re-exported from jurisdiction-kit)
56
+ export { JURISDICTIONS, getJurisdiction, getJurisdictionCodes, getProfessionalBodies, getMutualRecognitionPartners, isProfessionRegulated, findJurisdictionsForProfession, getDigitalConsentAge, getAgeOfMajority, canTransferData, getAllLanguages, getJurisdictionsByLanguage, computeJurisdictionConfidence, getJurisdictionConfidence, rankJurisdictionsByConfidence, } from 'jurisdiction-kit';
57
+ // Internationalization
58
+ export { setLanguage, getLanguage, getSupportedLanguages, t, getTranslations, getLanguageName, getLanguageNativeName, formatLocalizedTrustScore, getTierDescription, } from './i18n.js';
59
+ // Compliance
60
+ export { checkCredentialCompliance, checkCrossBorderCompliance, checkChildCompliance, getConsentRequirements, getRetentionGuidance, checkMultiJurisdictionCompliance, getMostRestrictiveRequirements, } from './compliance.js';
61
+ // Validation
62
+ export { validateCredential, validateVouch, validatePolicy, validateVerifier, validateChallenge, validateRevocation, validateEvent, getTagValue, getTagValues, } from './validation.js';
63
+ // Errors
64
+ export { SignetError, SignetValidationError, SignetCryptoError, } from './errors.js';
65
+ // BIP-39 Wordlist
66
+ export { wordlist as BIP39_WORDLIST } from '@scure/bip39/wordlists/english.js';
67
+ // Mnemonic (BIP-39)
68
+ export { generateMnemonic, mnemonicToEntropy, entropyToMnemonic, validateMnemonic, } from '@scure/bip39';
69
+ export { mnemonicToSeedSync as mnemonicToSeed } from '@scure/bip39';
70
+ // Identity Tree (nsec-tree integration)
71
+ export { createSignetIdentity, createSignetIdentityFromNsec, deriveAdditionalPersona, deriveSubIdentity, createLinkageProof, verifyLinkageProof, destroyIdentity, NATURAL_PERSON_PERSONA, ANONYMOUS_PERSONA, } from './identity-tree.js';
72
+ // nsec-tree re-exports
73
+ export { zeroise } from 'nsec-tree';
74
+ // NIP-19 encoding (nsec-tree/encoding)
75
+ export { encodeNsec, decodeNsec, encodeNpub, decodeNpub } from 'nsec-tree/encoding';
76
+ // Shamir's Secret Sharing
77
+ export { splitSecret, reconstructSecret, shareToWords, wordsToShare, } from '@forgesworn/shamir-words';
78
+ // Connections (ECDH / QR Exchange)
79
+ export { computeSharedSecret, createQRPayload, serializeQRPayload, parseQRPayload, createConnection, ConnectionStore, } from './connections.js';
80
+ // Badge Display (Level 1 integration)
81
+ export { computeBadge, getTrustLevel, meetsMinimumTier, filterEventsForPubkey, buildBadgeFilters, } from './badge.js';
82
+ // Signet Words (Time-Based Verification — powered by spoken-token)
83
+ export { SIGNET_EPOCH_SECONDS, SIGNET_WORD_COUNT, SIGNET_TOLERANCE, MAX_WORD_COUNT, SIGNET_WORDLIST, getEpoch, deriveWords, getSignetWords, verifySignetWords, formatSignetWords, getSignetDisplay, } from './signet-words.js';
84
+ // Cold-Call Verification (institutional caller verification via .well-known/signet.json + ephemeral ECDH)
85
+ export { fetchInstitutionKeys, generateSessionCode, deriveColdCallWords, initiateColdCallVerification, completeColdCallVerification, } from './cold-call.js';
86
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /** Encode a 32-byte private key as an nsec bech32 string (NIP-19) */
2
+ export declare function encodeNsec(privateKey: string): string;
3
+ /** Encode a 32-byte public key as an npub bech32 string (NIP-19) */
4
+ export declare function encodeNpub(publicKey: string): string;
5
+ /** Decode an nsec bech32 string to private + public key hex (NIP-19) */
6
+ export declare function decodeNsec(nsec: string): {
7
+ privateKey: string;
8
+ publicKey: string;
9
+ };
10
+ /** NIP-06 derivation path: m/44'/1237'/0'/0/0 */
11
+ export declare const NIP06_DERIVATION_PATH = "m/44'/1237'/0'/0/0";
12
+ /** Parse a BIP-32 derivation path into numeric indices.
13
+ * Retained for backwards compatibility — @scure/bip32 handles paths internally. */
14
+ export declare function parsePath(path: string): number[];
15
+ /** Derive a private key at the given BIP-32 path from a seed.
16
+ * Uses @scure/bip32 (audited BIP-32 implementation by paulmillr). */
17
+ export declare function deriveKeyFromSeed(seed: Uint8Array, path: string): Uint8Array;
18
+ /** Derive a Nostr keypair from a BIP-39 mnemonic using NIP-06 path.
19
+ *
20
+ * SECURITY NOTE: Intermediate Uint8Arrays (seed, key bytes) are zeroed after use,
21
+ * but the returned hex strings are JS primitives and cannot be wiped from memory.
22
+ * This is a fundamental limitation of the JavaScript runtime. */
23
+ export declare function deriveNostrKeyPair(mnemonic: string, passphrase?: string): {
24
+ privateKey: string;
25
+ publicKey: string;
26
+ };
27
+ /** Create a full Signet identity from a mnemonic.
28
+ *
29
+ * WARNING: The returned object contains the mnemonic alongside the private key.
30
+ * Do not serialise, log, or persist this object without first removing the
31
+ * mnemonic. The caller is responsible for discarding the mnemonic as quickly
32
+ * as possible. Mnemonics must never be stored in plaintext (use crypto-store.ts). */
33
+ export declare function createIdentityFromMnemonic(mnemonic: string, passphrase?: string): {
34
+ mnemonic: string;
35
+ privateKey: string;
36
+ publicKey: string;
37
+ };
38
+ /** Derive a child account keypair (e.g., for a child's account) at a given account index */
39
+ export declare function deriveChildAccount(mnemonic: string, accountIndex: number, passphrase?: string): {
40
+ privateKey: string;
41
+ publicKey: string;
42
+ };
43
+ //# sourceMappingURL=key-derivation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-derivation.d.ts","sourceRoot":"","sources":["../src/key-derivation.ts"],"names":[],"mappings":"AAsGA,qEAAqE;AACrE,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAKrD;AAED,oEAAoE;AACpE,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAKpD;AAED,wEAAwE;AACxE,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAUlF;AAED,iDAAiD;AACjD,eAAO,MAAM,qBAAqB,uBAAuB,CAAC;AAQ1D;oFACoF;AACpF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAiBhD;AAED;sEACsE;AACtE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,CAU5E;AAED;;;;kEAIkE;AAClE,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,GAClB;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAa3C;AAED;;;;;qFAKqF;AACrF,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,GAClB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAG7D;AAED,4FAA4F;AAC5F,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,GAClB;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAe3C"}
@@ -0,0 +1,212 @@
1
+ // NIP-06 Nostr Key Derivation & NIP-19 nsec/npub encoding
2
+ // Derives Nostr keypairs from BIP-39 mnemonics via @scure/bip32
3
+ // Also provides nsec/npub bech32 encoding (NIP-19)
4
+ import { secp256k1 } from '@noble/curves/secp256k1';
5
+ import { bytesToHex, hexToBytes } from '@noble/hashes/utils';
6
+ import { mnemonicToSeedSync } from '@scure/bip39';
7
+ import { HDKey } from '@scure/bip32';
8
+ import { zeroBytes } from './utils.js';
9
+ import { SignetValidationError, SignetCryptoError } from './errors.js';
10
+ // --- Bech32 encoding/decoding (BIP-173) for NIP-19 nsec/npub ---
11
+ const BECH32_CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
12
+ function bech32Polymod(values) {
13
+ const GEN = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
14
+ let chk = 1;
15
+ for (const v of values) {
16
+ const b = chk >> 25;
17
+ chk = ((chk & 0x1ffffff) << 5) ^ v;
18
+ for (let i = 0; i < 5; i++) {
19
+ if ((b >> i) & 1)
20
+ chk ^= GEN[i];
21
+ }
22
+ }
23
+ return chk;
24
+ }
25
+ function bech32HrpExpand(hrp) {
26
+ const ret = [];
27
+ for (let i = 0; i < hrp.length; i++)
28
+ ret.push(hrp.charCodeAt(i) >> 5);
29
+ ret.push(0);
30
+ for (let i = 0; i < hrp.length; i++)
31
+ ret.push(hrp.charCodeAt(i) & 31);
32
+ return ret;
33
+ }
34
+ function bech32CreateChecksum(hrp, data) {
35
+ const values = bech32HrpExpand(hrp).concat(data).concat([0, 0, 0, 0, 0, 0]);
36
+ const polymod = bech32Polymod(values) ^ 1;
37
+ const ret = [];
38
+ for (let i = 0; i < 6; i++)
39
+ ret.push((polymod >> (5 * (5 - i))) & 31);
40
+ return ret;
41
+ }
42
+ function bech32VerifyChecksum(hrp, data) {
43
+ return bech32Polymod(bech32HrpExpand(hrp).concat(data)) === 1;
44
+ }
45
+ function bech32Encode(hrp, data) {
46
+ const checksum = bech32CreateChecksum(hrp, data);
47
+ const combined = data.concat(checksum);
48
+ let ret = hrp + '1';
49
+ for (const d of combined)
50
+ ret += BECH32_CHARSET[d];
51
+ return ret;
52
+ }
53
+ function bech32Decode(str) {
54
+ const lower = str.toLowerCase();
55
+ if (lower !== str && str.toUpperCase() !== str) {
56
+ throw new SignetValidationError('Mixed-case bech32 string');
57
+ }
58
+ const s = lower;
59
+ const pos = s.lastIndexOf('1');
60
+ if (pos < 1 || pos + 7 > s.length || s.length > 90) {
61
+ throw new SignetValidationError('Invalid bech32 string');
62
+ }
63
+ const hrp = s.slice(0, pos);
64
+ const dataChars = s.slice(pos + 1);
65
+ const data = [];
66
+ for (const c of dataChars) {
67
+ const idx = BECH32_CHARSET.indexOf(c);
68
+ if (idx === -1)
69
+ throw new SignetValidationError(`Invalid bech32 character: ${c}`);
70
+ data.push(idx);
71
+ }
72
+ if (!bech32VerifyChecksum(hrp, data)) {
73
+ throw new SignetValidationError('Invalid bech32 checksum');
74
+ }
75
+ return { hrp, data: data.slice(0, data.length - 6) };
76
+ }
77
+ function convertBits(data, fromBits, toBits, pad) {
78
+ let acc = 0;
79
+ let bits = 0;
80
+ const ret = [];
81
+ const maxv = (1 << toBits) - 1;
82
+ for (const value of data) {
83
+ if (value < 0 || value >> fromBits !== 0)
84
+ throw new SignetValidationError('Invalid value for convertBits');
85
+ acc = (acc << fromBits) | value;
86
+ bits += fromBits;
87
+ while (bits >= toBits) {
88
+ bits -= toBits;
89
+ ret.push((acc >> bits) & maxv);
90
+ }
91
+ }
92
+ if (pad) {
93
+ if (bits > 0)
94
+ ret.push((acc << (toBits - bits)) & maxv);
95
+ }
96
+ else if (bits >= fromBits || ((acc << (toBits - bits)) & maxv) !== 0) {
97
+ throw new SignetValidationError('Invalid padding in convertBits');
98
+ }
99
+ return ret;
100
+ }
101
+ /** Encode a 32-byte private key as an nsec bech32 string (NIP-19) */
102
+ export function encodeNsec(privateKey) {
103
+ const bytes = hexToBytes(privateKey);
104
+ if (bytes.length !== 32)
105
+ throw new SignetValidationError('Private key must be 32 bytes');
106
+ const data5bit = convertBits(Array.from(bytes), 8, 5, true);
107
+ return bech32Encode('nsec', data5bit);
108
+ }
109
+ /** Encode a 32-byte public key as an npub bech32 string (NIP-19) */
110
+ export function encodeNpub(publicKey) {
111
+ const bytes = hexToBytes(publicKey);
112
+ if (bytes.length !== 32)
113
+ throw new SignetValidationError('Public key must be 32 bytes');
114
+ const data5bit = convertBits(Array.from(bytes), 8, 5, true);
115
+ return bech32Encode('npub', data5bit);
116
+ }
117
+ /** Decode an nsec bech32 string to private + public key hex (NIP-19) */
118
+ export function decodeNsec(nsec) {
119
+ const { hrp, data } = bech32Decode(nsec);
120
+ if (hrp !== 'nsec')
121
+ throw new SignetValidationError(`Expected nsec prefix, got ${hrp}`);
122
+ const bytes = convertBits(data, 5, 8, false);
123
+ if (bytes.length !== 32)
124
+ throw new SignetValidationError('Invalid nsec: decoded to wrong length');
125
+ const privateKey = bytesToHex(new Uint8Array(bytes));
126
+ // Derive x-only public key from private key
127
+ const fullPubkey = secp256k1.getPublicKey(new Uint8Array(bytes), true);
128
+ const publicKey = bytesToHex(fullPubkey.slice(1));
129
+ return { privateKey, publicKey };
130
+ }
131
+ /** NIP-06 derivation path: m/44'/1237'/0'/0/0 */
132
+ export const NIP06_DERIVATION_PATH = "m/44'/1237'/0'/0/0";
133
+ /** Maximum derivation path depth — prevents CPU-bound DoS on untrusted paths */
134
+ const MAX_PATH_DEPTH = 10;
135
+ /** Hardened offset for BIP-32 */
136
+ const HARDENED_OFFSET = 0x80000000;
137
+ /** Parse a BIP-32 derivation path into numeric indices.
138
+ * Retained for backwards compatibility — @scure/bip32 handles paths internally. */
139
+ export function parsePath(path) {
140
+ if (!path.startsWith('m/')) {
141
+ throw new SignetValidationError('Derivation path must start with m/');
142
+ }
143
+ const segments = path.slice(2).split('/');
144
+ if (segments.length > MAX_PATH_DEPTH) {
145
+ throw new SignetValidationError(`Derivation path too deep: ${segments.length} levels (max ${MAX_PATH_DEPTH})`);
146
+ }
147
+ return segments
148
+ .map((segment) => {
149
+ const hardened = segment.endsWith("'") || segment.endsWith('h');
150
+ const index = parseInt(hardened ? segment.slice(0, -1) : segment, 10);
151
+ if (isNaN(index) || index < 0) {
152
+ throw new SignetValidationError(`Invalid path segment: ${segment}`);
153
+ }
154
+ return hardened ? index + HARDENED_OFFSET : index;
155
+ });
156
+ }
157
+ /** Derive a private key at the given BIP-32 path from a seed.
158
+ * Uses @scure/bip32 (audited BIP-32 implementation by paulmillr). */
159
+ export function deriveKeyFromSeed(seed, path) {
160
+ // Validate path depth before delegating to @scure/bip32
161
+ parsePath(path);
162
+ const master = HDKey.fromMasterSeed(seed);
163
+ const child = master.derive(path);
164
+ if (!child.privateKey) {
165
+ throw new SignetCryptoError('Key derivation produced no private key');
166
+ }
167
+ // Return a copy — HDKey owns its internal buffer
168
+ return Uint8Array.from(child.privateKey);
169
+ }
170
+ /** Derive a Nostr keypair from a BIP-39 mnemonic using NIP-06 path.
171
+ *
172
+ * SECURITY NOTE: Intermediate Uint8Arrays (seed, key bytes) are zeroed after use,
173
+ * but the returned hex strings are JS primitives and cannot be wiped from memory.
174
+ * This is a fundamental limitation of the JavaScript runtime. */
175
+ export function deriveNostrKeyPair(mnemonic, passphrase) {
176
+ const seed = mnemonicToSeedSync(mnemonic, passphrase);
177
+ const privateKeyBytes = deriveKeyFromSeed(seed, NIP06_DERIVATION_PATH);
178
+ zeroBytes(seed);
179
+ const privateKey = bytesToHex(privateKeyBytes);
180
+ // x-only public key (BIP-340 / Nostr convention)
181
+ const fullPubkey = secp256k1.getPublicKey(privateKeyBytes, true); // 33 bytes compressed
182
+ // Drop the prefix byte to get x-only (32 bytes)
183
+ const publicKey = bytesToHex(fullPubkey.slice(1));
184
+ zeroBytes(privateKeyBytes);
185
+ return { privateKey, publicKey };
186
+ }
187
+ /** Create a full Signet identity from a mnemonic.
188
+ *
189
+ * WARNING: The returned object contains the mnemonic alongside the private key.
190
+ * Do not serialise, log, or persist this object without first removing the
191
+ * mnemonic. The caller is responsible for discarding the mnemonic as quickly
192
+ * as possible. Mnemonics must never be stored in plaintext (use crypto-store.ts). */
193
+ export function createIdentityFromMnemonic(mnemonic, passphrase) {
194
+ const { privateKey, publicKey } = deriveNostrKeyPair(mnemonic, passphrase);
195
+ return { mnemonic, privateKey, publicKey };
196
+ }
197
+ /** Derive a child account keypair (e.g., for a child's account) at a given account index */
198
+ export function deriveChildAccount(mnemonic, accountIndex, passphrase) {
199
+ if (!Number.isSafeInteger(accountIndex) || accountIndex < 0 || accountIndex > 0x7fffffff) {
200
+ throw new SignetValidationError('accountIndex must be an integer in [0, 2^31 - 1]');
201
+ }
202
+ const seed = mnemonicToSeedSync(mnemonic, passphrase);
203
+ const path = `m/44'/1237'/${accountIndex}'/0/0`;
204
+ const privateKeyBytes = deriveKeyFromSeed(seed, path);
205
+ zeroBytes(seed);
206
+ const privateKey = bytesToHex(privateKeyBytes);
207
+ const fullPubkey = secp256k1.getPublicKey(privateKeyBytes, true);
208
+ const publicKey = bytesToHex(fullPubkey.slice(1));
209
+ zeroBytes(privateKeyBytes);
210
+ return { privateKey, publicKey };
211
+ }
212
+ //# sourceMappingURL=key-derivation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-derivation.js","sourceRoot":"","sources":["../src/key-derivation.ts"],"names":[],"mappings":"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"}
package/dist/lsag.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ import { computeKeyImage as _computeKeyImage, hasDuplicateKeyImage as _hasDuplicateKeyImage, type LsagSignature, MAX_RING_SIZE } from '@forgesworn/ring-sig';
2
+ export { type LsagSignature, MAX_RING_SIZE };
3
+ export declare const computeKeyImage: typeof _computeKeyImage;
4
+ export declare const hasDuplicateKeyImage: typeof _hasDuplicateKeyImage;
5
+ /**
6
+ * Sign with LSAG using Signet's domain separator.
7
+ *
8
+ * @param message - The message to sign (typically `electionId:SHA-256(encryptedVote)`)
9
+ * @param ring - Array of x-only public keys (hex) forming the anonymity set
10
+ * @param signerIndex - Index of the actual signer in the ring
11
+ * @param privateKey - Signer's private key (hex)
12
+ * @param electionId - Election identifier for key image linkability
13
+ * @returns A linkable ring signature with Signet domain
14
+ */
15
+ export declare function lsagSign(message: string, ring: string[], signerIndex: number, privateKey: string, electionId: string): LsagSignature;
16
+ /**
17
+ * Verify an LSAG signature.
18
+ *
19
+ * @param sig - The LSAG signature to verify
20
+ * @returns true if the signature is valid
21
+ */
22
+ export declare function lsagVerify(sig: LsagSignature): boolean;
23
+ //# sourceMappingURL=lsag.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lsag.d.ts","sourceRoot":"","sources":["../src/lsag.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,eAAe,IAAI,gBAAgB,EACnC,oBAAoB,IAAI,qBAAqB,EAG7C,KAAK,aAAa,EAClB,aAAa,EACd,MAAM,sBAAsB,CAAC;AAI9B,OAAO,EAAE,KAAK,aAAa,EAAE,aAAa,EAAE,CAAC;AAG7C,eAAO,MAAM,eAAe,yBAAmB,CAAC;AAChD,eAAO,MAAM,oBAAoB,8BAAwB,CAAC;AAE1D;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CACtB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,aAAa,CAIf;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAEtD"}
package/dist/lsag.js ADDED
@@ -0,0 +1,35 @@
1
+ // LSAG (Linkable Spontaneous Anonymous Group) Ring Signatures
2
+ // Thin re-export from @forgesworn/ring-sig with Signet domain separator.
3
+ // Extends SAG with a key image that links signatures by the same signer
4
+ // across multiple uses of the same election, enabling double-vote detection.
5
+ import { computeKeyImage as _computeKeyImage, hasDuplicateKeyImage as _hasDuplicateKeyImage, lsagSign as _lsagSign, lsagVerify as _lsagVerify, MAX_RING_SIZE, } from '@forgesworn/ring-sig';
6
+ const SIGNET_LSAG_DOMAIN = 'signet-lsag-v1';
7
+ export { MAX_RING_SIZE };
8
+ // Key image functions do not involve challenge hashes — safe to re-export directly.
9
+ export const computeKeyImage = _computeKeyImage;
10
+ export const hasDuplicateKeyImage = _hasDuplicateKeyImage;
11
+ /**
12
+ * Sign with LSAG using Signet's domain separator.
13
+ *
14
+ * @param message - The message to sign (typically `electionId:SHA-256(encryptedVote)`)
15
+ * @param ring - Array of x-only public keys (hex) forming the anonymity set
16
+ * @param signerIndex - Index of the actual signer in the ring
17
+ * @param privateKey - Signer's private key (hex)
18
+ * @param electionId - Election identifier for key image linkability
19
+ * @returns A linkable ring signature with Signet domain
20
+ */
21
+ export function lsagSign(message, ring, signerIndex, privateKey, electionId) {
22
+ const sig = _lsagSign(message, ring, signerIndex, privateKey, electionId, SIGNET_LSAG_DOMAIN);
23
+ sig.domain = SIGNET_LSAG_DOMAIN;
24
+ return sig;
25
+ }
26
+ /**
27
+ * Verify an LSAG signature.
28
+ *
29
+ * @param sig - The LSAG signature to verify
30
+ * @returns true if the signature is valid
31
+ */
32
+ export function lsagVerify(sig) {
33
+ return _lsagVerify(sig);
34
+ }
35
+ //# sourceMappingURL=lsag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lsag.js","sourceRoot":"","sources":["../src/lsag.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,yEAAyE;AACzE,wEAAwE;AACxE,6EAA6E;AAE7E,OAAO,EACL,eAAe,IAAI,gBAAgB,EACnC,oBAAoB,IAAI,qBAAqB,EAC7C,QAAQ,IAAI,SAAS,EACrB,UAAU,IAAI,WAAW,EAEzB,aAAa,GACd,MAAM,sBAAsB,CAAC;AAE9B,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;AAE5C,OAAO,EAAsB,aAAa,EAAE,CAAC;AAE7C,oFAAoF;AACpF,MAAM,CAAC,MAAM,eAAe,GAAG,gBAAgB,CAAC;AAChD,MAAM,CAAC,MAAM,oBAAoB,GAAG,qBAAqB,CAAC;AAE1D;;;;;;;;;GASG;AACH,MAAM,UAAU,QAAQ,CACtB,OAAe,EACf,IAAc,EACd,WAAmB,EACnB,UAAkB,EAClB,UAAkB;IAElB,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,kBAAkB,CAAC,CAAC;IAC9F,GAAG,CAAC,MAAM,GAAG,kBAAkB,CAAC;IAChC,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,GAAkB;IAC3C,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { MerkleProof, SelectiveDisclosure } from './types.js';
2
+ export declare class MerkleTree {
3
+ private attributes;
4
+ private levels;
5
+ private leafHashes;
6
+ readonly root: string;
7
+ constructor(attributes: Record<string, string>);
8
+ /** Get the Merkle root */
9
+ getRoot(): string;
10
+ /** Generate a proof for a specific attribute */
11
+ prove(key: string): MerkleProof;
12
+ /** Create a selective disclosure revealing only specified attributes */
13
+ disclose(keys: string[]): SelectiveDisclosure;
14
+ }
15
+ /** Verify a Merkle proof against a root */
16
+ export declare function verifyMerkleProof(key: string, value: string, proof: MerkleProof): boolean;
17
+ /** Verify an entire selective disclosure */
18
+ export declare function verifySelectiveDisclosure(disclosure: SelectiveDisclosure): boolean;
19
+ //# sourceMappingURL=merkle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merkle.d.ts","sourceRoot":"","sources":["../src/merkle.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAiEnE,qBAAa,UAAU;IAKT,OAAO,CAAC,UAAU;IAJ9B,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,UAAU,CAAW;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEF,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAWtD,0BAA0B;IAC1B,OAAO,IAAI,MAAM;IAIjB,gDAAgD;IAChD,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW;IA0B/B,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,mBAAmB;CAmB9C;AAED,2CAA2C;AAC3C,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,WAAW,GACjB,OAAO,CAcT;AAED,4CAA4C;AAC5C,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,mBAAmB,GAAG,OAAO,CAalF"}
package/dist/merkle.js ADDED
@@ -0,0 +1,155 @@
1
+ // Merkle Tree Selective Disclosure
2
+ // Credential attributes as Merkle leaves — reveal chosen attributes + sibling paths
3
+ import { sha256 } from '@noble/hashes/sha2.js';
4
+ import { bytesToHex, hexToBytes, utf8ToBytes } from '@noble/hashes/utils.js';
5
+ import { SignetValidationError } from './errors.js';
6
+ /**
7
+ * Hash a leaf node with domain separation prefix 0x00.
8
+ * Leaf hash: SHA-256(0x00 || "key:value")
9
+ * RFC 6962 domain separation prevents second-preimage attacks.
10
+ */
11
+ function hashLeaf(data) {
12
+ const prefix = new Uint8Array([0x00]);
13
+ const content = utf8ToBytes(data);
14
+ const combined = new Uint8Array(1 + content.length);
15
+ combined.set(prefix);
16
+ combined.set(content, 1);
17
+ return bytesToHex(sha256(combined));
18
+ }
19
+ /**
20
+ * Hash an internal node with domain separation prefix 0x01.
21
+ * Internal node hash: SHA-256(0x01 || left || right)
22
+ * RFC 6962 domain separation prevents second-preimage attacks.
23
+ */
24
+ function hashInternal(left, right) {
25
+ const prefix = new Uint8Array([0x01]);
26
+ const leftBytes = hexToBytes(left);
27
+ const rightBytes = hexToBytes(right);
28
+ const combined = new Uint8Array(1 + leftBytes.length + rightBytes.length);
29
+ combined.set(prefix);
30
+ combined.set(leftBytes, 1);
31
+ combined.set(rightBytes, 1 + leftBytes.length);
32
+ return bytesToHex(sha256(combined));
33
+ }
34
+ /** Combine two child hashes into a parent node.
35
+ * Order is determined by tree position (left/right), NOT by hash value.
36
+ * Sorting would allow proof transplanting between sibling positions. */
37
+ function hashPairOrdered(left, right) {
38
+ return hashInternal(left, right);
39
+ }
40
+ /** Build a Merkle tree from leaf values. Returns all levels (bottom-up). */
41
+ function buildTree(leaves) {
42
+ if (leaves.length === 0)
43
+ throw new SignetValidationError('Cannot build tree from empty leaves');
44
+ // Pad to power of 2
45
+ const paddedLeaves = [...leaves];
46
+ while (paddedLeaves.length & (paddedLeaves.length - 1)) {
47
+ paddedLeaves.push(hashLeaf('__padding__' + paddedLeaves.length));
48
+ }
49
+ const levels = [paddedLeaves];
50
+ let current = paddedLeaves;
51
+ while (current.length > 1) {
52
+ const next = [];
53
+ for (let i = 0; i < current.length; i += 2) {
54
+ next.push(hashPairOrdered(current[i], current[i + 1]));
55
+ }
56
+ levels.push(next);
57
+ current = next;
58
+ }
59
+ return levels;
60
+ }
61
+ export class MerkleTree {
62
+ attributes;
63
+ levels;
64
+ leafHashes;
65
+ root;
66
+ constructor(attributes) {
67
+ this.attributes = attributes;
68
+ for (const k of Object.keys(attributes)) {
69
+ if (k.includes(':'))
70
+ throw new SignetValidationError(`Merkle attribute key must not contain ':': "${k}"`);
71
+ }
72
+ const entries = Object.entries(attributes).sort(([a], [b]) => a.localeCompare(b));
73
+ // Each leaf is hashLeaf("key:value") — domain-separated with 0x00 prefix
74
+ this.leafHashes = entries.map(([k, v]) => hashLeaf(`${k}:${v}`));
75
+ this.levels = buildTree(this.leafHashes);
76
+ this.root = this.levels[this.levels.length - 1][0];
77
+ }
78
+ /** Get the Merkle root */
79
+ getRoot() {
80
+ return this.root;
81
+ }
82
+ /** Generate a proof for a specific attribute */
83
+ prove(key) {
84
+ const entries = Object.entries(this.attributes).sort(([a], [b]) => a.localeCompare(b));
85
+ const idx = entries.findIndex(([k]) => k === key);
86
+ if (idx === -1)
87
+ throw new SignetValidationError(`Attribute "${key}" not found`);
88
+ const leafHash = this.leafHashes[idx];
89
+ const siblings = [];
90
+ let currentIdx = idx;
91
+ // Pad index space to match padded tree
92
+ for (let level = 0; level < this.levels.length - 1; level++) {
93
+ const siblingIdx = currentIdx ^ 1; // flip last bit to get sibling
94
+ if (siblingIdx < this.levels[level].length) {
95
+ siblings.push(this.levels[level][siblingIdx]);
96
+ }
97
+ currentIdx = currentIdx >> 1;
98
+ }
99
+ return {
100
+ leaf: leafHash,
101
+ index: idx,
102
+ siblings,
103
+ root: this.root,
104
+ };
105
+ }
106
+ /** Create a selective disclosure revealing only specified attributes */
107
+ disclose(keys) {
108
+ const revealedAttributes = {};
109
+ const proofs = [];
110
+ for (const key of keys) {
111
+ const entries = Object.entries(this.attributes).sort(([a], [b]) => a.localeCompare(b));
112
+ const entry = entries.find(([k]) => k === key);
113
+ if (!entry)
114
+ throw new SignetValidationError(`Attribute "${key}" not found`);
115
+ revealedAttributes[key] = entry[1];
116
+ proofs.push(this.prove(key));
117
+ }
118
+ return {
119
+ revealedAttributes,
120
+ proofs,
121
+ merkleRoot: this.root,
122
+ };
123
+ }
124
+ }
125
+ /** Verify a Merkle proof against a root */
126
+ export function verifyMerkleProof(key, value, proof) {
127
+ let currentHash = hashLeaf(`${key}:${value}`);
128
+ if (currentHash !== proof.leaf)
129
+ return false;
130
+ let idx = proof.index;
131
+ for (const sibling of proof.siblings) {
132
+ // Use index bit to determine left/right position — NOT sorted ordering
133
+ currentHash = (idx & 1) === 0
134
+ ? hashPairOrdered(currentHash, sibling)
135
+ : hashPairOrdered(sibling, currentHash);
136
+ idx = idx >> 1;
137
+ }
138
+ return currentHash === proof.root;
139
+ }
140
+ /** Verify an entire selective disclosure */
141
+ export function verifySelectiveDisclosure(disclosure) {
142
+ const entries = Object.entries(disclosure.revealedAttributes);
143
+ if (entries.length !== disclosure.proofs.length)
144
+ return false;
145
+ for (let i = 0; i < entries.length; i++) {
146
+ const [key, value] = entries[i];
147
+ const proof = disclosure.proofs[i];
148
+ if (proof.root !== disclosure.merkleRoot)
149
+ return false;
150
+ if (!verifyMerkleProof(key, value, proof))
151
+ return false;
152
+ }
153
+ return true;
154
+ }
155
+ //# sourceMappingURL=merkle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merkle.js","sourceRoot":"","sources":["../src/merkle.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,oFAAoF;AAEpF,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEpD;;;;GAIG;AACH,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,IAAI,UAAU,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACrB,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACzB,OAAO,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;AACtC,CAAC;AAED;;;;GAIG;AACH,SAAS,YAAY,CAAC,IAAY,EAAE,KAAa;IAC/C,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACtC,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,IAAI,UAAU,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAC1E,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACrB,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;IAC3B,QAAQ,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAC/C,OAAO,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;AACtC,CAAC;AAED;;yEAEyE;AACzE,SAAS,eAAe,CAAC,IAAY,EAAE,KAAa;IAClD,OAAO,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACnC,CAAC;AAED,4EAA4E;AAC5E,SAAS,SAAS,CAAC,MAAgB;IACjC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,qBAAqB,CAAC,qCAAqC,CAAC,CAAC;IAEhG,oBAAoB;IACpB,MAAM,YAAY,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;IACjC,OAAO,YAAY,CAAC,MAAM,GAAG,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;QACvD,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,MAAM,GAAe,CAAC,YAAY,CAAC,CAAC;IAC1C,IAAI,OAAO,GAAG,YAAY,CAAC;IAE3B,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAa,EAAE,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3C,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClB,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,OAAO,UAAU;IAKD;IAJZ,MAAM,CAAa;IACnB,UAAU,CAAW;IACpB,IAAI,CAAS;IAEtB,YAAoB,UAAkC;QAAlC,eAAU,GAAV,UAAU,CAAwB;QACpD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,MAAM,IAAI,qBAAqB,CAAC,+CAA+C,CAAC,GAAG,CAAC,CAAC;QAC5G,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QAClF,yEAAyE;QACzE,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACjE,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,0BAA0B;IAC1B,OAAO;QACL,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,gDAAgD;IAChD,KAAK,CAAC,GAAW;QACf,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QACvF,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;QAClD,IAAI,GAAG,KAAK,CAAC,CAAC;YAAE,MAAM,IAAI,qBAAqB,CAAC,cAAc,GAAG,aAAa,CAAC,CAAC;QAEhF,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,IAAI,UAAU,GAAG,GAAG,CAAC;QAErB,uCAAuC;QACvC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;YAC5D,MAAM,UAAU,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,+BAA+B;YAClE,IAAI,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;gBAC3C,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;YAChD,CAAC;YACD,UAAU,GAAG,UAAU,IAAI,CAAC,CAAC;QAC/B,CAAC;QAED,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,GAAG;YACV,QAAQ;YACR,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC;IACJ,CAAC;IAED,wEAAwE;IACxE,QAAQ,CAAC,IAAc;QACrB,MAAM,kBAAkB,GAA2B,EAAE,CAAC;QACtD,MAAM,MAAM,GAAkB,EAAE,CAAC;QAEjC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;YACvF,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;YAC/C,IAAI,CAAC,KAAK;gBAAE,MAAM,IAAI,qBAAqB,CAAC,cAAc,GAAG,aAAa,CAAC,CAAC;YAE5E,kBAAkB,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACnC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/B,CAAC;QAED,OAAO;YACL,kBAAkB;YAClB,MAAM;YACN,UAAU,EAAE,IAAI,CAAC,IAAI;SACtB,CAAC;IACJ,CAAC;CACF;AAED,2CAA2C;AAC3C,MAAM,UAAU,iBAAiB,CAC/B,GAAW,EACX,KAAa,EACb,KAAkB;IAElB,IAAI,WAAW,GAAG,QAAQ,CAAC,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC;IAC9C,IAAI,WAAW,KAAK,KAAK,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IAE7C,IAAI,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC;IACtB,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACrC,uEAAuE;QACvE,WAAW,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC;YAC3B,CAAC,CAAC,eAAe,CAAC,WAAW,EAAE,OAAO,CAAC;YACvC,CAAC,CAAC,eAAe,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QAC1C,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC;IACjB,CAAC;IAED,OAAO,WAAW,KAAK,KAAK,CAAC,IAAI,CAAC;AACpC,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,yBAAyB,CAAC,UAA+B;IACvE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;IAC9D,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,CAAC,MAAM,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAE9D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAEnC,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,UAAU;YAAE,OAAO,KAAK,CAAC;QACvD,IAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;IAC1D,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}