@solidus-network/auth 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +128 -18
- package/demo/unlinkability-demo.mjs +159 -0
- package/dist/challenge.d.ts +35 -0
- package/dist/challenge.d.ts.map +1 -1
- package/dist/challenge.js +39 -0
- package/dist/challenge.js.map +1 -1
- package/dist/envelope.d.ts +72 -0
- package/dist/envelope.d.ts.map +1 -0
- package/dist/envelope.js +153 -0
- package/dist/envelope.js.map +1 -0
- package/dist/index.d.ts +10 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/pairwise.d.ts +36 -0
- package/dist/pairwise.d.ts.map +1 -0
- package/dist/pairwise.js +115 -0
- package/dist/pairwise.js.map +1 -0
- package/dist/rp.d.ts +34 -0
- package/dist/rp.d.ts.map +1 -0
- package/dist/rp.js +59 -0
- package/dist/rp.js.map +1 -0
- package/dist/verify.d.ts +76 -1
- package/dist/verify.d.ts.map +1 -1
- package/dist/verify.js +137 -0
- package/dist/verify.js.map +1 -1
- package/package.json +39 -7
|
@@ -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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,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;
|
|
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"}
|
package/dist/pairwise.js
ADDED
|
@@ -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
|
package/dist/rp.d.ts.map
ADDED
|
@@ -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
|
package/dist/verify.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"
|
|
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
|
package/dist/verify.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gBAAgB,CAAA;AACpC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAA;AAE9F,OAAO,EACL,yBAAyB,GAE1B,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAiCtE;;;;;;;;;;;;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;AAgED,SAAS,UAAU,CAAC,GAAW;IAC7B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,KAAK,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACtD,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,SAAuB,EACvB,YAAgD,EAChD,IAAsB;IAEtB,MAAM,MAAM,GAAgD;QAC1D,UAAU,EAAE,KAAK;QACjB,OAAO,EAAE,KAAK;QACd,kBAAkB,EAAE,KAAK;QACzB,qBAAqB,EAAE,KAAK;QAC5B,iBAAiB,EAAE,KAAK;QACxB,gBAAgB,EAAE,KAAK;QACvB,UAAU,EAAE,KAAK;KAClB,CAAA;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,IAAI,IAAI,EAAE,CAAA;IAEtC,MAAM,CAAC,UAAU,GAAG,GAAG,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;IACvD,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACvB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,CAAA;IAC7D,CAAC;IAED,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAA;IACnC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,wBAAwB,EAAE,MAAM,EAAE,CAAA;IAClE,CAAC;IAED,MAAM,CAAC,kBAAkB,GAAG,YAAY,CAAC,WAAW,KAAK,SAAS,CAAC,EAAE,CAAA;IACrE,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAC/B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,4CAA4C,EAAE,MAAM,EAAE,CAAA;IACtF,CAAC;IAED,MAAM,gBAAgB,GAAG,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;IACnE,MAAM,CAAC,qBAAqB,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CACzD,yBAA+C,CAAC,QAAQ,CAAC,CAAC,CAAC,CAC7D,CAAA;IACD,IAAI,CAAC,MAAM,CAAC,qBAAqB,EAAE,CAAC;QAClC,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,+CAA+C;YACtD,MAAM;SACP,CAAA;IACH,CAAC;IAED,MAAM,CAAC,iBAAiB,GAAG,SAAS,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAC/D,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAC7B,CAAA;IACD,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAC9B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,oCAAoC,EAAE,MAAM,EAAE,CAAA;IAC9E,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;IACpE,MAAM,CAAC,gBAAgB,GAAG,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,CAAC,MAAM,KAAK,GAAG,CAAA;IACzF,IAAI,CAAC,MAAM,CAAC,gBAAgB,IAAI,CAAC,YAAY,EAAE,CAAC;QAC9C,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,kDAAkD,EAAE,MAAM,EAAE,CAAA;IAC5F,CAAC;IAED,IAAI,CAAC;QACH,sEAAsE;QACtE,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,cAAc,EAAE,YAAY,CAAC,KAAK,CAAC,CAAA;QAC1F,MAAM,EAAE,GAAG,wBAAwB,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAA;QAClF,MAAM,MAAM,GAAG,CAAC,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAA;QAC5E,MAAM,CAAC,UAAU,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;YACpE,EAAE,EAAE,YAAY,CAAC,OAAO,CAAC,YAAY,CAAC;YACtC,MAAM;YACN,kBAAkB,EAAE,EAAE;YACtB,gBAAgB,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;YAC5C,iBAAiB,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;SAC5D,CAAC,CAAA;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,CAAC,UAAU,GAAG,KAAK,CAAA;IAC3B,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACvB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,2BAA2B,EAAE,MAAM,EAAE,CAAA;IACrE,CAAC;IAED,4EAA4E;IAC5E,4EAA4E;IAC5E,2EAA2E;IAC3E,2DAA2D;IAC3D,IAAI,YAAY,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;QACtC,MAAM,CAAC,oBAAoB,GAAG,KAAK,CAAA;QACnC,MAAM,CAAC,sBAAsB,GAAG,KAAK,CAAA;QAErC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,4DAA4D,EAAE,MAAM,EAAE,CAAA;QACtG,CAAC;QACD,MAAM,UAAU,GAAG,oBAAoB,CAAC,YAAY,CAAC,aAAa,CAAC,CAAA;QACnE,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,+BAA+B,EAAE,MAAM,EAAE,CAAA;QACzE,CAAC;QAED,0EAA0E;QAC1E,yEAAyE;QACzE,gEAAgE;QAChE,IAAI,MAAkB,CAAA;QACtB,IAAI,CAAC;YACH,MAAM,GAAG,UAAU,CAAC,UAAU,CAAC,YAAY,CAAC,CAAA;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,sCAAsC,EAAE,MAAM,EAAE,CAAA;QAChF,CAAC;QACD,MAAM,aAAa,GAAG,gBAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QAC5D,MAAM,CAAC,oBAAoB;YACzB,aAAa,KAAK,YAAY,CAAC,WAAW,IAAI,UAAU,CAAC,EAAE,CAAC,MAAM,KAAK,YAAY,CAAC,WAAW,CAAA;QACjG,IAAI,CAAC,MAAM,CAAC,oBAAoB,EAAE,CAAC;YACjC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,8CAA8C,EAAE,MAAM,EAAE,CAAA;QACxF,CAAC;QAED,2EAA2E;QAC3E,sEAAsE;QACtE,uCAAuC;QACvC,MAAM,iBAAiB,GAAc;YACnC,EAAE,EAAE,SAAS,CAAC,EAAE;YAChB,GAAG,EAAE,YAAY,CAAC,WAAW;YAC7B,KAAK,EAAE,SAAS,CAAC,KAAK;YACtB,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,SAAS,EAAE,SAAS,CAAC,SAAS;SAC/B,CAAA;QACD,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,iBAAiB,EAAE,UAAU,CAAC,EAAE,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,CAAA;QAC/F,MAAM,CAAC,sBAAsB,GAAG,QAAQ,CAAC,KAAK,CAAA;QAC9C,IAAI,CAAC,MAAM,CAAC,sBAAsB,EAAE,CAAC;YACnC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,wBAAwB,QAAQ,CAAC,KAAK,IAAI,WAAW,EAAE,EAAE,MAAM,EAAE,CAAA;QACjG,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,CAAC,WAAW,EAAE,CAAA;IACvE,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;AAChC,CAAC"}
|