@solidus-network/bbs 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 +25 -0
- package/dist/benchmark.d.ts +73 -0
- package/dist/benchmark.d.ts.map +1 -0
- package/dist/benchmark.js +190 -0
- package/dist/benchmark.js.map +1 -0
- package/dist/dispatch.d.ts +50 -0
- package/dist/dispatch.d.ts.map +1 -0
- package/dist/dispatch.js +35 -0
- package/dist/dispatch.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -2
- package/dist/index.js.map +1 -1
- package/dist/v2.d.ts +30 -0
- package/dist/v2.d.ts.map +1 -0
- package/dist/v2.js +75 -0
- package/dist/v2.js.map +1 -0
- package/package.json +25 -7
package/README.md
CHANGED
|
@@ -78,6 +78,31 @@ const ok = await proof.verify({
|
|
|
78
78
|
})
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
+
## Credential-format v2 helpers (unlinkable presentations)
|
|
82
|
+
|
|
83
|
+
The helpers behind Solidus's unlinkable KYC presentations (used by
|
|
84
|
+
`@solidus-network/auth`'s verifier surface — see that package's README for the
|
|
85
|
+
full relying-party quickstart and the runnable unlinkability demo):
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import { buildV2Header, derivePresentationHeader, BBS_CREDENTIAL_V2 } from '@solidus-network/bbs'
|
|
89
|
+
|
|
90
|
+
// The v2 signing header is CONSTANT per (issuer, credential-type, epoch) —
|
|
91
|
+
// no per-credential entropy, so it places a holder in a cohort, never
|
|
92
|
+
// identifies one:
|
|
93
|
+
const header = buildV2Header('did:solidus:testnet:issuer', 'kyc', 2)
|
|
94
|
+
// utf8("solidus-bbs-credential:v2:did:solidus:testnet:issuer:kyc:2")
|
|
95
|
+
|
|
96
|
+
// The presentation header binds a proof to ONE verifier challenge
|
|
97
|
+
// (length-prefixed domain ‖ nonce, hashed) — replay under any other
|
|
98
|
+
// challenge fails cryptographically:
|
|
99
|
+
const ph = derivePresentationHeader('rp.example.com', nonce32)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Also exported: `benchmarkDevice` / `decideProofPath` (the on-device
|
|
103
|
+
proof-generation benchmark that routes slow devices to an assist prover)
|
|
104
|
+
and `dispatchProof` (the routing itself).
|
|
105
|
+
|
|
81
106
|
## Sizes
|
|
82
107
|
|
|
83
108
|
| Element | Bytes |
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/** Latency budget for the client-side (primary) proof path. */
|
|
2
|
+
export declare const PROOF_GEN_BUDGET: Readonly<{
|
|
3
|
+
/** Median proof-gen must be at or under this for the client path. */
|
|
4
|
+
p50Ms: 1500;
|
|
5
|
+
/** A single run above this routes to assist immediately. */
|
|
6
|
+
p95Ms: 3000;
|
|
7
|
+
}>;
|
|
8
|
+
export type ProofGenBudget = typeof PROOF_GEN_BUDGET;
|
|
9
|
+
export interface TimingSummary {
|
|
10
|
+
runs: number;
|
|
11
|
+
p50Ms: number;
|
|
12
|
+
p95Ms: number;
|
|
13
|
+
meanMs: number;
|
|
14
|
+
minMs: number;
|
|
15
|
+
maxMs: number;
|
|
16
|
+
}
|
|
17
|
+
/** Where this device should generate selective-disclosure proofs. */
|
|
18
|
+
export type ProofPath = 'client' | 'assist';
|
|
19
|
+
export interface ProofPathDecision {
|
|
20
|
+
path: ProofPath;
|
|
21
|
+
/** Raw per-run proof-gen timings gathered before deciding. */
|
|
22
|
+
samplesMs: number[];
|
|
23
|
+
budget: ProofGenBudget;
|
|
24
|
+
/** ISO timestamp — callers cache the decision keyed by app version. */
|
|
25
|
+
decidedAt: string;
|
|
26
|
+
}
|
|
27
|
+
export interface ProofGenMeasurement {
|
|
28
|
+
/** One-time cost: deterministic keygen + signing the 8-message vector. */
|
|
29
|
+
setupMs: number;
|
|
30
|
+
proofGen: TimingSummary;
|
|
31
|
+
verify: TimingSummary;
|
|
32
|
+
/** True iff a generated proof verified — proves the harness measured real crypto. */
|
|
33
|
+
proofVerified: boolean;
|
|
34
|
+
proofBytes: number;
|
|
35
|
+
messageCount: number;
|
|
36
|
+
hiddenIndices: number[];
|
|
37
|
+
disclosedIndices: number[];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Nearest-rank percentile summary. p50 over an even-sized sample is the
|
|
41
|
+
* lower-middle element (nearest-rank, not interpolated) — deterministic and
|
|
42
|
+
* adequate for routing decisions.
|
|
43
|
+
*/
|
|
44
|
+
export declare function summarizeTimings(samplesMs: number[]): TimingSummary;
|
|
45
|
+
/**
|
|
46
|
+
* Final routing rule: the sample median (nearest-rank p50) must be within
|
|
47
|
+
* the p50 budget for the client path.
|
|
48
|
+
*/
|
|
49
|
+
export declare function decideProofPath(samplesMs: number[], budget?: ProofGenBudget): ProofPath;
|
|
50
|
+
/**
|
|
51
|
+
* One-shot adaptive device benchmark (run at wallet init, cache the result).
|
|
52
|
+
*
|
|
53
|
+
* Cost on a fast device: one proof-gen. On a decisively slow device: also
|
|
54
|
+
* one (a single run over the p95 budget answers the question). Only the
|
|
55
|
+
* inconclusive middle gathers up to `maxRuns` samples, then the median
|
|
56
|
+
* decides against the p50 budget.
|
|
57
|
+
*/
|
|
58
|
+
export declare function benchmarkDevice(opts?: {
|
|
59
|
+
budget?: ProofGenBudget;
|
|
60
|
+
maxRuns?: number;
|
|
61
|
+
/** Injectable for tests: returns one proof-gen duration in ms. */
|
|
62
|
+
runProofGen?: () => Promise<number>;
|
|
63
|
+
}): Promise<ProofPathDecision>;
|
|
64
|
+
/**
|
|
65
|
+
* Full measurement harness behind the device-tier latency table. Signs the
|
|
66
|
+
* synthetic vector once, then times `runs` proof generations and `runs`
|
|
67
|
+
* proof verifications, and sanity-verifies one proof so a broken harness
|
|
68
|
+
* cannot report numbers for crypto it never ran.
|
|
69
|
+
*/
|
|
70
|
+
export declare function measureProofGeneration(opts?: {
|
|
71
|
+
runs?: number;
|
|
72
|
+
}): Promise<ProofGenMeasurement>;
|
|
73
|
+
//# sourceMappingURL=benchmark.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"benchmark.d.ts","sourceRoot":"","sources":["../src/benchmark.ts"],"names":[],"mappings":"AA6BA,+DAA+D;AAC/D,eAAO,MAAM,gBAAgB;IAC3B,qEAAqE;;IAErE,4DAA4D;;EAE5D,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG,OAAO,gBAAgB,CAAA;AAEpD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED,qEAAqE;AACrE,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAE3C,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,SAAS,CAAA;IACf,8DAA8D;IAC9D,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,MAAM,EAAE,cAAc,CAAA;IACtB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,aAAa,CAAA;IACvB,MAAM,EAAE,aAAa,CAAA;IACrB,qFAAqF;IACrF,aAAa,EAAE,OAAO,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAC3B;AAOD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,aAAa,CAenE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EAAE,EACnB,MAAM,GAAE,cAAiC,GACxC,SAAS,CAEX;AAuED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,IAAI,CAAC,EAAE;IAC3C,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CACpC,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAuB7B;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,CAAC,EAAE;IAClD,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA8B/B"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proof-generation micro-benchmark + device routing (privacy rebuild Phase 0).
|
|
3
|
+
*
|
|
4
|
+
* BBS+ selective-disclosure proof generation is pure-JS BLS12-381 math
|
|
5
|
+
* (`@noble/curves` under `@digitalbazaar/bbs-signatures`) — fast enough on
|
|
6
|
+
* laptops, unproven on phones. The wallet runs {@link benchmarkDevice} once
|
|
7
|
+
* at init (cache the result — see below) to route each device:
|
|
8
|
+
*
|
|
9
|
+
* - `'client'` — proofs are generated on-device; the signing bundle never
|
|
10
|
+
* leaves the wallet (the primary, privacy-preserving path).
|
|
11
|
+
* - `'assist'` — this device is too slow; the wallet uses the stateless
|
|
12
|
+
* assist prover (pod-mediated fallback). The UI must disclose this.
|
|
13
|
+
*
|
|
14
|
+
* Budget (frozen by the rebuild plan §6 Phase 0): the client path requires
|
|
15
|
+
* proof-gen ≤ 1.5 s p50 / 3 s p95 on the device.
|
|
16
|
+
*
|
|
17
|
+
* Caching is the CALLER's job: persist the returned decision keyed by app
|
|
18
|
+
* version (a library upgrade can change the numbers) and re-use it instead
|
|
19
|
+
* of re-benchmarking every init. Proof generation is synchronous CPU work —
|
|
20
|
+
* on the web, run this (and real proof-gen) in a Worker to keep the main
|
|
21
|
+
* thread responsive.
|
|
22
|
+
*
|
|
23
|
+
* The benchmark exercises the production configuration: an 8-message
|
|
24
|
+
* KYC-shaped vector (synthetic data), hiding indices {0,2,3,6,7} and
|
|
25
|
+
* disclosing {1,4,5} — hidden messages are what make proof-gen expensive,
|
|
26
|
+
* so this is the worst-case production shape.
|
|
27
|
+
*/
|
|
28
|
+
import { BbsSecretKey, utf8 } from './index.js';
|
|
29
|
+
/** Latency budget for the client-side (primary) proof path. */
|
|
30
|
+
export const PROOF_GEN_BUDGET = Object.freeze({
|
|
31
|
+
/** Median proof-gen must be at or under this for the client path. */
|
|
32
|
+
p50Ms: 1500,
|
|
33
|
+
/** A single run above this routes to assist immediately. */
|
|
34
|
+
p95Ms: 3000,
|
|
35
|
+
});
|
|
36
|
+
function now() {
|
|
37
|
+
const perf = globalThis.performance;
|
|
38
|
+
return perf ? perf.now() : Date.now();
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Nearest-rank percentile summary. p50 over an even-sized sample is the
|
|
42
|
+
* lower-middle element (nearest-rank, not interpolated) — deterministic and
|
|
43
|
+
* adequate for routing decisions.
|
|
44
|
+
*/
|
|
45
|
+
export function summarizeTimings(samplesMs) {
|
|
46
|
+
if (samplesMs.length === 0) {
|
|
47
|
+
throw new Error('summarizeTimings requires at least one sample');
|
|
48
|
+
}
|
|
49
|
+
const sorted = [...samplesMs].sort((a, b) => a - b);
|
|
50
|
+
const rank = (q) => sorted[Math.ceil((q / 100) * sorted.length) - 1];
|
|
51
|
+
const sum = sorted.reduce((n, x) => n + x, 0);
|
|
52
|
+
return {
|
|
53
|
+
runs: sorted.length,
|
|
54
|
+
p50Ms: rank(50),
|
|
55
|
+
p95Ms: rank(95),
|
|
56
|
+
meanMs: sum / sorted.length,
|
|
57
|
+
minMs: sorted[0],
|
|
58
|
+
maxMs: sorted[sorted.length - 1],
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Final routing rule: the sample median (nearest-rank p50) must be within
|
|
63
|
+
* the p50 budget for the client path.
|
|
64
|
+
*/
|
|
65
|
+
export function decideProofPath(samplesMs, budget = PROOF_GEN_BUDGET) {
|
|
66
|
+
return summarizeTimings(samplesMs).p50Ms <= budget.p50Ms ? 'client' : 'assist';
|
|
67
|
+
}
|
|
68
|
+
// ---------- synthetic production-shaped workload ----------
|
|
69
|
+
// Synthetic KYC-shaped vector — realistic byte lengths, no real data.
|
|
70
|
+
const BENCH_MESSAGES = [
|
|
71
|
+
'did:solidus:testnet:9f4kAqNwXyBhcVpQ2mTuLgRd3eZs', // 0 subject_did (hidden)
|
|
72
|
+
'did:solidus:testnet:6bJcQvJqrgXk2sYwHnEuPfM8dTzA', // 1 issuer_did (disclosed)
|
|
73
|
+
'3f2504e0-4f89-41d3-9a0c-0305e82c3301', // 2 verification_id (hidden)
|
|
74
|
+
'2026-01-01T00:00:00.000Z', // 3 verified_at (hidden)
|
|
75
|
+
'2', // 4 kyc_level (disclosed)
|
|
76
|
+
'TR', // 5 country (disclosed)
|
|
77
|
+
'passport', // 6 document_type (hidden)
|
|
78
|
+
'9c1185a5c5e9fc54612808977ee8f548b2258d31d8a4c48e14d3c8b6a9f2e701', // 7 document_hash (hidden)
|
|
79
|
+
].map(utf8);
|
|
80
|
+
const BENCH_HIDDEN = [0, 2, 3, 6, 7];
|
|
81
|
+
const BENCH_DISCLOSED = [1, 4, 5];
|
|
82
|
+
// v2-shaped header: issuer/type/epoch constant (the target envelope format).
|
|
83
|
+
const BENCH_HEADER = utf8('solidus-bbs-credential:v2:did:solidus:testnet:6bJcQvJqrgXk2sYwHnEuPfM8dTzA:kyc:1');
|
|
84
|
+
const BENCH_PH = utf8('solidus-bbs-benchmark-ph:example.rp.solidus.network:0123456789abcdef');
|
|
85
|
+
const BENCH_IKM = utf8('solidus-bbs-proofgen-benchmark-fixed-ikm-32-bytes-or-more.v1');
|
|
86
|
+
async function createBenchContext() {
|
|
87
|
+
const t0 = now();
|
|
88
|
+
const sk = await BbsSecretKey.fromIkm(BENCH_IKM);
|
|
89
|
+
const pk = await sk.publicKey();
|
|
90
|
+
const sig = await sk.sign(BENCH_HEADER, BENCH_MESSAGES);
|
|
91
|
+
const setupMs = now() - t0;
|
|
92
|
+
const runOnce = async () => {
|
|
93
|
+
const t = now();
|
|
94
|
+
await sig.createProof({
|
|
95
|
+
pk,
|
|
96
|
+
header: BENCH_HEADER,
|
|
97
|
+
presentationHeader: BENCH_PH,
|
|
98
|
+
messages: BENCH_MESSAGES,
|
|
99
|
+
disclosedIndices: BENCH_DISCLOSED,
|
|
100
|
+
});
|
|
101
|
+
return now() - t;
|
|
102
|
+
};
|
|
103
|
+
const verifyOnce = async () => {
|
|
104
|
+
const proof = await sig.createProof({
|
|
105
|
+
pk,
|
|
106
|
+
header: BENCH_HEADER,
|
|
107
|
+
presentationHeader: BENCH_PH,
|
|
108
|
+
messages: BENCH_MESSAGES,
|
|
109
|
+
disclosedIndices: BENCH_DISCLOSED,
|
|
110
|
+
});
|
|
111
|
+
const disclosedMessages = BENCH_DISCLOSED.map((i) => BENCH_MESSAGES[i]);
|
|
112
|
+
const t = now();
|
|
113
|
+
const verified = await proof.verify({
|
|
114
|
+
pk,
|
|
115
|
+
header: BENCH_HEADER,
|
|
116
|
+
presentationHeader: BENCH_PH,
|
|
117
|
+
disclosedIndices: BENCH_DISCLOSED,
|
|
118
|
+
disclosedMessages,
|
|
119
|
+
});
|
|
120
|
+
return { ms: now() - t, verified, proofBytes: proof.toBytes().length };
|
|
121
|
+
};
|
|
122
|
+
return { runOnce, verifyOnce, setupMs };
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* One-shot adaptive device benchmark (run at wallet init, cache the result).
|
|
126
|
+
*
|
|
127
|
+
* Cost on a fast device: one proof-gen. On a decisively slow device: also
|
|
128
|
+
* one (a single run over the p95 budget answers the question). Only the
|
|
129
|
+
* inconclusive middle gathers up to `maxRuns` samples, then the median
|
|
130
|
+
* decides against the p50 budget.
|
|
131
|
+
*/
|
|
132
|
+
export async function benchmarkDevice(opts) {
|
|
133
|
+
const budget = opts?.budget ?? PROOF_GEN_BUDGET;
|
|
134
|
+
const maxRuns = opts?.maxRuns ?? 3;
|
|
135
|
+
const run = opts?.runProofGen ?? (await createBenchContext()).runOnce;
|
|
136
|
+
const samplesMs = [];
|
|
137
|
+
let path;
|
|
138
|
+
for (let i = 0; i < maxRuns; i++) {
|
|
139
|
+
const ms = await run();
|
|
140
|
+
samplesMs.push(ms);
|
|
141
|
+
if (i === 0) {
|
|
142
|
+
if (ms <= budget.p50Ms) {
|
|
143
|
+
path = 'client';
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
if (ms > budget.p95Ms) {
|
|
147
|
+
path = 'assist';
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
path ??= decideProofPath(samplesMs, budget);
|
|
153
|
+
return { path, samplesMs, budget, decidedAt: new Date().toISOString() };
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Full measurement harness behind the device-tier latency table. Signs the
|
|
157
|
+
* synthetic vector once, then times `runs` proof generations and `runs`
|
|
158
|
+
* proof verifications, and sanity-verifies one proof so a broken harness
|
|
159
|
+
* cannot report numbers for crypto it never ran.
|
|
160
|
+
*/
|
|
161
|
+
export async function measureProofGeneration(opts) {
|
|
162
|
+
const runs = opts?.runs ?? 30;
|
|
163
|
+
if (runs < 1)
|
|
164
|
+
throw new Error('measureProofGeneration requires runs ≥ 1');
|
|
165
|
+
const ctx = await createBenchContext();
|
|
166
|
+
const proofGenSamples = [];
|
|
167
|
+
for (let i = 0; i < runs; i++) {
|
|
168
|
+
proofGenSamples.push(await ctx.runOnce());
|
|
169
|
+
}
|
|
170
|
+
const verifySamples = [];
|
|
171
|
+
let proofVerified = true;
|
|
172
|
+
let proofBytes = 0;
|
|
173
|
+
for (let i = 0; i < runs; i++) {
|
|
174
|
+
const v = await ctx.verifyOnce();
|
|
175
|
+
verifySamples.push(v.ms);
|
|
176
|
+
proofVerified &&= v.verified;
|
|
177
|
+
proofBytes = v.proofBytes;
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
setupMs: ctx.setupMs,
|
|
181
|
+
proofGen: summarizeTimings(proofGenSamples),
|
|
182
|
+
verify: summarizeTimings(verifySamples),
|
|
183
|
+
proofVerified,
|
|
184
|
+
proofBytes,
|
|
185
|
+
messageCount: BENCH_MESSAGES.length,
|
|
186
|
+
hiddenIndices: [...BENCH_HIDDEN],
|
|
187
|
+
disclosedIndices: [...BENCH_DISCLOSED],
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=benchmark.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"benchmark.js","sourceRoot":"","sources":["../src/benchmark.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proof-path dispatch (privacy rebuild §5.3 — wallet routing).
|
|
3
|
+
*
|
|
4
|
+
* The wallet benchmarks the device once (`benchmarkDevice`) and caches the
|
|
5
|
+
* decision. Each presentation routes through `dispatchProof`: generate the
|
|
6
|
+
* proof on-device when the device is fast, or hand a decrypted bundle to the
|
|
7
|
+
* assist prover when it is slow. The dispatcher returns which path ran so the
|
|
8
|
+
* UI can disclose it honestly ("proving on Solidus's assist service because
|
|
9
|
+
* this device is slow") — never a blanket "non-custodial" claim.
|
|
10
|
+
*
|
|
11
|
+
* A client-path FAILURE is NOT silently retried on the assist service —
|
|
12
|
+
* rerouting a bundle to the server behind the user's back would violate the
|
|
13
|
+
* privacy expectation the client path set. The caller decides whether to
|
|
14
|
+
* re-benchmark and retry.
|
|
15
|
+
*/
|
|
16
|
+
import type { ProofPath, ProofPathDecision } from './benchmark.js';
|
|
17
|
+
export interface ProofDispatchHandlers {
|
|
18
|
+
/** Generate the proof on-device; returns proofHex. */
|
|
19
|
+
localProve: () => Promise<string>;
|
|
20
|
+
/** Generate the proof via the assist prover; returns proofHex. */
|
|
21
|
+
fallbackProve: () => Promise<string>;
|
|
22
|
+
}
|
|
23
|
+
export interface DispatchedProof {
|
|
24
|
+
proofHex: string;
|
|
25
|
+
/** Which path produced the proof — surface this in the UI. */
|
|
26
|
+
path: ProofPath;
|
|
27
|
+
}
|
|
28
|
+
/** Route a proof to the client or the assist path per the cached decision. */
|
|
29
|
+
export declare function dispatchProof(decision: ProofPathDecision | {
|
|
30
|
+
path: ProofPath;
|
|
31
|
+
}, handlers: ProofDispatchHandlers): Promise<DispatchedProof>;
|
|
32
|
+
/** Request payload for the assist prover's `POST /v1/prove`. */
|
|
33
|
+
export interface AssistProveRequest {
|
|
34
|
+
messagesHex: string[];
|
|
35
|
+
signatureHex: string;
|
|
36
|
+
issuerPubkeyHex: string;
|
|
37
|
+
headerHex: string;
|
|
38
|
+
phHex: string;
|
|
39
|
+
disclosedIndices: number[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Call the stateless assist prover. `walletJwt` is the identity-api-issued
|
|
43
|
+
* wallet token; `fetchImpl` is injectable for tests. Throws on any non-200.
|
|
44
|
+
* The caller is responsible for TLS (the URL must be https in production) and
|
|
45
|
+
* for zeroizing the plaintext bundle it passed once this resolves.
|
|
46
|
+
*/
|
|
47
|
+
export declare function callAssistProver(proveUrl: string, walletJwt: string, req: AssistProveRequest, opts?: {
|
|
48
|
+
fetchImpl?: typeof fetch;
|
|
49
|
+
}): Promise<string>;
|
|
50
|
+
//# sourceMappingURL=dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAElE,MAAM,WAAW,qBAAqB;IACpC,sDAAsD;IACtD,UAAU,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;IACjC,kEAAkE;IAClE,aAAa,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CACrC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAA;IAChB,8DAA8D;IAC9D,IAAI,EAAE,SAAS,CAAA;CAChB;AAED,8EAA8E;AAC9E,wBAAsB,aAAa,CACjC,QAAQ,EAAE,iBAAiB,GAAG;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,EACjD,QAAQ,EAAE,qBAAqB,GAC9B,OAAO,CAAC,eAAe,CAAC,CAK1B;AAED,gEAAgE;AAChE,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,eAAe,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAC3B;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,kBAAkB,EACvB,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CAAE,GAClC,OAAO,CAAC,MAAM,CAAC,CAmBjB"}
|
package/dist/dispatch.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** Route a proof to the client or the assist path per the cached decision. */
|
|
2
|
+
export async function dispatchProof(decision, handlers) {
|
|
3
|
+
if (decision.path === 'client') {
|
|
4
|
+
return { proofHex: await handlers.localProve(), path: 'client' };
|
|
5
|
+
}
|
|
6
|
+
return { proofHex: await handlers.fallbackProve(), path: 'assist' };
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Call the stateless assist prover. `walletJwt` is the identity-api-issued
|
|
10
|
+
* wallet token; `fetchImpl` is injectable for tests. Throws on any non-200.
|
|
11
|
+
* The caller is responsible for TLS (the URL must be https in production) and
|
|
12
|
+
* for zeroizing the plaintext bundle it passed once this resolves.
|
|
13
|
+
*/
|
|
14
|
+
export async function callAssistProver(proveUrl, walletJwt, req, opts) {
|
|
15
|
+
const doFetch = opts?.fetchImpl ?? globalThis.fetch;
|
|
16
|
+
if (!doFetch)
|
|
17
|
+
throw new Error('no fetch implementation available');
|
|
18
|
+
const res = await doFetch(proveUrl, {
|
|
19
|
+
method: 'POST',
|
|
20
|
+
headers: {
|
|
21
|
+
'content-type': 'application/json',
|
|
22
|
+
authorization: `Bearer ${walletJwt}`,
|
|
23
|
+
},
|
|
24
|
+
body: JSON.stringify(req),
|
|
25
|
+
});
|
|
26
|
+
if (!res.ok) {
|
|
27
|
+
throw new Error(`assist prover returned ${res.status}`);
|
|
28
|
+
}
|
|
29
|
+
const body = (await res.json());
|
|
30
|
+
if (typeof body.proofHex !== 'string' || body.proofHex.length === 0) {
|
|
31
|
+
throw new Error('assist prover response missing proofHex');
|
|
32
|
+
}
|
|
33
|
+
return body.proofHex;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"AA8BA,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAAiD,EACjD,QAA+B;IAE/B,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA;IAClE,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA;AACrE,CAAC;AAYD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,QAAgB,EAChB,SAAiB,EACjB,GAAuB,EACvB,IAAmC;IAEnC,MAAM,OAAO,GAAG,IAAI,EAAE,SAAS,IAAK,UAAU,CAAC,KAAsB,CAAA;IACrE,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAA;IAClE,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE;QAClC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,SAAS,EAAE;SACrC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;KAC1B,CAAC,CAAA;IACF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAA;IACzD,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA2B,CAAA;IACzD,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;IAC5D,CAAC;IACD,OAAO,IAAI,CAAC,QAAQ,CAAA;AACtB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -98,4 +98,7 @@ export declare class BbsProof {
|
|
|
98
98
|
}
|
|
99
99
|
/** Encode a UTF-8 string as raw bytes (for use as a message or header). */
|
|
100
100
|
export declare function utf8(s: string): Uint8Array;
|
|
101
|
+
export * from './benchmark.js';
|
|
102
|
+
export * from './v2.js';
|
|
103
|
+
export * from './dispatch.js';
|
|
101
104
|
//# 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":"AA+BA,kEAAkE;AAClE,eAAO,MAAM,oBAAoB,KAAK,CAAA;AACtC,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB,KAAK,CAAA;AACtC,2CAA2C;AAC3C,eAAO,MAAM,mBAAmB,KAAK,CAAA;AACrC;;;GAGG;AACH,eAAO,MAAM,qBAAqB,KAAK,CAAA;AAIvC,qBAAa,QAAS,SAAQ,KAAK;IACJ,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO;gBAAzC,OAAO,EAAE,MAAM,EAAW,KAAK,CAAC,EAAE,OAAO,YAAA;CAItD;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -44,14 +44,25 @@ function assertLen(label, got, want) {
|
|
|
44
44
|
throw new BbsError(`${label}: expected ${want} bytes, got ${got}`);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
+
// Buffer-free hex codecs — this package runs in the browser wallet
|
|
48
|
+
// (client-side proof generation is the primary path), where node globals
|
|
49
|
+
// don't exist and Next/webpack no longer polyfill them.
|
|
47
50
|
function toHex(bytes) {
|
|
48
|
-
|
|
51
|
+
let out = '';
|
|
52
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
53
|
+
out += bytes[i].toString(16).padStart(2, '0');
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
49
56
|
}
|
|
50
57
|
function fromHex(hex, label) {
|
|
51
58
|
if (!/^[0-9a-f]*$/i.test(hex) || hex.length % 2 !== 0) {
|
|
52
59
|
throw new BbsError(`${label} is not valid hex`);
|
|
53
60
|
}
|
|
54
|
-
|
|
61
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
62
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
63
|
+
bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
64
|
+
}
|
|
65
|
+
return bytes;
|
|
55
66
|
}
|
|
56
67
|
// ---------- BbsSecretKey ----------
|
|
57
68
|
export class BbsSecretKey {
|
|
@@ -267,4 +278,10 @@ export class BbsProof {
|
|
|
267
278
|
export function utf8(s) {
|
|
268
279
|
return new TextEncoder().encode(s);
|
|
269
280
|
}
|
|
281
|
+
// ---------- proof-generation benchmark + device routing (Phase 0) ----------
|
|
282
|
+
export * from './benchmark.js';
|
|
283
|
+
// ---------- credential-envelope v2 format helpers (Phase 1) ----------
|
|
284
|
+
export * from './v2.js';
|
|
285
|
+
// ---------- proof-path dispatch: client vs assist prover (Phase 3B) ----------
|
|
286
|
+
export * from './dispatch.js';
|
|
270
287
|
//# 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;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EACL,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,IAAI,IAAI,OAAO,EACf,eAAe,IAAI,SAAS,EAC5B,WAAW,IAAI,cAAc,EAC7B,WAAW,IAAI,cAAc,GAC9B,MAAM,+BAA+B,CAAA;AAEtC,MAAM,WAAW,GAAG,YAAY,CAAC,eAAe,CAAA;AAEhD,mEAAmE;AAEnE,kEAAkE;AAClE,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAA;AACtC,4EAA4E;AAC5E,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAA;AACtC,2CAA2C;AAC3C,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAA;AACrC;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,CAAA;AAEvC,oCAAoC;AAEpC,MAAM,OAAO,QAAS,SAAQ,KAAK;IACK;IAAtC,YAAY,OAAe,EAAW,KAAe;QACnD,KAAK,CAAC,OAAO,CAAC,CAAA;QADsB,UAAK,GAAL,KAAK,CAAU;QAEnD,IAAI,CAAC,IAAI,GAAG,UAAU,CAAA;IACxB,CAAC;CACF;AAED,gCAAgC;AAEhC,SAAS,SAAS,CAAC,KAAa,EAAE,GAAW,EAAE,IAAY;IACzD,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,MAAM,IAAI,QAAQ,CAAC,GAAG,KAAK,cAAc,IAAI,eAAe,GAAG,EAAE,CAAC,CAAA;IACpE,CAAC;AACH,CAAC;AAED,SAAS,KAAK,CAAC,KAAiB;IAC9B,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/v2.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Version marker carried by v2 credential bundles and envelopes. */
|
|
2
|
+
export declare const BBS_CREDENTIAL_V2 = "bbs-v2";
|
|
3
|
+
/**
|
|
4
|
+
* Build the v2 BBS header: `solidus-bbs-credential:v2:<issuerDid>:<credentialType>:<epoch>`.
|
|
5
|
+
*
|
|
6
|
+
* Issuer/type/epoch-level CONSTANT — contains no per-credential entropy by
|
|
7
|
+
* construction. `credentialType` must not contain `:` (keeps the cohort
|
|
8
|
+
* label unambiguous); `epoch` is the issuer's key-rotation epoch (a cohort
|
|
9
|
+
* label shared by all holders issued in that epoch, never per-credential).
|
|
10
|
+
*/
|
|
11
|
+
export declare function buildV2Header(issuerDid: string, credentialType: string, epoch: number): Uint8Array;
|
|
12
|
+
/**
|
|
13
|
+
* Derive the presentation header binding a proof to one verifier challenge:
|
|
14
|
+
*
|
|
15
|
+
* ph = SHA-256( utf8("solidus.bbs.ph.v1") ‖ u32le(|domain|) ‖ utf8(domain) ‖ nonce )
|
|
16
|
+
*
|
|
17
|
+
* `deriveProof` folds `ph` into the Fiat–Shamir challenge, so a proof made
|
|
18
|
+
* under one `ph` fails under any other — replay across challenges or across
|
|
19
|
+
* verifiers is cryptographically dead. The verifier recomputes `ph` from its
|
|
20
|
+
* own authenticated `domain` and the stored challenge `nonce`; nonce
|
|
21
|
+
* single-use + expiry enforcement is the verifier's job on top.
|
|
22
|
+
*
|
|
23
|
+
* The domain is length-prefixed (u32le, matching the project's LE
|
|
24
|
+
* convention) because bare `domain ‖ nonce` concatenation is boundary-
|
|
25
|
+
* ambiguous: ("rp.example.com", 00‖…) and ("rp.example.com\x00", …) would
|
|
26
|
+
* hash identically, letting a verifier with a prefix-compatible domain
|
|
27
|
+
* alias another verifier's challenge and replay a captured presentation.
|
|
28
|
+
*/
|
|
29
|
+
export declare function derivePresentationHeader(domain: string, nonce: Uint8Array): Uint8Array;
|
|
30
|
+
//# sourceMappingURL=v2.d.ts.map
|
package/dist/v2.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v2.d.ts","sourceRoot":"","sources":["../src/v2.ts"],"names":[],"mappings":"AAgBA,qEAAqE;AACrE,eAAO,MAAM,iBAAiB,WAAW,CAAA;AAKzC;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,MAAM,GACZ,UAAU,CAUZ;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,UAAU,CAetF"}
|
package/dist/v2.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credential-envelope v2 format helpers (privacy rebuild — T2).
|
|
3
|
+
*
|
|
4
|
+
* WIRE FORMAT — changing anything here is a credential-format change that
|
|
5
|
+
* requires bumping the version marker and re-issuing credentials.
|
|
6
|
+
*
|
|
7
|
+
* Header v2 closes the v1 header leak: v1 embedded the per-credential
|
|
8
|
+
* `verificationId`, which IRTF BBS requires in cleartext at verify — a
|
|
9
|
+
* correlation handle as strong as the DID even with all messages hidden.
|
|
10
|
+
* v2 headers are constant per (issuer, credentialType, epoch) cohort, so
|
|
11
|
+
* every holder in the cohort shares one header — an anonymity set, not a
|
|
12
|
+
* handle. `verification_id` lives on as hidden message index 2 only.
|
|
13
|
+
*/
|
|
14
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
15
|
+
import { BbsError, utf8 } from './index.js';
|
|
16
|
+
/** Version marker carried by v2 credential bundles and envelopes. */
|
|
17
|
+
export const BBS_CREDENTIAL_V2 = 'bbs-v2';
|
|
18
|
+
/** Domain-separation tag for presentation-header derivation. */
|
|
19
|
+
const PH_DOMAIN_TAG = 'solidus.bbs.ph.v1';
|
|
20
|
+
/**
|
|
21
|
+
* Build the v2 BBS header: `solidus-bbs-credential:v2:<issuerDid>:<credentialType>:<epoch>`.
|
|
22
|
+
*
|
|
23
|
+
* Issuer/type/epoch-level CONSTANT — contains no per-credential entropy by
|
|
24
|
+
* construction. `credentialType` must not contain `:` (keeps the cohort
|
|
25
|
+
* label unambiguous); `epoch` is the issuer's key-rotation epoch (a cohort
|
|
26
|
+
* label shared by all holders issued in that epoch, never per-credential).
|
|
27
|
+
*/
|
|
28
|
+
export function buildV2Header(issuerDid, credentialType, epoch) {
|
|
29
|
+
if (!issuerDid)
|
|
30
|
+
throw new BbsError('issuerDid must be non-empty');
|
|
31
|
+
if (!credentialType)
|
|
32
|
+
throw new BbsError('credentialType must be non-empty');
|
|
33
|
+
if (credentialType.includes(':')) {
|
|
34
|
+
throw new BbsError('credentialType must not contain ":"');
|
|
35
|
+
}
|
|
36
|
+
if (!Number.isInteger(epoch) || epoch < 0) {
|
|
37
|
+
throw new BbsError(`epoch must be a non-negative integer, got ${epoch}`);
|
|
38
|
+
}
|
|
39
|
+
return utf8(`solidus-bbs-credential:v2:${issuerDid}:${credentialType}:${epoch}`);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Derive the presentation header binding a proof to one verifier challenge:
|
|
43
|
+
*
|
|
44
|
+
* ph = SHA-256( utf8("solidus.bbs.ph.v1") ‖ u32le(|domain|) ‖ utf8(domain) ‖ nonce )
|
|
45
|
+
*
|
|
46
|
+
* `deriveProof` folds `ph` into the Fiat–Shamir challenge, so a proof made
|
|
47
|
+
* under one `ph` fails under any other — replay across challenges or across
|
|
48
|
+
* verifiers is cryptographically dead. The verifier recomputes `ph` from its
|
|
49
|
+
* own authenticated `domain` and the stored challenge `nonce`; nonce
|
|
50
|
+
* single-use + expiry enforcement is the verifier's job on top.
|
|
51
|
+
*
|
|
52
|
+
* The domain is length-prefixed (u32le, matching the project's LE
|
|
53
|
+
* convention) because bare `domain ‖ nonce` concatenation is boundary-
|
|
54
|
+
* ambiguous: ("rp.example.com", 00‖…) and ("rp.example.com\x00", …) would
|
|
55
|
+
* hash identically, letting a verifier with a prefix-compatible domain
|
|
56
|
+
* alias another verifier's challenge and replay a captured presentation.
|
|
57
|
+
*/
|
|
58
|
+
export function derivePresentationHeader(domain, nonce) {
|
|
59
|
+
if (!domain)
|
|
60
|
+
throw new BbsError('domain must be non-empty');
|
|
61
|
+
if (nonce.length < 16) {
|
|
62
|
+
throw new BbsError(`nonce must be ≥ 16 bytes, got ${nonce.length}`);
|
|
63
|
+
}
|
|
64
|
+
const tag = utf8(PH_DOMAIN_TAG);
|
|
65
|
+
const dom = utf8(domain);
|
|
66
|
+
const len = new Uint8Array(4);
|
|
67
|
+
new DataView(len.buffer).setUint32(0, dom.length, true);
|
|
68
|
+
const input = new Uint8Array(tag.length + 4 + dom.length + nonce.length);
|
|
69
|
+
input.set(tag, 0);
|
|
70
|
+
input.set(len, tag.length);
|
|
71
|
+
input.set(dom, tag.length + 4);
|
|
72
|
+
input.set(nonce, tag.length + 4 + dom.length);
|
|
73
|
+
return sha256(input);
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=v2.js.map
|
package/dist/v2.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v2.js","sourceRoot":"","sources":["../src/v2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAC7C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAE3C,qEAAqE;AACrE,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAA;AAEzC,gEAAgE;AAChE,MAAM,aAAa,GAAG,mBAAmB,CAAA;AAEzC;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAC3B,SAAiB,EACjB,cAAsB,EACtB,KAAa;IAEb,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,QAAQ,CAAC,6BAA6B,CAAC,CAAA;IACjE,IAAI,CAAC,cAAc;QAAE,MAAM,IAAI,QAAQ,CAAC,kCAAkC,CAAC,CAAA;IAC3E,IAAI,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,QAAQ,CAAC,qCAAqC,CAAC,CAAA;IAC3D,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,QAAQ,CAAC,6CAA6C,KAAK,EAAE,CAAC,CAAA;IAC1E,CAAC;IACD,OAAO,IAAI,CAAC,6BAA6B,SAAS,IAAI,cAAc,IAAI,KAAK,EAAE,CAAC,CAAA;AAClF,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAAc,EAAE,KAAiB;IACxE,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,QAAQ,CAAC,0BAA0B,CAAC,CAAA;IAC3D,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACtB,MAAM,IAAI,QAAQ,CAAC,iCAAiC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAA;IACrE,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,CAAA;IAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,CAAA;IACxB,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAA;IAC7B,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IACvD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAA;IACxE,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;IACjB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC1B,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAC9B,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAA;IAC7C,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;AACtB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidus-network/bbs",
|
|
3
|
-
"version": "0.6.
|
|
4
|
-
"description": "BBS+ selective-disclosure primitives for Solidus Network — IRTF draft-irtf-cfrg-bbs-signatures, BLS12-381 SHA-256. Byte-compatible with the Solidus chain (zkryptium-backed).",
|
|
3
|
+
"version": "0.6.2",
|
|
4
|
+
"description": "BBS+ selective-disclosure primitives for Solidus Network — IRTF draft-irtf-cfrg-bbs-signatures, BLS12-381 SHA-256 ciphersuite. Byte-compatible with the Solidus chain (zkryptium-backed).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -11,19 +11,37 @@
|
|
|
11
11
|
"types": "./dist/index.d.ts"
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
|
-
"files": [
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
15
19
|
"dependencies": {
|
|
16
|
-
"@digitalbazaar/bbs-signatures": "^3.0.0"
|
|
20
|
+
"@digitalbazaar/bbs-signatures": "^3.0.0",
|
|
21
|
+
"@noble/hashes": "^1.5.0"
|
|
17
22
|
},
|
|
18
|
-
"keywords": [
|
|
23
|
+
"keywords": [
|
|
24
|
+
"solidus",
|
|
25
|
+
"bbs",
|
|
26
|
+
"bbs+",
|
|
27
|
+
"selective-disclosure",
|
|
28
|
+
"verifiable-credentials",
|
|
29
|
+
"zero-knowledge",
|
|
30
|
+
"bls12-381",
|
|
31
|
+
"irtf"
|
|
32
|
+
],
|
|
19
33
|
"author": "Solidus Network (https://solidus.network)",
|
|
20
34
|
"license": "Apache-2.0",
|
|
21
35
|
"homepage": "https://solidus.network",
|
|
22
|
-
"bugs": {
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/solidusnetwork/sdk/issues"
|
|
38
|
+
},
|
|
23
39
|
"repository": {
|
|
24
40
|
"type": "git",
|
|
25
41
|
"url": "git+https://github.com/solidusnetwork/sdk.git",
|
|
26
42
|
"directory": "bbs"
|
|
27
43
|
},
|
|
28
|
-
"publishConfig": {
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
}
|
|
29
47
|
}
|