@solidus-network/auth 0.6.0 → 0.6.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.
@@ -17,4 +17,39 @@ export interface Challenge {
17
17
  * @param ttlSeconds - How long the challenge is valid (default: 300 = 5 minutes)
18
18
  */
19
19
  export declare function createChallenge(did: string, ttlSeconds?: number): Challenge;
20
+ export interface BbsChallenge {
21
+ /** UUID, for idempotency and storage. */
22
+ id: string;
23
+ /**
24
+ * The verifier's AUTHENTICATED origin (e.g. its TLS hostname). Folded
25
+ * into the presentation header, so a proof made for this verifier
26
+ * fails at every other one.
27
+ */
28
+ domain: string;
29
+ /** The credential type this challenge accepts (pins the header cohort). */
30
+ credentialType: string;
31
+ /** Message indices the presenter must disclose. */
32
+ requiredIndices: number[];
33
+ /** 32-byte random hex — folded into the presentation header. */
34
+ nonce: string;
35
+ /** ISO 8601 */
36
+ issuedAt: string;
37
+ /** ISO 8601 */
38
+ expiresAt: string;
39
+ }
40
+ /**
41
+ * Create a DID-less selective-disclosure challenge. Carries no DID by
42
+ * construction — the verifier learns only what the disclosed indices say.
43
+ *
44
+ * The CALLER stores the challenge and must enforce single-use (mark it
45
+ * used once a presentation verifies) — the cryptographic ph binding kills
46
+ * cross-challenge replay, storage-side bookkeeping kills same-challenge
47
+ * re-submission.
48
+ */
49
+ export declare function createBbsChallenge(opts: {
50
+ domain: string;
51
+ credentialType: string;
52
+ requiredIndices: number[];
53
+ ttlSeconds?: number;
54
+ }): BbsChallenge;
20
55
  //# sourceMappingURL=challenge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"challenge.d.ts","sourceRoot":"","sources":["../src/challenge.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IACxB,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAA;IACV,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAA;IACX,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAA;IACb,eAAe;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe;IACf,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,SAAM,GAAG,SAAS,CAUxE"}
1
+ {"version":3,"file":"challenge.d.ts","sourceRoot":"","sources":["../src/challenge.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IACxB,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAA;IACV,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAA;IACX,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAA;IACb,eAAe;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe;IACf,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,SAAM,GAAG,SAAS,CAUxE;AASD,MAAM,WAAW,YAAY;IAC3B,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAA;IACV;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAA;IACd,2EAA2E;IAC3E,cAAc,EAAE,MAAM,CAAA;IACtB,mDAAmD;IACnD,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAA;IACb,eAAe;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe;IACf,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,MAAM,CAAA;IACtB,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,GAAG,YAAY,CA0Bf"}
package/dist/challenge.js CHANGED
@@ -16,4 +16,43 @@ export function createChallenge(did, ttlSeconds = 300) {
16
16
  expiresAt: expiresAt.toISOString(),
17
17
  };
18
18
  }
19
+ // ---------------------------------------------------------------------------
20
+ // DID-less BBS challenge (privacy rebuild §5.3) — additive beside the
21
+ // DID-bound challenge above; never a replacement.
22
+ // ---------------------------------------------------------------------------
23
+ import { ALWAYS_HIDDEN_KYC_INDICES } from './envelope.js';
24
+ /**
25
+ * Create a DID-less selective-disclosure challenge. Carries no DID by
26
+ * construction — the verifier learns only what the disclosed indices say.
27
+ *
28
+ * The CALLER stores the challenge and must enforce single-use (mark it
29
+ * used once a presentation verifies) — the cryptographic ph binding kills
30
+ * cross-challenge replay, storage-side bookkeeping kills same-challenge
31
+ * re-submission.
32
+ */
33
+ export function createBbsChallenge(opts) {
34
+ if (!opts.domain)
35
+ throw new Error('domain must be non-empty');
36
+ if (!opts.credentialType)
37
+ throw new Error('credentialType must be non-empty');
38
+ const forbidden = opts.requiredIndices.filter((i) => ALWAYS_HIDDEN_KYC_INDICES.includes(i));
39
+ if (forbidden.length > 0) {
40
+ throw new Error(`requiredIndices ${forbidden.join(',')} are always-hidden fields ` +
41
+ `(subject_did/verification_id/document_hash) and can never be requested`);
42
+ }
43
+ if (opts.requiredIndices.some((i) => !Number.isInteger(i) || i < 0)) {
44
+ throw new Error('requiredIndices must be non-negative integers');
45
+ }
46
+ const now = new Date();
47
+ const ttl = opts.ttlSeconds ?? 300;
48
+ return {
49
+ id: randomUUID(),
50
+ domain: opts.domain,
51
+ credentialType: opts.credentialType,
52
+ requiredIndices: [...opts.requiredIndices],
53
+ nonce: randomBytes(32).toString('hex'),
54
+ issuedAt: now.toISOString(),
55
+ expiresAt: new Date(now.getTime() + ttl * 1_000).toISOString(),
56
+ };
57
+ }
19
58
  //# sourceMappingURL=challenge.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"challenge.js","sourceRoot":"","sources":["../src/challenge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAerD;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,UAAU,GAAG,GAAG;IAC3D,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAA;IACtB,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,UAAU,GAAG,KAAK,CAAC,CAAA;IAC9D,OAAO;QACL,EAAE,EAAE,UAAU,EAAE;QAChB,GAAG;QACH,KAAK,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;QACtC,QAAQ,EAAE,GAAG,CAAC,WAAW,EAAE;QAC3B,SAAS,EAAE,SAAS,CAAC,WAAW,EAAE;KACnC,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"challenge.js","sourceRoot":"","sources":["../src/challenge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAerD;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,UAAU,GAAG,GAAG;IAC3D,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAA;IACtB,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,UAAU,GAAG,KAAK,CAAC,CAAA;IAC9D,OAAO;QACL,EAAE,EAAE,UAAU,EAAE;QAChB,GAAG;QACH,KAAK,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;QACtC,QAAQ,EAAE,GAAG,CAAC,WAAW,EAAE;QAC3B,SAAS,EAAE,SAAS,CAAC,WAAW,EAAE;KACnC,CAAA;AACH,CAAC;AAED,8EAA8E;AAC9E,sEAAsE;AACtE,kDAAkD;AAClD,8EAA8E;AAE9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAA;AAuBzD;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAKlC;IACC,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;IAC7D,IAAI,CAAC,IAAI,CAAC,cAAc;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAA;IAC7E,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACjD,yBAA+C,CAAC,QAAQ,CAAC,CAAC,CAAC,CAC7D,CAAA;IACD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACb,mBAAmB,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,4BAA4B;YAChE,wEAAwE,CAC3E,CAAA;IACH,CAAC;IACD,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;IAClE,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAA;IACtB,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,GAAG,CAAA;IAClC,OAAO;QACL,EAAE,EAAE,UAAU,EAAE;QAChB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,cAAc,EAAE,IAAI,CAAC,cAAc;QACnC,eAAe,EAAE,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC;QAC1C,KAAK,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;QACtC,QAAQ,EAAE,GAAG,CAAC,WAAW,EAAE;QAC3B,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,WAAW,EAAE;KAC/D,CAAA;AACH,CAAC"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * DID-less selective-disclosure presentation envelope (privacy rebuild §5.3).
3
+ *
4
+ * A `BbsSelectiveDisclosurePresentation` is what a wallet sends a relying
5
+ * party: a randomized BBS+ proof over the issuer-signed credential,
6
+ * disclosing exactly the requested message indices. By construction it has
7
+ * NO `holder` field, no subject DID, no per-credential identifier — the
8
+ * only things a verifier learns are "a valid credential from this issuer's
9
+ * (type, epoch) cohort" plus the disclosed claim values.
10
+ *
11
+ * DELIBERATE OMISSION vs the design sketch: the envelope does NOT carry
12
+ * the BBS header. The verifier RECONSTRUCTS the header from its own
13
+ * trusted (issuerDid, credentialType, epoch) — a header taken from the
14
+ * envelope would let a credential of a different cohort (e.g. a lower KYC
15
+ * level) satisfy a check whose policy expects another, and invites
16
+ * third-party RP implementations to skip policy binding entirely.
17
+ *
18
+ * Browser-safe: the wallet builds envelopes client-side — no node imports.
19
+ */
20
+ /** Canonical KYC message order (frozen — mirrors verify's `buildKycMessageVector`). */
21
+ export declare const KYC_MESSAGE_FIELDS: readonly ["subject_did", "issuer_did", "verification_id", "verified_at", "kyc_level", "country", "document_type", "document_hash"];
22
+ /**
23
+ * Indices that must NEVER be disclosed (§5.2 disposition): the subject
24
+ * DID (the T2 handle), the per-credential verification id (the old
25
+ * header leak), and the per-document hash. Verifiers reject envelopes
26
+ * disclosing any of these even when the proof is cryptographically valid.
27
+ */
28
+ export declare const ALWAYS_HIDDEN_KYC_INDICES: readonly [0, 2, 7];
29
+ export declare const BBS_PRESENTATION_TYPE = "BbsSelectiveDisclosurePresentation";
30
+ export interface DisclosedMessage {
31
+ /** Zero-based index in the original signed vector. */
32
+ index: number;
33
+ /** Hex-encoded message bytes. */
34
+ message: string;
35
+ }
36
+ export interface BbsSelectiveDisclosurePresentation {
37
+ type: typeof BBS_PRESENTATION_TYPE;
38
+ /** Credential-format version marker. */
39
+ v: 'bbs-v2';
40
+ /** The challenge this presentation answers. */
41
+ challengeId: string;
42
+ /** Issuer key-rotation epoch (cohort label — selects the pubkey). */
43
+ epoch: number;
44
+ /** Hex-encoded randomized BBS+ proof. */
45
+ proof: string;
46
+ totalMessageCount: number;
47
+ disclosed: DisclosedMessage[];
48
+ /** Re-recognition (mechanism B) only — §5.4. Null in one-shot mode. */
49
+ pairwiseDid: string | null;
50
+ /** VP signed by the pairwise key — §5.4. Null in one-shot mode. */
51
+ pairwiseProof: Record<string, unknown> | null;
52
+ }
53
+ export interface BuildBbsPresentationInput {
54
+ challengeId: string;
55
+ epoch: number;
56
+ proofHex: string;
57
+ totalMessageCount: number;
58
+ disclosed: DisclosedMessage[];
59
+ pairwiseDid?: string | null;
60
+ pairwiseProof?: Record<string, unknown> | null;
61
+ }
62
+ /** Build (and validate) a presentation envelope — wallet side. */
63
+ export declare function buildBbsPresentation(input: BuildBbsPresentationInput): BbsSelectiveDisclosurePresentation;
64
+ /** Parse + strictly validate a serialized envelope — verifier side. */
65
+ export declare function parseBbsPresentation(json: string): BbsSelectiveDisclosurePresentation;
66
+ /**
67
+ * Decode disclosed messages to named KYC fields (utf8). Only disclosed
68
+ * indices appear; always-hidden fields can never appear in a valid
69
+ * envelope (the verifier rejects them).
70
+ */
71
+ export declare function decodeDisclosedKycFields(disclosed: DisclosedMessage[]): Partial<Record<(typeof KYC_MESSAGE_FIELDS)[number], string>>;
72
+ //# sourceMappingURL=envelope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,uFAAuF;AACvF,eAAO,MAAM,kBAAkB,oIASrB,CAAA;AAEV;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,oBAAqB,CAAA;AAE3D,eAAO,MAAM,qBAAqB,uCAAuC,CAAA;AAEzE,MAAM,WAAW,gBAAgB;IAC/B,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAA;IACb,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,kCAAkC;IACjD,IAAI,EAAE,OAAO,qBAAqB,CAAA;IAClC,wCAAwC;IACxC,CAAC,EAAE,QAAQ,CAAA;IACX,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAA;IACnB,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAA;IACb,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAA;IACb,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,EAAE,gBAAgB,EAAE,CAAA;IAC7B,uEAAuE;IACvE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,mEAAmE;IACnE,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;CAC9C;AAQD,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,EAAE,gBAAgB,EAAE,CAAA;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;CAC/C;AAED,kEAAkE;AAClE,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,yBAAyB,GAC/B,kCAAkC,CAcpC;AAED,uEAAuE;AACvE,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,kCAAkC,CAwBrF;AAmDD;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,gBAAgB,EAAE,GAC5B,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAa9D"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * DID-less selective-disclosure presentation envelope (privacy rebuild §5.3).
3
+ *
4
+ * A `BbsSelectiveDisclosurePresentation` is what a wallet sends a relying
5
+ * party: a randomized BBS+ proof over the issuer-signed credential,
6
+ * disclosing exactly the requested message indices. By construction it has
7
+ * NO `holder` field, no subject DID, no per-credential identifier — the
8
+ * only things a verifier learns are "a valid credential from this issuer's
9
+ * (type, epoch) cohort" plus the disclosed claim values.
10
+ *
11
+ * DELIBERATE OMISSION vs the design sketch: the envelope does NOT carry
12
+ * the BBS header. The verifier RECONSTRUCTS the header from its own
13
+ * trusted (issuerDid, credentialType, epoch) — a header taken from the
14
+ * envelope would let a credential of a different cohort (e.g. a lower KYC
15
+ * level) satisfy a check whose policy expects another, and invites
16
+ * third-party RP implementations to skip policy binding entirely.
17
+ *
18
+ * Browser-safe: the wallet builds envelopes client-side — no node imports.
19
+ */
20
+ /** Canonical KYC message order (frozen — mirrors verify's `buildKycMessageVector`). */
21
+ export const KYC_MESSAGE_FIELDS = [
22
+ 'subject_did',
23
+ 'issuer_did',
24
+ 'verification_id',
25
+ 'verified_at',
26
+ 'kyc_level',
27
+ 'country',
28
+ 'document_type',
29
+ 'document_hash',
30
+ ];
31
+ /**
32
+ * Indices that must NEVER be disclosed (§5.2 disposition): the subject
33
+ * DID (the T2 handle), the per-credential verification id (the old
34
+ * header leak), and the per-document hash. Verifiers reject envelopes
35
+ * disclosing any of these even when the proof is cryptographically valid.
36
+ */
37
+ export const ALWAYS_HIDDEN_KYC_INDICES = [0, 2, 7];
38
+ export const BBS_PRESENTATION_TYPE = 'BbsSelectiveDisclosurePresentation';
39
+ const HEX_RE = /^[0-9a-f]*$/i;
40
+ function isHex(s) {
41
+ return HEX_RE.test(s) && s.length % 2 === 0;
42
+ }
43
+ /** Build (and validate) a presentation envelope — wallet side. */
44
+ export function buildBbsPresentation(input) {
45
+ const envelope = {
46
+ type: BBS_PRESENTATION_TYPE,
47
+ v: 'bbs-v2',
48
+ challengeId: input.challengeId,
49
+ epoch: input.epoch,
50
+ proof: input.proofHex,
51
+ totalMessageCount: input.totalMessageCount,
52
+ disclosed: input.disclosed.map((d) => ({ index: d.index, message: d.message })),
53
+ pairwiseDid: input.pairwiseDid ?? null,
54
+ pairwiseProof: input.pairwiseProof ?? null,
55
+ };
56
+ assertEnvelopeShape(envelope);
57
+ return envelope;
58
+ }
59
+ /** Parse + strictly validate a serialized envelope — verifier side. */
60
+ export function parseBbsPresentation(json) {
61
+ let raw;
62
+ try {
63
+ raw = JSON.parse(json);
64
+ }
65
+ catch {
66
+ throw new Error('presentation is not valid JSON');
67
+ }
68
+ if (typeof raw !== 'object' || raw === null) {
69
+ throw new Error('presentation must be a JSON object');
70
+ }
71
+ const e = raw;
72
+ const envelope = {
73
+ type: e['type'],
74
+ v: e['v'],
75
+ challengeId: e['challengeId'],
76
+ epoch: e['epoch'],
77
+ proof: e['proof'],
78
+ totalMessageCount: e['totalMessageCount'],
79
+ disclosed: e['disclosed'],
80
+ pairwiseDid: (e['pairwiseDid'] ?? null),
81
+ pairwiseProof: (e['pairwiseProof'] ?? null),
82
+ };
83
+ assertEnvelopeShape(envelope);
84
+ return envelope;
85
+ }
86
+ function assertEnvelopeShape(e) {
87
+ if (e.type !== BBS_PRESENTATION_TYPE) {
88
+ throw new Error(`presentation type must be ${BBS_PRESENTATION_TYPE}`);
89
+ }
90
+ if (e.v !== 'bbs-v2')
91
+ throw new Error('unsupported presentation version');
92
+ if (typeof e.challengeId !== 'string' || e.challengeId.length === 0) {
93
+ throw new Error('challengeId must be a non-empty string');
94
+ }
95
+ if (!Number.isInteger(e.epoch) || e.epoch < 0) {
96
+ throw new Error('epoch must be a non-negative integer');
97
+ }
98
+ if (typeof e.proof !== 'string' || e.proof.length === 0 || !isHex(e.proof)) {
99
+ throw new Error('proof must be non-empty hex');
100
+ }
101
+ if (!Number.isInteger(e.totalMessageCount) ||
102
+ e.totalMessageCount < 1 ||
103
+ e.totalMessageCount > 64) {
104
+ throw new Error('totalMessageCount out of range');
105
+ }
106
+ if (!Array.isArray(e.disclosed))
107
+ throw new Error('disclosed must be an array');
108
+ const seen = new Set();
109
+ for (const d of e.disclosed) {
110
+ if (typeof d !== 'object' ||
111
+ d === null ||
112
+ !Number.isInteger(d.index) ||
113
+ d.index < 0 ||
114
+ d.index >= e.totalMessageCount ||
115
+ typeof d.message !== 'string' ||
116
+ !isHex(d.message)) {
117
+ throw new Error('disclosed entries must be {index within range, hex message}');
118
+ }
119
+ if (seen.has(d.index))
120
+ throw new Error(`duplicate disclosed index ${d.index}`);
121
+ seen.add(d.index);
122
+ }
123
+ if (e.pairwiseDid !== null && (typeof e.pairwiseDid !== 'string' || e.pairwiseDid.length === 0)) {
124
+ throw new Error('pairwiseDid must be null or a non-empty string');
125
+ }
126
+ if (e.pairwiseProof !== null && (typeof e.pairwiseProof !== 'object' || Array.isArray(e.pairwiseProof))) {
127
+ throw new Error('pairwiseProof must be null or an object');
128
+ }
129
+ if ((e.pairwiseDid === null) !== (e.pairwiseProof === null)) {
130
+ throw new Error('pairwiseDid and pairwiseProof must be provided together');
131
+ }
132
+ }
133
+ /**
134
+ * Decode disclosed messages to named KYC fields (utf8). Only disclosed
135
+ * indices appear; always-hidden fields can never appear in a valid
136
+ * envelope (the verifier rejects them).
137
+ */
138
+ export function decodeDisclosedKycFields(disclosed) {
139
+ const out = {};
140
+ const decoder = new TextDecoder();
141
+ for (const d of disclosed) {
142
+ const field = KYC_MESSAGE_FIELDS[d.index];
143
+ if (!field)
144
+ continue;
145
+ const bytes = new Uint8Array(d.message.length / 2);
146
+ for (let i = 0; i < bytes.length; i++) {
147
+ bytes[i] = parseInt(d.message.slice(i * 2, i * 2 + 2), 16);
148
+ }
149
+ out[field] = decoder.decode(bytes);
150
+ }
151
+ return out;
152
+ }
153
+ //# sourceMappingURL=envelope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.js","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,11 @@
1
- export { createChallenge } from './challenge.js';
2
- export type { Challenge } from './challenge.js';
3
- export { verifyPresentation } from './verify.js';
4
- export type { VerifiablePresentation, PresentationVerificationResult } from './verify.js';
1
+ export { createChallenge, createBbsChallenge } from './challenge.js';
2
+ export type { Challenge, BbsChallenge } from './challenge.js';
3
+ export { verifyPresentation, verifyBbsPresentation } from './verify.js';
4
+ export type { VerifiablePresentation, PresentationVerificationResult, BbsVerifyOptions, BbsPresentationVerificationResult, } from './verify.js';
5
+ export { buildBbsPresentation, parseBbsPresentation, decodeDisclosedKycFields, KYC_MESSAGE_FIELDS, ALWAYS_HIDDEN_KYC_INDICES, BBS_PRESENTATION_TYPE, } from './envelope.js';
6
+ export type { BbsSelectiveDisclosurePresentation, DisclosedMessage, BuildBbsPresentationInput, } from './envelope.js';
7
+ export { buildPairwiseAttachment, buildPairwiseDid, pairwiseAddressFromPublicKey, asPairwiseAttachment, } from './pairwise.js';
8
+ export type { PairwiseAttachment } from './pairwise.js';
9
+ export { createIssuerKeyResolver } from './rp.js';
10
+ export type { IssuerKeyResolverOptions } from './rp.js';
5
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChD,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAChD,YAAY,EAAE,sBAAsB,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACpE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7D,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACvE,YAAY,EACV,sBAAsB,EACtB,8BAA8B,EAC9B,gBAAgB,EAChB,iCAAiC,GAClC,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,kBAAkB,EAClB,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,eAAe,CAAA;AACtB,YAAY,EACV,kCAAkC,EAClC,gBAAgB,EAChB,yBAAyB,GAC1B,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,4BAA4B,EAC5B,oBAAoB,GACrB,MAAM,eAAe,CAAA;AACtB,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA;AACjD,YAAY,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAA"}
package/dist/index.js CHANGED
@@ -1,3 +1,6 @@
1
- export { createChallenge } from './challenge.js';
2
- export { verifyPresentation } from './verify.js';
1
+ export { createChallenge, createBbsChallenge } from './challenge.js';
2
+ export { verifyPresentation, verifyBbsPresentation } from './verify.js';
3
+ export { buildBbsPresentation, parseBbsPresentation, decodeDisclosedKycFields, KYC_MESSAGE_FIELDS, ALWAYS_HIDDEN_KYC_INDICES, BBS_PRESENTATION_TYPE, } from './envelope.js';
4
+ export { buildPairwiseAttachment, buildPairwiseDid, pairwiseAddressFromPublicKey, asPairwiseAttachment, } from './pairwise.js';
5
+ export { createIssuerKeyResolver } from './rp.js';
3
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAEhD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAEpE,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAOvE,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,kBAAkB,EAClB,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,eAAe,CAAA;AAMtB,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,4BAA4B,EAC5B,oBAAoB,GACrB,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA"}
@@ -0,0 +1,36 @@
1
+ import type { VerifiablePresentation } from './verify.js';
2
+ /** The self-certifying attachment carried in the envelope's `pairwiseProof`. */
3
+ export interface PairwiseAttachment {
4
+ /** Hex pairwise public key — the verifier binds this to the pairwise DID. */
5
+ publicKeyHex: string;
6
+ /** Standard W3C VP signed by the pairwise key, holder = the pairwise DID. */
7
+ vp: VerifiablePresentation;
8
+ }
9
+ declare function hexToBytes(hex: string): Uint8Array;
10
+ /** `addr = base58(BLAKE3(pubkey)[0..20])` — mirrors the SDK `addressFromPublicKey`. */
11
+ export declare function pairwiseAddressFromPublicKey(publicKey: Uint8Array): string;
12
+ /** `did:solidus:{network}:{addr}` — the self-certifying pairwise DID (never on-chain). */
13
+ export declare function buildPairwiseDid(network: string, publicKey: Uint8Array): string;
14
+ /**
15
+ * Build the pairwise VP attachment. Takes the ALREADY-DERIVED pairwise key
16
+ * (the wallet derives it via `derivePairwiseKeyFromSeed` under the verifier's
17
+ * authenticated id) plus the challenge nonce it must sign over. The produced
18
+ * VP is byte-compatible with the shipped DID-bound `verifyPresentation`.
19
+ */
20
+ export declare function buildPairwiseAttachment(opts: {
21
+ /** 32-byte pairwise private key, hex. */
22
+ pairwisePrivateKeyHex: string;
23
+ /** Verifier's network (goes into the DID). */
24
+ network: string;
25
+ /** The challenge nonce — the VP's `proof.challenge`. */
26
+ nonce: string;
27
+ /** ISO timestamp; defaults to now. */
28
+ created?: string;
29
+ }): Promise<{
30
+ pairwiseDid: string;
31
+ attachment: PairwiseAttachment;
32
+ }>;
33
+ /** Narrow an unknown envelope `pairwiseProof` to a `PairwiseAttachment`. */
34
+ export declare function asPairwiseAttachment(value: unknown): PairwiseAttachment | null;
35
+ export { hexToBytes as _pairwiseHexToBytes };
36
+ //# sourceMappingURL=pairwise.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pairwise.d.ts","sourceRoot":"","sources":["../src/pairwise.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAEzD,gFAAgF;AAChF,MAAM,WAAW,kBAAkB;IACjC,6EAA6E;IAC7E,YAAY,EAAE,MAAM,CAAA;IACpB,6EAA6E;IAC7E,EAAE,EAAE,sBAAsB,CAAA;CAC3B;AAED,iBAAS,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAI3C;AAiBD,uFAAuF;AACvF,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,UAAU,GAAG,MAAM,CAE1E;AAED,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,MAAM,CAG/E;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAAC,IAAI,EAAE;IAClD,yCAAyC;IACzC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAA;IACf,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAA;IACb,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,GAAG,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,kBAAkB,CAAA;CAAE,CAAC,CAgCnE;AAED,4EAA4E;AAC5E,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,GAAG,IAAI,CAU9E;AAED,OAAO,EAAE,UAAU,IAAI,mBAAmB,EAAE,CAAA"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Pairwise-DID re-recognition (privacy rebuild §5.4 — mechanism B).
3
+ *
4
+ * "Remember me at THIS verifier" without two verifiers colluding. Beside the
5
+ * one-shot SD proof, the wallet attaches a standard W3C VP signed by a
6
+ * per-verifier pairwise key (derived via `derivePairwiseKeyFromSeed`, §5.1).
7
+ * The pairwise DID is a SELF-CERTIFYING string — `did:solidus:{network}:{addr}`
8
+ * where `addr = base58(BLAKE3(pubkey)[0..20])` — and is NEVER registered
9
+ * on-chain (an on-chain anchor would itself be a correlation handle, BD-7).
10
+ *
11
+ * The verifier recognizes a returning user because the same (seed, verifier)
12
+ * always yields the same pairwise DID; two verifiers get independent HKDF
13
+ * outputs, so they cannot link the same person.
14
+ *
15
+ * Authenticity caveat (§5.4): the WALLET must derive the pairwise key under
16
+ * the verifier's OWN authenticated identity (its TLS origin = the challenge
17
+ * `domain`), never a `verifier_id` copied blindly from an untrusted channel —
18
+ * else verifier A can request B's pseudonym and collude. This module verifies
19
+ * the binding + signature; the wallet owns the "derive under the right id" step.
20
+ *
21
+ * Weakness (surfaced, not buried): mechanism B proves two things SIDE BY SIDE,
22
+ * not jointly — "holds a valid Solidus KYC credential" (the b.1 proof) and
23
+ * "controls this pairwise key" (the VP) — nothing cryptographically binds them
24
+ * to the SAME seed. Assurance tops out at "a returning controller of this key
25
+ * who can also show some valid Solidus credential," fine for cooperative
26
+ * re-recognition. Access-control-grade "provably the same KYC holder" needs
27
+ * mechanism C — swapped in later behind the same verifier_id→handle contract.
28
+ */
29
+ import * as ed from '@noble/ed25519';
30
+ import { blake3 } from '@noble/hashes/blake3';
31
+ import bs58 from 'bs58';
32
+ function hexToBytes(hex) {
33
+ const bytes = new Uint8Array(hex.length / 2);
34
+ for (let i = 0; i < bytes.length; i++)
35
+ bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
36
+ return bytes;
37
+ }
38
+ function bytesToHex(bytes) {
39
+ let out = '';
40
+ for (let i = 0; i < bytes.length; i++)
41
+ out += bytes[i].toString(16).padStart(2, '0');
42
+ return out;
43
+ }
44
+ function base64url(bytes) {
45
+ // Browser-safe base64url (no node Buffer) so this module can move into the
46
+ // wallet later without change.
47
+ let bin = '';
48
+ for (let i = 0; i < bytes.length; i++)
49
+ bin += String.fromCharCode(bytes[i]);
50
+ const b64 = typeof btoa === 'function' ? btoa(bin) : Buffer.from(bytes).toString('base64');
51
+ return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
52
+ }
53
+ /** `addr = base58(BLAKE3(pubkey)[0..20])` — mirrors the SDK `addressFromPublicKey`. */
54
+ export function pairwiseAddressFromPublicKey(publicKey) {
55
+ return bs58.encode(blake3(publicKey).slice(0, 20));
56
+ }
57
+ /** `did:solidus:{network}:{addr}` — the self-certifying pairwise DID (never on-chain). */
58
+ export function buildPairwiseDid(network, publicKey) {
59
+ if (!network)
60
+ throw new Error('network must be non-empty');
61
+ return `did:solidus:${network}:${pairwiseAddressFromPublicKey(publicKey)}`;
62
+ }
63
+ /**
64
+ * Build the pairwise VP attachment. Takes the ALREADY-DERIVED pairwise key
65
+ * (the wallet derives it via `derivePairwiseKeyFromSeed` under the verifier's
66
+ * authenticated id) plus the challenge nonce it must sign over. The produced
67
+ * VP is byte-compatible with the shipped DID-bound `verifyPresentation`.
68
+ */
69
+ export async function buildPairwiseAttachment(opts) {
70
+ const priv = hexToBytes(opts.pairwisePrivateKeyHex);
71
+ const pub = await ed.getPublicKeyAsync(priv);
72
+ const pairwiseDid = buildPairwiseDid(opts.network, pub);
73
+ // Presentation (proof added after signing) — key order MUST match what
74
+ // `verifyPresentation` reconstructs (it strips `proof` and stringifies).
75
+ const presentation = {
76
+ '@context': ['https://www.w3.org/2018/credentials/v1'],
77
+ type: ['VerifiablePresentation'],
78
+ holder: pairwiseDid,
79
+ };
80
+ const header = { alg: 'EdDSA', b64: false, crit: ['b64'] };
81
+ const headerB64 = base64url(new TextEncoder().encode(JSON.stringify(header)));
82
+ const payloadB64 = base64url(new TextEncoder().encode(JSON.stringify(presentation)));
83
+ const signingInput = `${headerB64}.${payloadB64}`;
84
+ const signature = await ed.signAsync(new TextEncoder().encode(signingInput), priv);
85
+ const jws = `${headerB64}..${base64url(signature)}`;
86
+ const vp = {
87
+ ...presentation,
88
+ proof: {
89
+ type: 'Ed25519Signature2020',
90
+ created: opts.created ?? new Date().toISOString(),
91
+ challenge: opts.nonce,
92
+ proofPurpose: 'authentication',
93
+ verificationMethod: `${pairwiseDid}#key-0`,
94
+ jws,
95
+ },
96
+ };
97
+ return { pairwiseDid, attachment: { publicKeyHex: bytesToHex(pub), vp } };
98
+ }
99
+ /** Narrow an unknown envelope `pairwiseProof` to a `PairwiseAttachment`. */
100
+ export function asPairwiseAttachment(value) {
101
+ if (typeof value !== 'object' || value === null)
102
+ return null;
103
+ const a = value;
104
+ if (typeof a['publicKeyHex'] !== 'string')
105
+ return null;
106
+ if (typeof a['vp'] !== 'object' || a['vp'] === null)
107
+ return null;
108
+ const vp = a['vp'];
109
+ if (typeof vp['holder'] !== 'string' || typeof vp['proof'] !== 'object' || vp['proof'] === null) {
110
+ return null;
111
+ }
112
+ return value;
113
+ }
114
+ export { hexToBytes as _pairwiseHexToBytes };
115
+ //# sourceMappingURL=pairwise.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pairwise.js","sourceRoot":"","sources":["../src/pairwise.ts"],"names":[],"mappings":"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"}
package/dist/rp.d.ts ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Relying-party surface (privacy rebuild §5.7).
3
+ *
4
+ * The verifier primitives — `createBbsChallenge` (issue a DID-less challenge)
5
+ * and `verifyBbsPresentation` (stateless verify) — are the RP SDK. This module
6
+ * adds the batteries a third-party verifier would otherwise hand-roll: an
7
+ * issuer-key resolver that fetches `/.well-known/solidus-bbs-issuer.json`,
8
+ * caches the current + grace epoch pubkeys, and returns exactly the
9
+ * `resolveIssuerKey(epoch)` function `verifyBbsPresentation` expects.
10
+ *
11
+ * FAIL-CLOSED by design: an unknown/lapsed epoch, an unreachable issuer, a
12
+ * non-200, or a malformed doc all resolve to `null` — never a key — so the
13
+ * verify path rejects rather than accepting on error. That is also the
14
+ * bounded-lifetime enforcement point (a lapsed epoch is simply absent from the
15
+ * doc → null → reject; §5.5).
16
+ *
17
+ * Browser-safe (fetch only); works in an RP backend or a browser verifier.
18
+ */
19
+ export interface IssuerKeyResolverOptions {
20
+ /** The issuer's base URL, e.g. `https://verify.solidus.network`. */
21
+ issuerBaseUrl: string;
22
+ /** Injectable for tests / custom transports. */
23
+ fetchImpl?: typeof fetch;
24
+ /** How long to cache the fetched doc. Default 5 min (matches its Cache-Control). */
25
+ cacheTtlMs?: number;
26
+ /** Clock injection for tests. */
27
+ now?: () => number;
28
+ }
29
+ /**
30
+ * Build a caching, fail-closed `resolveIssuerKey(epoch) => Promise<string|null>`
31
+ * suitable to pass straight into `verifyBbsPresentation`'s options.
32
+ */
33
+ export declare function createIssuerKeyResolver(opts: IssuerKeyResolverOptions): (epoch: number) => Promise<string | null>;
34
+ //# sourceMappingURL=rp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rp.d.ts","sourceRoot":"","sources":["../src/rp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAcH,MAAM,WAAW,wBAAwB;IACvC,oEAAoE;IACpE,aAAa,EAAE,MAAM,CAAA;IACrB,gDAAgD;IAChD,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACxB,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,wBAAwB,GAC7B,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmC3C"}
package/dist/rp.js ADDED
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Relying-party surface (privacy rebuild §5.7).
3
+ *
4
+ * The verifier primitives — `createBbsChallenge` (issue a DID-less challenge)
5
+ * and `verifyBbsPresentation` (stateless verify) — are the RP SDK. This module
6
+ * adds the batteries a third-party verifier would otherwise hand-roll: an
7
+ * issuer-key resolver that fetches `/.well-known/solidus-bbs-issuer.json`,
8
+ * caches the current + grace epoch pubkeys, and returns exactly the
9
+ * `resolveIssuerKey(epoch)` function `verifyBbsPresentation` expects.
10
+ *
11
+ * FAIL-CLOSED by design: an unknown/lapsed epoch, an unreachable issuer, a
12
+ * non-200, or a malformed doc all resolve to `null` — never a key — so the
13
+ * verify path rejects rather than accepting on error. That is also the
14
+ * bounded-lifetime enforcement point (a lapsed epoch is simply absent from the
15
+ * doc → null → reject; §5.5).
16
+ *
17
+ * Browser-safe (fetch only); works in an RP backend or a browser verifier.
18
+ */
19
+ /**
20
+ * Build a caching, fail-closed `resolveIssuerKey(epoch) => Promise<string|null>`
21
+ * suitable to pass straight into `verifyBbsPresentation`'s options.
22
+ */
23
+ export function createIssuerKeyResolver(opts) {
24
+ const doFetch = opts.fetchImpl ?? globalThis.fetch;
25
+ const now = opts.now ?? (() => Date.now());
26
+ const ttl = opts.cacheTtlMs ?? 300_000;
27
+ const url = `${opts.issuerBaseUrl.replace(/\/$/, '')}/.well-known/solidus-bbs-issuer.json`;
28
+ let cache = null;
29
+ async function loadDoc() {
30
+ if (cache && now() - cache.fetchedAt < ttl)
31
+ return cache.byEpoch;
32
+ const byEpoch = new Map();
33
+ try {
34
+ const res = await doFetch(url, { method: 'GET' });
35
+ if (res.ok) {
36
+ const doc = (await res.json());
37
+ if (doc?.current && typeof doc.current.pubkeyHex === 'string') {
38
+ byEpoch.set(doc.current.epoch, doc.current.pubkeyHex);
39
+ for (const g of doc.grace ?? []) {
40
+ if (typeof g?.pubkeyHex === 'string')
41
+ byEpoch.set(g.epoch, g.pubkeyHex);
42
+ }
43
+ }
44
+ }
45
+ }
46
+ catch {
47
+ // Fail-closed: leave byEpoch empty → every resolve returns null → reject.
48
+ }
49
+ // Cache even an empty result briefly so a hard-down issuer doesn't get
50
+ // hammered on every presentation; the short TTL bounds staleness.
51
+ cache = { byEpoch, fetchedAt: now() };
52
+ return byEpoch;
53
+ }
54
+ return async function resolveIssuerKey(epoch) {
55
+ const byEpoch = await loadDoc();
56
+ return byEpoch.get(epoch) ?? null;
57
+ };
58
+ }
59
+ //# sourceMappingURL=rp.js.map
package/dist/rp.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rp.js","sourceRoot":"","sources":["../src/rp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAyBH;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,IAA8B;IAE9B,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,IAAK,UAAU,CAAC,KAAsB,CAAA;IACpE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;IAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,OAAO,CAAA;IACtC,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,sCAAsC,CAAA;IAE1F,IAAI,KAAK,GAA+D,IAAI,CAAA;IAE5E,KAAK,UAAU,OAAO;QACpB,IAAI,KAAK,IAAI,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,GAAG,GAAG;YAAE,OAAO,KAAK,CAAC,OAAO,CAAA;QAChE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAA;QACzC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;YACjD,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBACX,MAAM,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAsB,CAAA;gBACnD,IAAI,GAAG,EAAE,OAAO,IAAI,OAAO,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;oBAC9D,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;oBACrD,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;wBAChC,IAAI,OAAO,CAAC,EAAE,SAAS,KAAK,QAAQ;4BAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,SAAS,CAAC,CAAA;oBACzE,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,0EAA0E;QAC5E,CAAC;QACD,uEAAuE;QACvE,kEAAkE;QAClE,KAAK,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,CAAA;QACrC,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,OAAO,KAAK,UAAU,gBAAgB,CAAC,KAAa;QAClD,MAAM,OAAO,GAAG,MAAM,OAAO,EAAE,CAAA;QAC/B,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAA;IACnC,CAAC,CAAA;AACH,CAAC"}
package/dist/verify.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import type { Challenge } from './challenge.js';
1
+ import type { Challenge, BbsChallenge } from './challenge.js';
2
+ import { type BbsSelectiveDisclosurePresentation } from './envelope.js';
2
3
  export interface VerifiablePresentation {
3
4
  '@context': string[];
4
5
  /** Must include 'VerifiablePresentation' */
@@ -42,4 +43,78 @@ export interface PresentationVerificationResult {
42
43
  * @param getPublicKey - Async resolver: given a verificationMethod ID, return the Ed25519 public key (32 bytes)
43
44
  */
44
45
  export declare function verifyPresentation(challenge: Challenge, presentation: VerifiablePresentation, getPublicKey: (verificationMethodId: string) => Promise<Uint8Array>): Promise<PresentationVerificationResult>;
46
+ export interface BbsVerifyOptions {
47
+ /** The trusted issuer DID (from the verifier's own policy, never the envelope). */
48
+ issuerDid: string;
49
+ /**
50
+ * Resolve the issuer's BBS pubkey (hex) for an epoch — typically from
51
+ * `/.well-known/solidus-bbs-issuer.json` (current + grace), cached.
52
+ * Return null for unknown/lapsed epochs.
53
+ */
54
+ resolveIssuerKey: (epoch: number) => Promise<string | null>;
55
+ /**
56
+ * Whether this challenge was already answered (storage-side single-use
57
+ * bookkeeping — the caller tracks it; this library only enforces it).
58
+ */
59
+ used?: boolean;
60
+ /**
61
+ * The verifier's network (e.g. 'testnet'). REQUIRED when the presentation
62
+ * carries a pairwise attachment — the pairwise DID binds to it. A pairwise
63
+ * attachment presented without a configured network fails closed.
64
+ */
65
+ network?: string;
66
+ /** Clock injection for tests. */
67
+ now?: () => Date;
68
+ }
69
+ export interface BbsPresentationVerificationResult {
70
+ valid: boolean;
71
+ error?: string;
72
+ /**
73
+ * DID-less by construction for the one-shot proof: no holder check of any
74
+ * kind. A presentation proves "a valid credential from the trusted issuer's
75
+ * (type, epoch) cohort, disclosing exactly these claims" — never who.
76
+ *
77
+ * The pairwise checks run ONLY when a re-recognition attachment is present
78
+ * (§5.4). They verify the self-certifying pairwise DID + its VP signature;
79
+ * they still reveal nothing that links the user across verifiers.
80
+ */
81
+ checks: {
82
+ notExpired: boolean;
83
+ notUsed: boolean;
84
+ challengeIdMatches: boolean;
85
+ noForbiddenDisclosure: boolean;
86
+ requiredDisclosed: boolean;
87
+ epochKeyResolved: boolean;
88
+ proofValid: boolean;
89
+ /** Present only when a pairwise attachment is included. */
90
+ pairwiseBindingValid?: boolean;
91
+ pairwiseSignatureValid?: boolean;
92
+ };
93
+ /**
94
+ * The verified pairwise DID (re-recognition handle) when the presentation
95
+ * carried a valid pairwise attachment. The verifier stores/matches this
96
+ * keyed by its own verifier id — the seam mechanism C swaps into later
97
+ * without the RP re-integrating.
98
+ */
99
+ pairwiseDid?: string;
100
+ }
101
+ /**
102
+ * Verify a DID-less selective-disclosure presentation against a challenge.
103
+ *
104
+ * Checks (fail-fast):
105
+ * 1. challenge not expired, not already used
106
+ * 2. envelope answers THIS challenge
107
+ * 3. no always-hidden index is disclosed (subject_did / verification_id /
108
+ * document_hash) — enforced even when the proof itself is valid
109
+ * 4. every required index is disclosed
110
+ * 5. the issuer key for the envelope's epoch resolves (current or grace)
111
+ * 6. the BBS proof verifies under the RECONSTRUCTED header
112
+ * (issuerDid + challenge.credentialType + envelope.epoch — never a
113
+ * header taken from the envelope) and the ph recomputed from the
114
+ * verifier's own domain + stored nonce
115
+ *
116
+ * Uses ONLY the stateless issuer-key check — never a per-credential
117
+ * chain lookup (`verifyCredentialProof` leaks subject_did; BD-5).
118
+ */
119
+ export declare function verifyBbsPresentation(challenge: BbsChallenge, presentation: BbsSelectiveDisclosurePresentation, opts: BbsVerifyOptions): Promise<BbsPresentationVerificationResult>;
45
120
  //# sourceMappingURL=verify.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE/C,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,4CAA4C;IAC5C,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,oBAAoB,CAAC,EAAE,OAAO,EAAE,GAAG,SAAS,CAAA;IAC5C,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAA;QACZ,OAAO,EAAE,MAAM,CAAA;QACf,iCAAiC;QACjC,SAAS,EAAE,MAAM,CAAA;QACjB,YAAY,EAAE,MAAM,CAAA;QACpB,0CAA0C;QAC1C,kBAAkB,EAAE,MAAM,CAAA;QAC1B,4DAA4D;QAC5D,GAAG,EAAE,MAAM,CAAA;KACZ,CAAA;CACF;AAED,MAAM,WAAW,8BAA8B;IAC7C,KAAK,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE;QACN,UAAU,EAAE,OAAO,CAAA;QACnB,aAAa,EAAE,OAAO,CAAA;QACtB,YAAY,EAAE,OAAO,CAAA;QACrB,cAAc,EAAE,OAAO,CAAA;KACxB,CAAA;CACF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,sBAAsB,EACpC,YAAY,EAAE,CAAC,oBAAoB,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,GAClE,OAAO,CAAC,8BAA8B,CAAC,CA8DzC"}
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7D,OAAO,EAEL,KAAK,kCAAkC,EACxC,MAAM,eAAe,CAAA;AAGtB,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,4CAA4C;IAC5C,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,oBAAoB,CAAC,EAAE,OAAO,EAAE,GAAG,SAAS,CAAA;IAC5C,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAA;QACZ,OAAO,EAAE,MAAM,CAAA;QACf,iCAAiC;QACjC,SAAS,EAAE,MAAM,CAAA;QACjB,YAAY,EAAE,MAAM,CAAA;QACpB,0CAA0C;QAC1C,kBAAkB,EAAE,MAAM,CAAA;QAC1B,4DAA4D;QAC5D,GAAG,EAAE,MAAM,CAAA;KACZ,CAAA;CACF;AAED,MAAM,WAAW,8BAA8B;IAC7C,KAAK,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE;QACN,UAAU,EAAE,OAAO,CAAA;QACnB,aAAa,EAAE,OAAO,CAAA;QACtB,YAAY,EAAE,OAAO,CAAA;QACrB,cAAc,EAAE,OAAO,CAAA;KACxB,CAAA;CACF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,sBAAsB,EACpC,YAAY,EAAE,CAAC,oBAAoB,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,GAClE,OAAO,CAAC,8BAA8B,CAAC,CA8DzC;AAOD,MAAM,WAAW,gBAAgB;IAC/B,mFAAmF;IACnF,SAAS,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAC3D;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;IACd;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;CACjB;AAED,MAAM,WAAW,iCAAiC;IAChD,KAAK,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;;;;;OAQG;IACH,MAAM,EAAE;QACN,UAAU,EAAE,OAAO,CAAA;QACnB,OAAO,EAAE,OAAO,CAAA;QAChB,kBAAkB,EAAE,OAAO,CAAA;QAC3B,qBAAqB,EAAE,OAAO,CAAA;QAC9B,iBAAiB,EAAE,OAAO,CAAA;QAC1B,gBAAgB,EAAE,OAAO,CAAA;QACzB,UAAU,EAAE,OAAO,CAAA;QACnB,2DAA2D;QAC3D,oBAAoB,CAAC,EAAE,OAAO,CAAA;QAC9B,sBAAsB,CAAC,EAAE,OAAO,CAAA;KACjC,CAAA;IACD;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAUD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,YAAY,EACvB,YAAY,EAAE,kCAAkC,EAChD,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,iCAAiC,CAAC,CA4H5C"}
package/dist/verify.js CHANGED
@@ -1,4 +1,7 @@
1
1
  import * as ed from '@noble/ed25519';
2
+ import { BbsProof, BbsPublicKey, buildV2Header, derivePresentationHeader } from '@solidus-network/bbs';
3
+ import { ALWAYS_HIDDEN_KYC_INDICES, } from './envelope.js';
4
+ import { asPairwiseAttachment, buildPairwiseDid } from './pairwise.js';
2
5
  /**
3
6
  * Verify a W3C Verifiable Presentation against a challenge.
4
7
  *
@@ -60,4 +63,138 @@ export async function verifyPresentation(challenge, presentation, getPublicKey)
60
63
  }
61
64
  return { valid: true, checks };
62
65
  }
66
+ function hexToBytes(hex) {
67
+ const bytes = new Uint8Array(hex.length / 2);
68
+ for (let i = 0; i < bytes.length; i++) {
69
+ bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
70
+ }
71
+ return bytes;
72
+ }
73
+ /**
74
+ * Verify a DID-less selective-disclosure presentation against a challenge.
75
+ *
76
+ * Checks (fail-fast):
77
+ * 1. challenge not expired, not already used
78
+ * 2. envelope answers THIS challenge
79
+ * 3. no always-hidden index is disclosed (subject_did / verification_id /
80
+ * document_hash) — enforced even when the proof itself is valid
81
+ * 4. every required index is disclosed
82
+ * 5. the issuer key for the envelope's epoch resolves (current or grace)
83
+ * 6. the BBS proof verifies under the RECONSTRUCTED header
84
+ * (issuerDid + challenge.credentialType + envelope.epoch — never a
85
+ * header taken from the envelope) and the ph recomputed from the
86
+ * verifier's own domain + stored nonce
87
+ *
88
+ * Uses ONLY the stateless issuer-key check — never a per-credential
89
+ * chain lookup (`verifyCredentialProof` leaks subject_did; BD-5).
90
+ */
91
+ export async function verifyBbsPresentation(challenge, presentation, opts) {
92
+ const checks = {
93
+ notExpired: false,
94
+ notUsed: false,
95
+ challengeIdMatches: false,
96
+ noForbiddenDisclosure: false,
97
+ requiredDisclosed: false,
98
+ epochKeyResolved: false,
99
+ proofValid: false,
100
+ };
101
+ const now = opts.now?.() ?? new Date();
102
+ checks.notExpired = now < new Date(challenge.expiresAt);
103
+ if (!checks.notExpired) {
104
+ return { valid: false, error: 'Challenge expired', checks };
105
+ }
106
+ checks.notUsed = opts.used !== true;
107
+ if (!checks.notUsed) {
108
+ return { valid: false, error: 'Challenge already used', checks };
109
+ }
110
+ checks.challengeIdMatches = presentation.challengeId === challenge.id;
111
+ if (!checks.challengeIdMatches) {
112
+ return { valid: false, error: 'Presentation answers a different challenge', checks };
113
+ }
114
+ const disclosedIndices = presentation.disclosed.map((d) => d.index);
115
+ checks.noForbiddenDisclosure = !disclosedIndices.some((i) => ALWAYS_HIDDEN_KYC_INDICES.includes(i));
116
+ if (!checks.noForbiddenDisclosure) {
117
+ return {
118
+ valid: false,
119
+ error: 'Presentation discloses an always-hidden field',
120
+ checks,
121
+ };
122
+ }
123
+ checks.requiredDisclosed = challenge.requiredIndices.every((i) => disclosedIndices.includes(i));
124
+ if (!checks.requiredDisclosed) {
125
+ return { valid: false, error: 'A required claim was not disclosed', checks };
126
+ }
127
+ const issuerKeyHex = await opts.resolveIssuerKey(presentation.epoch);
128
+ checks.epochKeyResolved = typeof issuerKeyHex === 'string' && issuerKeyHex.length === 192;
129
+ if (!checks.epochKeyResolved || !issuerKeyHex) {
130
+ return { valid: false, error: 'No issuer key for this epoch (unknown or lapsed)', checks };
131
+ }
132
+ try {
133
+ // Reconstruct — never trust — the header and the presentation header.
134
+ const header = buildV2Header(opts.issuerDid, challenge.credentialType, presentation.epoch);
135
+ const ph = derivePresentationHeader(challenge.domain, hexToBytes(challenge.nonce));
136
+ const sorted = [...presentation.disclosed].sort((a, b) => a.index - b.index);
137
+ checks.proofValid = await BbsProof.fromHex(presentation.proof).verify({
138
+ pk: BbsPublicKey.fromHex(issuerKeyHex),
139
+ header,
140
+ presentationHeader: ph,
141
+ disclosedIndices: sorted.map((d) => d.index),
142
+ disclosedMessages: sorted.map((d) => hexToBytes(d.message)),
143
+ });
144
+ }
145
+ catch {
146
+ checks.proofValid = false;
147
+ }
148
+ if (!checks.proofValid) {
149
+ return { valid: false, error: 'Proof verification failed', checks };
150
+ }
151
+ // ---- Re-recognition (mechanism B) — only when a pairwise attachment rides
152
+ // the envelope. The one-shot proof above already passed; this adds the
153
+ // "same returning user at this verifier" binding without any on-chain
154
+ // anchor and without leaking a cross-verifier handle.
155
+ if (presentation.pairwiseDid !== null) {
156
+ checks.pairwiseBindingValid = false;
157
+ checks.pairwiseSignatureValid = false;
158
+ if (!opts.network) {
159
+ return { valid: false, error: 'Pairwise attachment requires a configured verifier network', checks };
160
+ }
161
+ const attachment = asPairwiseAttachment(presentation.pairwiseProof);
162
+ if (!attachment) {
163
+ return { valid: false, error: 'Malformed pairwise attachment', checks };
164
+ }
165
+ // 1. Binding: the claimed pairwise DID must be the self-certifying DID of
166
+ // the attached public key (under the verifier's own network), and the
167
+ // VP's holder must equal it. A stolen/forged DID fails here.
168
+ let pubkey;
169
+ try {
170
+ pubkey = hexToBytes(attachment.publicKeyHex);
171
+ }
172
+ catch {
173
+ return { valid: false, error: 'Pairwise public key is not valid hex', checks };
174
+ }
175
+ const recomputedDid = buildPairwiseDid(opts.network, pubkey);
176
+ checks.pairwiseBindingValid =
177
+ recomputedDid === presentation.pairwiseDid && attachment.vp.holder === presentation.pairwiseDid;
178
+ if (!checks.pairwiseBindingValid) {
179
+ return { valid: false, error: 'Pairwise DID does not bind to its public key', checks };
180
+ }
181
+ // 2. Signature: reuse the shipped DID-bound `verifyPresentation` verbatim,
182
+ // resolving the self-certified key. holderMatches + nonceMatches +
183
+ // signatureValid all run inside it.
184
+ const pairwiseChallenge = {
185
+ id: challenge.id,
186
+ did: presentation.pairwiseDid,
187
+ nonce: challenge.nonce,
188
+ issuedAt: challenge.issuedAt,
189
+ expiresAt: challenge.expiresAt,
190
+ };
191
+ const vpResult = await verifyPresentation(pairwiseChallenge, attachment.vp, async () => pubkey);
192
+ checks.pairwiseSignatureValid = vpResult.valid;
193
+ if (!checks.pairwiseSignatureValid) {
194
+ return { valid: false, error: `Pairwise VP invalid: ${vpResult.error ?? 'signature'}`, checks };
195
+ }
196
+ return { valid: true, checks, pairwiseDid: presentation.pairwiseDid };
197
+ }
198
+ return { valid: true, checks };
199
+ }
63
200
  //# sourceMappingURL=verify.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"verify.js","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAkCpC;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,SAAoB,EACpB,YAAoC,EACpC,YAAmE;IAEnE,MAAM,MAAM,GAAG;QACb,UAAU,EAAE,KAAK;QACjB,aAAa,EAAE,KAAK;QACpB,YAAY,EAAE,KAAK;QACnB,cAAc,EAAE,KAAK;KACtB,CAAA;IAED,iBAAiB;IACjB,MAAM,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;IAC9D,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACvB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,CAAA;IAC7D,CAAC;IAED,oBAAoB;IACpB,MAAM,CAAC,aAAa,GAAG,YAAY,CAAC,MAAM,KAAK,SAAS,CAAC,GAAG,CAAA;IAC5D,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;QAC1B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,yCAAyC,EAAE,MAAM,EAAE,CAAA;IACnF,CAAC;IAED,mBAAmB;IACnB,MAAM,CAAC,YAAY,GAAG,YAAY,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS,CAAC,KAAK,CAAA;IACtE,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1D,CAAC;IAED,qBAAqB;IACrB,iEAAiE;IACjE,oFAAoF;IACpF,iFAAiF;IACjF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAClD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,oDAAoD,EAAE,MAAM,EAAE,CAAA;QAC9F,CAAC;QACD,MAAM,CAAC,SAAS,EAAE,AAAD,EAAG,MAAM,CAAC,GAAG,QAAoC,CAAA;QAElE,oEAAoE;QACpE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,wBAAwB,EAAE,GAAG,YAAY,CAAA;QACnE,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAClC,IAAI,CAAC,SAAS,CAAC,wBAAwB,CAAC,CACzC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;QAEvB,MAAM,YAAY,GAAG,GAAG,SAAS,IAAI,gBAAgB,EAAE,CAAA;QACvD,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAA;QAElE,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,YAAY,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAA;QAE3E,MAAM,CAAC,cAAc,GAAG,MAAM,EAAE,CAAC,WAAW,CAC1C,SAAS,EACT,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,EACtC,SAAS,CACV,CAAA;IACH,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,CAAC,cAAc,GAAG,KAAK,CAAA;IAC/B,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QAC3B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,CAAA;IAC7D,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;AAChC,CAAC"}
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidus-network/auth",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "DID-based authentication for the Solidus Network protocol — Ed25519 challenge / W3C Verifiable Presentation verification primitives.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",