@nuggetslife/vc 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.toml +1 -0
- package/W3C_CONFORMANCE.md +9 -6
- package/bench/frame_compare.mjs +7 -20
- package/bench/v2_internals.mjs +3 -5
- package/bench/vc_ops.mjs +4 -10
- package/index.d.ts +2 -2
- package/interop-allowlist.json +3 -0
- package/interop-smoke-allowlist.json +3 -0
- package/package.json +8 -7
- package/src/bls_signatures/bbs_bls_holder_bound_signature_2022/mod.rs +18 -27
- package/src/bls_signatures/bbs_bls_holder_bound_signature_proof_2022/mod.rs +9 -10
- package/src/bls_signatures/bbs_bls_signature_2020/mod.rs +21 -25
- package/src/bls_signatures/bbs_bls_signature_proof_2020/mod.rs +6 -12
- package/src/jsonld.rs +40 -75
- package/src/ld_signatures.rs +210 -224
- package/src/lib.rs +8 -0
- package/test-fixtures/interop/README.md +46 -0
- package/test-fixtures/interop/_contexts/README.md +51 -0
- package/test-fixtures/interop/_contexts/bbs-bound-v1.jsonld +92 -0
- package/test-fixtures/interop/_contexts/citizenship-v1.jsonld +58 -0
- package/test-fixtures/interop/_contexts/credentials-v1.jsonld +316 -0
- package/test-fixtures/interop/_contexts/elm-edc-ap.jsonld +809 -0
- package/test-fixtures/interop/_contexts/essif-schemas-vc-2020-v1.jsonld +47 -0
- package/test-fixtures/interop/_contexts/identity-v2.jsonld +195 -0
- package/test-fixtures/interop/_contexts/nuggets-identity-v1.jsonld +175 -0
- package/test-fixtures/interop/_contexts/nuggets-kyb-v1.jsonld +333 -0
- package/test-fixtures/interop/_contexts/openbadges-v3.jsonld +445 -0
- package/test-fixtures/interop/_contexts/security-bbs-v1.jsonld +93 -0
- package/test-fixtures/interop/ebsi/diploma-elm/README.md +29 -0
- package/test-fixtures/interop/ebsi/diploma-elm/expected.nq +70 -0
- package/test-fixtures/interop/ebsi/diploma-elm/frame.jsonld +24 -0
- package/test-fixtures/interop/ebsi/diploma-elm/input.jsonld +444 -0
- package/test-fixtures/interop/ebsi/diploma-simple/README.md +19 -0
- package/test-fixtures/interop/ebsi/diploma-simple/expected.nq +9 -0
- package/test-fixtures/interop/ebsi/diploma-simple/frame.jsonld +13 -0
- package/test-fixtures/interop/ebsi/diploma-simple/input.jsonld +24 -0
- package/test-fixtures/interop/idv2/full-disclosure/README.md +9 -0
- package/test-fixtures/interop/idv2/full-disclosure/expected.nq +59 -0
- package/test-fixtures/interop/idv2/full-disclosure/frame.jsonld +9 -0
- package/test-fixtures/interop/idv2/full-disclosure/input.jsonld +82 -0
- package/test-fixtures/interop/nuggets/identity-v1/README.md +17 -0
- package/test-fixtures/interop/nuggets/identity-v1/expected.nq +21 -0
- package/test-fixtures/interop/nuggets/identity-v1/frame.jsonld +17 -0
- package/test-fixtures/interop/nuggets/identity-v1/input.jsonld +31 -0
- package/test-fixtures/interop/nuggets/kyb-v1/README.md +15 -0
- package/test-fixtures/interop/nuggets/kyb-v1/expected.nq +18 -0
- package/test-fixtures/interop/nuggets/kyb-v1/frame.jsonld +24 -0
- package/test-fixtures/interop/nuggets/kyb-v1/input.jsonld +60 -0
- package/test-fixtures/interop/openbadges-v3/basic-achievement/README.md +17 -0
- package/test-fixtures/interop/openbadges-v3/basic-achievement/expected.nq +12 -0
- package/test-fixtures/interop/openbadges-v3/basic-achievement/frame.jsonld +17 -0
- package/test-fixtures/interop/openbadges-v3/basic-achievement/input.jsonld +25 -0
- package/test-fixtures/interop/openbadges-v3/with-allowed-values/README.md +11 -0
- package/test-fixtures/interop/openbadges-v3/with-allowed-values/expected.nq +25 -0
- package/test-fixtures/interop/openbadges-v3/with-allowed-values/frame.jsonld +22 -0
- package/test-fixtures/interop/openbadges-v3/with-allowed-values/input.jsonld +40 -0
- package/test-fixtures/interop/vp/single-vc-wrap/README.md +6 -0
- package/test-fixtures/interop/vp/single-vc-wrap/expected.nq +7 -0
- package/test-fixtures/interop/vp/single-vc-wrap/frame.jsonld +17 -0
- package/test-fixtures/interop/vp/single-vc-wrap/input.jsonld +27 -0
- package/test-fixtures/interop/w3c-vc-v1/permanent-resident-card/README.md +5 -0
- package/test-fixtures/interop/w3c-vc-v1/permanent-resident-card/expected.nq +13 -0
- package/test-fixtures/interop/w3c-vc-v1/permanent-resident-card/frame.jsonld +14 -0
- package/test-fixtures/interop/w3c-vc-v1/permanent-resident-card/input.jsonld +29 -0
- package/test_interop.mjs +184 -0
- package/test_interop_smoke.mjs +388 -0
- package/test_w3c_conformance.mjs +7 -0
- package/tools/regen_expected.mjs +108 -0
- package/w3c-baseline.json +63 -74
- package/w3c-denylist.json +6 -1
package/Cargo.toml
CHANGED
|
@@ -13,6 +13,7 @@ bs58 = "0.5.1"
|
|
|
13
13
|
chrono = "0.4.38"
|
|
14
14
|
hex = "0.4.3"
|
|
15
15
|
lru = "0.14.0"
|
|
16
|
+
mimalloc = { version = "0.1", default-features = false }
|
|
16
17
|
# Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix
|
|
17
18
|
napi = { version = "2.16.10", default-features = false, features = ["full"] }
|
|
18
19
|
napi-derive = "2.16.12"
|
package/W3C_CONFORMANCE.md
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
# W3C Conformance Gate
|
|
2
2
|
|
|
3
3
|
The CI runs the W3C JSON-LD 1.1 API and RDF Dataset Canonicalization (RDFC-1.0)
|
|
4
|
-
test suites against the
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
test suites against the (sole) V2 JSON-LD path via `test_w3c_conformance.mjs`.
|
|
5
|
+
The job fails only when a test that **previously passed** starts failing —
|
|
6
|
+
never on tests that were already failing in the committed baseline.
|
|
7
|
+
|
|
8
|
+
Note: prior versions of this doc referenced `CLIENTFFI_JSONLD_V2=1`; the V1
|
|
9
|
+
JSON-LD pipeline was retired in v1.13.0 (Sprint 4 close-out) and that env
|
|
10
|
+
var is now a no-op.
|
|
8
11
|
|
|
9
12
|
## Files
|
|
10
13
|
|
|
@@ -22,12 +25,12 @@ committed baseline.
|
|
|
22
25
|
yarn fetch:w3c-tests
|
|
23
26
|
|
|
24
27
|
# Verify nothing has regressed vs baseline
|
|
25
|
-
|
|
28
|
+
yarn test:w3c
|
|
26
29
|
|
|
27
30
|
# Re-run the suite and overwrite the baseline. Add `--runs 3` for
|
|
28
31
|
# fast algos (canonize, fromRdf) to take the intersection of 3 runs
|
|
29
32
|
# and filter out flaky tests.
|
|
30
|
-
|
|
33
|
+
yarn test:w3c:update
|
|
31
34
|
```
|
|
32
35
|
|
|
33
36
|
## Adding a denylist entry
|
package/bench/frame_compare.mjs
CHANGED
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
// Head-to-head frame() bench: jsonld.js (Digital Bazaar reference) vs.
|
|
2
|
-
// the
|
|
2
|
+
// the Rust NAPI binding (V2 native typed-tree walker).
|
|
3
3
|
//
|
|
4
4
|
// Usage:
|
|
5
5
|
// node vc/js/bench/frame_compare.mjs # default 30w + 30t
|
|
6
6
|
// node vc/js/bench/frame_compare.mjs --warm 20 --timed 100
|
|
7
7
|
// node vc/js/bench/frame_compare.mjs --json
|
|
8
8
|
//
|
|
9
|
-
// Each backend runs in its own measurement loop. The
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
// Caveat: the env flags are read by `frame_native::use_native()` (cached
|
|
16
|
-
// via OnceLock) and inline `std::env::var` in the binding. We can't toggle
|
|
17
|
-
// them within a single Node process, so this script spawns a fresh child
|
|
18
|
-
// process per backend.
|
|
9
|
+
// Each backend runs in its own measurement loop. The legacy `frame_v2` /
|
|
10
|
+
// `frame_v2_fast` Rust variants were retired in Sprint 3 Phase D and the
|
|
11
|
+
// V1 JSON-LD pipeline (selected via `CLIENTFFI_JSONLD_V2=0` opt-out) was
|
|
12
|
+
// retired in Sprint 4 V1 retirement (v1.13.0); only the V2 native frame
|
|
13
|
+
// remains.
|
|
19
14
|
|
|
20
15
|
import { readFileSync, existsSync } from 'node:fs';
|
|
21
16
|
import { resolve, dirname, join } from 'node:path';
|
|
@@ -51,17 +46,9 @@ if (!backend) {
|
|
|
51
46
|
label: 'jsonld.js',
|
|
52
47
|
env: { BENCH_BACKEND: 'jsonld_js' },
|
|
53
48
|
},
|
|
54
|
-
{
|
|
55
|
-
label: 'frame_v2',
|
|
56
|
-
env: { BENCH_BACKEND: 'rust', CLIENTFFI_JSONLD_V2: '1' },
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
label: 'frame_v2_fast',
|
|
60
|
-
env: { BENCH_BACKEND: 'rust', CLIENTFFI_JSONLD_V2: '1', CLIENTFFI_FRAME_FAST: '1' },
|
|
61
|
-
},
|
|
62
49
|
{
|
|
63
50
|
label: 'frame_native',
|
|
64
|
-
env: { BENCH_BACKEND: 'rust'
|
|
51
|
+
env: { BENCH_BACKEND: 'rust' },
|
|
65
52
|
},
|
|
66
53
|
];
|
|
67
54
|
|
package/bench/v2_internals.mjs
CHANGED
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
// 166 KB IDv2 credential fixture. 30 warm + 30 timed samples per op.
|
|
3
3
|
//
|
|
4
4
|
// Usage:
|
|
5
|
-
// node vc/js/bench/v2_internals.mjs #
|
|
6
|
-
// CLIENTFFI_JSONLD_V2=1 node vc/js/bench/v2_internals.mjs # V2 (vendored crate pipeline)
|
|
5
|
+
// node vc/js/bench/v2_internals.mjs # default V2 pipeline
|
|
7
6
|
// node vc/js/bench/v2_internals.mjs --json # machine-readable output
|
|
8
7
|
// node vc/js/bench/v2_internals.mjs --only compact # restrict to one op
|
|
9
8
|
//
|
|
10
|
-
//
|
|
9
|
+
// V1 baseline variant retired in Sprint 4 V1 retirement (v1.13.0).
|
|
11
10
|
|
|
12
11
|
import { readFileSync, existsSync } from 'node:fs';
|
|
13
12
|
import { resolve, dirname, join } from 'node:path';
|
|
@@ -84,10 +83,9 @@ if (onlyArg && !ops[onlyArg]) {
|
|
|
84
83
|
process.exit(1);
|
|
85
84
|
}
|
|
86
85
|
|
|
87
|
-
const variant = process.env.CLIENTFFI_JSONLD_V2 ? 'V2' : 'V1';
|
|
88
86
|
const results = {
|
|
89
87
|
meta: {
|
|
90
|
-
variant,
|
|
88
|
+
variant: 'V2',
|
|
91
89
|
commit: gitSha,
|
|
92
90
|
fixture: idv2Json,
|
|
93
91
|
fixtureBytes: JSON.stringify(big).length,
|
package/bench/vc_ops.mjs
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
// End-to-end BBS+ verifiable credential ops bench.
|
|
2
2
|
//
|
|
3
3
|
// Times the full sign → verify → derive_proof → verify_derived flow for two
|
|
4
|
-
// fixtures
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// v1 : default (V1 jsonld pipeline)
|
|
9
|
-
// v2 : CLIENTFFI_JSONLD_V2=1 (V2 pipeline, frame_v2)
|
|
10
|
-
// v2_native : CLIENTFFI_JSONLD_V2=1 + CLIENTFFI_FRAME_NATIVE=1
|
|
4
|
+
// fixtures across the Rust V2 pipeline (jsonld.js reference for comparison).
|
|
5
|
+
// V1 + intermediate frame_v2 / frame_v2_fast variants were retired in
|
|
6
|
+
// Sprint 4 V1 retirement (v1.13.0).
|
|
11
7
|
//
|
|
12
8
|
// Usage:
|
|
13
9
|
// node vc/js/bench/vc_ops.mjs
|
|
@@ -38,9 +34,7 @@ if (!backend) {
|
|
|
38
34
|
// Driver: spawn child per pipeline config.
|
|
39
35
|
const configs = [
|
|
40
36
|
{ label: 'js_ref', env: { BENCH_PIPELINE: 'js' } },
|
|
41
|
-
{ label: '
|
|
42
|
-
{ label: 'v2', env: { CLIENTFFI_JSONLD_V2: '1' } },
|
|
43
|
-
{ label: 'v2_native', env: { CLIENTFFI_JSONLD_V2: '1', CLIENTFFI_FRAME_NATIVE: '1' } },
|
|
37
|
+
{ label: 'v2_native', env: {} },
|
|
44
38
|
];
|
|
45
39
|
|
|
46
40
|
const allResults = [];
|
package/index.d.ts
CHANGED
|
@@ -500,8 +500,8 @@ export declare class BoundBls12381G2KeyPair {
|
|
|
500
500
|
/**
|
|
501
501
|
* JSON-LD processor — drop-in replacement for the jsonld.js API.
|
|
502
502
|
*
|
|
503
|
-
* Holds a `DocumentLoader`
|
|
504
|
-
*
|
|
503
|
+
* Holds a `DocumentLoader` internally so it is created once and reused
|
|
504
|
+
* across all method calls.
|
|
505
505
|
*
|
|
506
506
|
* ```js
|
|
507
507
|
* const jsonld = new JsonLd({ contexts: { "https://example.org/ctx": {...} } });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuggetslife/vc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"types": "index.d.ts",
|
|
6
6
|
"napi": {
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
"@mattrglobal/jsonld-signatures-bbs": "^1.2.0",
|
|
23
23
|
"@napi-rs/cli": "^2.18.3",
|
|
24
24
|
"@types/node": "^20.14.9",
|
|
25
|
-
"jsonld": "^8.3.3"
|
|
25
|
+
"jsonld": "^8.3.3",
|
|
26
|
+
"jsonld-signatures": "^7.0.0"
|
|
26
27
|
},
|
|
27
28
|
"engines": {
|
|
28
29
|
"node": ">= 10"
|
|
@@ -41,11 +42,11 @@
|
|
|
41
42
|
},
|
|
42
43
|
"packageManager": "yarn@4.3.1",
|
|
43
44
|
"optionalDependencies": {
|
|
44
|
-
"@nuggetslife/vc-darwin-arm64": "0.
|
|
45
|
-
"@nuggetslife/vc-linux-arm64-gnu": "0.
|
|
46
|
-
"@nuggetslife/vc-linux-arm64-musl": "0.
|
|
47
|
-
"@nuggetslife/vc-linux-x64-gnu": "0.
|
|
48
|
-
"@nuggetslife/vc-linux-x64-musl": "0.
|
|
45
|
+
"@nuggetslife/vc-darwin-arm64": "0.3.0",
|
|
46
|
+
"@nuggetslife/vc-linux-arm64-gnu": "0.3.0",
|
|
47
|
+
"@nuggetslife/vc-linux-arm64-musl": "0.3.0",
|
|
48
|
+
"@nuggetslife/vc-linux-x64-gnu": "0.3.0",
|
|
49
|
+
"@nuggetslife/vc-linux-x64-musl": "0.3.0"
|
|
49
50
|
},
|
|
50
51
|
"dependencies": {}
|
|
51
52
|
}
|
|
@@ -29,14 +29,14 @@ impl BbsBlsHolderBoundSignature2022 {
|
|
|
29
29
|
match options {
|
|
30
30
|
Some(opts) => {
|
|
31
31
|
let key = match opts.key {
|
|
32
|
-
Some(kp_opts) =>
|
|
33
|
-
super::bls_12381_g2_keypair::types::KeyPairOptions {
|
|
32
|
+
Some(kp_opts) => {
|
|
33
|
+
Bls12381G2KeyPair::new(Some(super::bls_12381_g2_keypair::types::KeyPairOptions {
|
|
34
34
|
id: kp_opts.id,
|
|
35
35
|
controller: kp_opts.controller,
|
|
36
36
|
public_key_base58: kp_opts.public_key_base58,
|
|
37
37
|
private_key_base58: kp_opts.private_key_base58,
|
|
38
|
-
}
|
|
39
|
-
|
|
38
|
+
}))
|
|
39
|
+
}
|
|
40
40
|
None => Bls12381G2KeyPair::new(None),
|
|
41
41
|
};
|
|
42
42
|
|
|
@@ -80,7 +80,7 @@ impl BbsBlsHolderBoundSignature2022 {
|
|
|
80
80
|
&self,
|
|
81
81
|
options: BoundCreateProofOptions,
|
|
82
82
|
) -> Result<serde_json::Value> {
|
|
83
|
-
let
|
|
83
|
+
let loader = loader_from_contexts(options.contexts.as_ref());
|
|
84
84
|
|
|
85
85
|
let rust_key = napi_key_to_rust_key(&self.key);
|
|
86
86
|
|
|
@@ -102,7 +102,7 @@ impl BbsBlsHolderBoundSignature2022 {
|
|
|
102
102
|
|
|
103
103
|
let purpose = vc::jsonld::signatures::AssertionProofPurpose::new();
|
|
104
104
|
suite
|
|
105
|
-
.create_blind_sign_commitment_context(&options.document, &purpose, loader
|
|
105
|
+
.create_blind_sign_commitment_context(&options.document, &purpose, loader)
|
|
106
106
|
.await
|
|
107
107
|
.map_err(|e| {
|
|
108
108
|
napi::Error::from_reason(format!("createBlindSignCommitmentContext failed: {e}"))
|
|
@@ -111,11 +111,8 @@ impl BbsBlsHolderBoundSignature2022 {
|
|
|
111
111
|
|
|
112
112
|
/// Create a proof for a document using BbsBlsHolderBoundSignature2022 (blind signing).
|
|
113
113
|
#[napi]
|
|
114
|
-
pub async fn create_proof(
|
|
115
|
-
|
|
116
|
-
options: BoundCreateProofOptions,
|
|
117
|
-
) -> Result<serde_json::Value> {
|
|
118
|
-
let (loader, cr) = loader_from_contexts(options.contexts.as_ref());
|
|
114
|
+
pub async fn create_proof(&self, options: BoundCreateProofOptions) -> Result<serde_json::Value> {
|
|
115
|
+
let loader = loader_from_contexts(options.contexts.as_ref());
|
|
119
116
|
|
|
120
117
|
let commitment = self
|
|
121
118
|
.commitment
|
|
@@ -145,7 +142,7 @@ impl BbsBlsHolderBoundSignature2022 {
|
|
|
145
142
|
|
|
146
143
|
let purpose = vc::jsonld::signatures::AssertionProofPurpose::new();
|
|
147
144
|
let signed =
|
|
148
|
-
vc::jsonld::signatures::sign_holder_bound(options.document, &suite, &purpose, loader
|
|
145
|
+
vc::jsonld::signatures::sign_holder_bound(options.document, &suite, &purpose, loader)
|
|
149
146
|
.await
|
|
150
147
|
.map_err(|e| napi::Error::from_reason(format!("createProof failed: {e}")))?;
|
|
151
148
|
|
|
@@ -159,15 +156,15 @@ impl BbsBlsHolderBoundSignature2022 {
|
|
|
159
156
|
///
|
|
160
157
|
/// Returns `{ verified: boolean, error?: string }`.
|
|
161
158
|
#[napi]
|
|
162
|
-
pub async fn verify_proof(
|
|
163
|
-
|
|
164
|
-
options: BoundVerifyProofOptions,
|
|
165
|
-
) -> Result<serde_json::Value> {
|
|
166
|
-
let (loader, cr) = loader_from_contexts(options.contexts.as_ref());
|
|
159
|
+
pub async fn verify_proof(&self, options: BoundVerifyProofOptions) -> Result<serde_json::Value> {
|
|
160
|
+
let loader = loader_from_contexts(options.contexts.as_ref());
|
|
167
161
|
|
|
168
162
|
let blinding_factor = options.blinding_factor.to_vec();
|
|
169
|
-
let blinded_messages: Vec<Vec<u8>> =
|
|
170
|
-
|
|
163
|
+
let blinded_messages: Vec<Vec<u8>> = options
|
|
164
|
+
.blinded_messages
|
|
165
|
+
.iter()
|
|
166
|
+
.map(|m| m.to_vec())
|
|
167
|
+
.collect();
|
|
171
168
|
|
|
172
169
|
let purpose = vc::jsonld::signatures::AssertionProofPurpose::new();
|
|
173
170
|
let result = vc::jsonld::signatures::verify_holder_bound(
|
|
@@ -176,7 +173,6 @@ impl BbsBlsHolderBoundSignature2022 {
|
|
|
176
173
|
blinded_messages,
|
|
177
174
|
&purpose,
|
|
178
175
|
loader,
|
|
179
|
-
cr,
|
|
180
176
|
)
|
|
181
177
|
.await
|
|
182
178
|
.map_err(|e| napi::Error::from_reason(format!("verifyProof failed: {e}")))?;
|
|
@@ -189,18 +185,13 @@ impl BbsBlsHolderBoundSignature2022 {
|
|
|
189
185
|
|
|
190
186
|
/// Ensure both BBS and holder-bound suite contexts are present.
|
|
191
187
|
#[napi]
|
|
192
|
-
pub fn ensure_suite_context(
|
|
193
|
-
&self,
|
|
194
|
-
document: serde_json::Value,
|
|
195
|
-
) -> Result<serde_json::Value> {
|
|
188
|
+
pub fn ensure_suite_context(&self, document: serde_json::Value) -> Result<serde_json::Value> {
|
|
196
189
|
let mut doc = document;
|
|
197
190
|
|
|
198
191
|
for context_url in &[BBS_CONTEXT_URL, BBS_BOUND_CONTEXT_URL] {
|
|
199
192
|
let has_context = match doc.get("@context") {
|
|
200
193
|
Some(serde_json::Value::String(s)) => s == *context_url,
|
|
201
|
-
Some(serde_json::Value::Array(arr)) =>
|
|
202
|
-
arr.iter().any(|v| v.as_str() == Some(*context_url))
|
|
203
|
-
}
|
|
194
|
+
Some(serde_json::Value::Array(arr)) => arr.iter().any(|v| v.as_str() == Some(*context_url)),
|
|
204
195
|
_ => false,
|
|
205
196
|
};
|
|
206
197
|
|
|
@@ -23,15 +23,15 @@ impl BbsBlsHolderBoundSignatureProof2022 {
|
|
|
23
23
|
|
|
24
24
|
/// Derive a selective disclosure proof from a holder-bound signed document.
|
|
25
25
|
#[napi]
|
|
26
|
-
pub async fn derive_proof(
|
|
27
|
-
|
|
28
|
-
options: BoundDeriveProofOptions,
|
|
29
|
-
) -> Result<serde_json::Value> {
|
|
30
|
-
let (loader, cr) = loader_from_contexts(options.contexts.as_ref());
|
|
26
|
+
pub async fn derive_proof(&self, options: BoundDeriveProofOptions) -> Result<serde_json::Value> {
|
|
27
|
+
let loader = loader_from_contexts(options.contexts.as_ref());
|
|
31
28
|
|
|
32
29
|
let blinding_factor = options.blinding_factor.to_vec();
|
|
33
|
-
let blinded_messages: Vec<Vec<u8>> =
|
|
34
|
-
|
|
30
|
+
let blinded_messages: Vec<Vec<u8>> = options
|
|
31
|
+
.blinded_messages
|
|
32
|
+
.iter()
|
|
33
|
+
.map(|m| m.to_vec())
|
|
34
|
+
.collect();
|
|
35
35
|
let nonce = options.nonce.map(|s| s.as_bytes().to_vec());
|
|
36
36
|
|
|
37
37
|
vc::jsonld::signatures::derive_proof_holder_bound(
|
|
@@ -41,7 +41,6 @@ impl BbsBlsHolderBoundSignatureProof2022 {
|
|
|
41
41
|
blinded_messages,
|
|
42
42
|
nonce,
|
|
43
43
|
loader,
|
|
44
|
-
cr,
|
|
45
44
|
)
|
|
46
45
|
.await
|
|
47
46
|
.map_err(|e| napi::Error::from_reason(format!("deriveProof failed: {e}")))
|
|
@@ -55,10 +54,10 @@ impl BbsBlsHolderBoundSignatureProof2022 {
|
|
|
55
54
|
&self,
|
|
56
55
|
options: BoundVerifyDerivedProofOptions,
|
|
57
56
|
) -> Result<serde_json::Value> {
|
|
58
|
-
let
|
|
57
|
+
let loader = loader_from_contexts(options.contexts.as_ref());
|
|
59
58
|
|
|
60
59
|
let purpose = vc::jsonld::signatures::AssertionProofPurpose::new();
|
|
61
|
-
let result = vc::jsonld::signatures::verify(&options.document, &purpose, loader
|
|
60
|
+
let result = vc::jsonld::signatures::verify(&options.document, &purpose, loader)
|
|
62
61
|
.await
|
|
63
62
|
.map_err(|e| napi::Error::from_reason(format!("verifyProof failed: {e}")))?;
|
|
64
63
|
|
|
@@ -63,14 +63,14 @@ impl BbsBlsSignature2020 {
|
|
|
63
63
|
match options {
|
|
64
64
|
Some(opts) => {
|
|
65
65
|
let key = match opts.key {
|
|
66
|
-
Some(kp_opts) =>
|
|
67
|
-
super::bls_12381_g2_keypair::types::KeyPairOptions {
|
|
66
|
+
Some(kp_opts) => {
|
|
67
|
+
Bls12381G2KeyPair::new(Some(super::bls_12381_g2_keypair::types::KeyPairOptions {
|
|
68
68
|
id: kp_opts.id,
|
|
69
69
|
controller: kp_opts.controller,
|
|
70
70
|
public_key_base58: kp_opts.public_key_base58,
|
|
71
71
|
private_key_base58: kp_opts.private_key_base58,
|
|
72
|
-
}
|
|
73
|
-
|
|
72
|
+
}))
|
|
73
|
+
}
|
|
74
74
|
None => Bls12381G2KeyPair::new(None),
|
|
75
75
|
};
|
|
76
76
|
|
|
@@ -116,15 +116,13 @@ impl BbsBlsSignature2020 {
|
|
|
116
116
|
/// Generate a BbsBlsSignature2020 suite from a seed (async key generation).
|
|
117
117
|
#[napi(factory)]
|
|
118
118
|
pub async fn generate(options: SignatureSuiteOptions) -> Self {
|
|
119
|
-
let key = Bls12381G2KeyPair::generate(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}),
|
|
127
|
-
)
|
|
119
|
+
let key = Bls12381G2KeyPair::generate(options.key.map(|kp| {
|
|
120
|
+
super::bls_12381_g2_keypair::types::GenerateKeyPairOptions {
|
|
121
|
+
id: kp.id,
|
|
122
|
+
controller: kp.controller,
|
|
123
|
+
seed: kp.private_key_base58.map(|s| s.into_bytes().into()),
|
|
124
|
+
}
|
|
125
|
+
}))
|
|
128
126
|
.await;
|
|
129
127
|
|
|
130
128
|
let proof = json!({
|
|
@@ -165,7 +163,7 @@ impl BbsBlsSignature2020 {
|
|
|
165
163
|
/// Returns just the proof object (matching JS reference behavior).
|
|
166
164
|
#[napi]
|
|
167
165
|
pub async fn create_proof(&self, options: CreateProofOptions) -> Result<serde_json::Value> {
|
|
168
|
-
let
|
|
166
|
+
let loader = loader_from_contexts(options.contexts.as_ref());
|
|
169
167
|
|
|
170
168
|
let rust_key = napi_key_to_rust_key(&self.key);
|
|
171
169
|
let suite = vc::jsonld::signatures::bbs::BbsBlsSignature2020::new(
|
|
@@ -179,7 +177,7 @@ impl BbsBlsSignature2020 {
|
|
|
179
177
|
.await;
|
|
180
178
|
|
|
181
179
|
let purpose = vc::jsonld::signatures::AssertionProofPurpose::new();
|
|
182
|
-
let signed = vc::jsonld::signatures::sign(options.document, &suite, &purpose, loader
|
|
180
|
+
let signed = vc::jsonld::signatures::sign(options.document, &suite, &purpose, loader)
|
|
183
181
|
.await
|
|
184
182
|
.map_err(|e| napi::Error::from_reason(format!("createProof failed: {e}")))?;
|
|
185
183
|
|
|
@@ -194,10 +192,10 @@ impl BbsBlsSignature2020 {
|
|
|
194
192
|
/// Returns `{ verified: boolean, error?: string }`.
|
|
195
193
|
#[napi]
|
|
196
194
|
pub async fn verify_proof(&self, options: VerifyProofOptions) -> Result<serde_json::Value> {
|
|
197
|
-
let
|
|
195
|
+
let loader = loader_from_contexts(options.contexts.as_ref());
|
|
198
196
|
|
|
199
197
|
let purpose = vc::jsonld::signatures::AssertionProofPurpose::new();
|
|
200
|
-
let result = vc::jsonld::signatures::verify(&options.document, &purpose, loader
|
|
198
|
+
let result = vc::jsonld::signatures::verify(&options.document, &purpose, loader)
|
|
201
199
|
.await
|
|
202
200
|
.map_err(|e| napi::Error::from_reason(format!("verifyProof failed: {e}")))?;
|
|
203
201
|
|
|
@@ -209,25 +207,23 @@ impl BbsBlsSignature2020 {
|
|
|
209
207
|
|
|
210
208
|
/// Ensure the BBS suite context is present in the document's @context.
|
|
211
209
|
#[napi]
|
|
212
|
-
pub fn ensure_suite_context(
|
|
213
|
-
&self,
|
|
214
|
-
document: serde_json::Value,
|
|
215
|
-
) -> Result<serde_json::Value> {
|
|
210
|
+
pub fn ensure_suite_context(&self, document: serde_json::Value) -> Result<serde_json::Value> {
|
|
216
211
|
let bbs_context = "https://w3id.org/security/bbs/v1";
|
|
217
212
|
let mut doc = document;
|
|
218
213
|
|
|
219
214
|
// Check if already present
|
|
220
215
|
let has_context = match doc.get("@context") {
|
|
221
216
|
Some(serde_json::Value::String(s)) => s == bbs_context,
|
|
222
|
-
Some(serde_json::Value::Array(arr)) =>
|
|
223
|
-
arr.iter().any(|v| v.as_str() == Some(bbs_context))
|
|
224
|
-
}
|
|
217
|
+
Some(serde_json::Value::Array(arr)) => arr.iter().any(|v| v.as_str() == Some(bbs_context)),
|
|
225
218
|
_ => false,
|
|
226
219
|
};
|
|
227
220
|
|
|
228
221
|
if !has_context {
|
|
229
222
|
if let Some(obj) = doc.as_object_mut() {
|
|
230
|
-
let existing = obj
|
|
223
|
+
let existing = obj
|
|
224
|
+
.get("@context")
|
|
225
|
+
.cloned()
|
|
226
|
+
.unwrap_or(serde_json::Value::Null);
|
|
231
227
|
let mut new_context = match existing {
|
|
232
228
|
serde_json::Value::Array(arr) => serde_json::Value::Array(arr),
|
|
233
229
|
other => serde_json::Value::Array(vec![other]),
|
|
@@ -24,19 +24,13 @@ impl BbsBlsSignatureProof2020 {
|
|
|
24
24
|
/// Derive a selective disclosure proof from a signed document.
|
|
25
25
|
#[napi]
|
|
26
26
|
pub async fn derive_proof(&self, options: DeriveProofOptions) -> Result<serde_json::Value> {
|
|
27
|
-
let
|
|
27
|
+
let loader = loader_from_contexts(options.contexts.as_ref());
|
|
28
28
|
|
|
29
29
|
let nonce = options.nonce.map(|s| s.as_bytes().to_vec());
|
|
30
30
|
|
|
31
|
-
vc::jsonld::signatures::derive_proof(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
nonce,
|
|
35
|
-
loader,
|
|
36
|
-
cr,
|
|
37
|
-
)
|
|
38
|
-
.await
|
|
39
|
-
.map_err(|e| napi::Error::from_reason(format!("deriveProof failed: {e}")))
|
|
31
|
+
vc::jsonld::signatures::derive_proof(&options.document, &options.reveal_document, nonce, loader)
|
|
32
|
+
.await
|
|
33
|
+
.map_err(|e| napi::Error::from_reason(format!("deriveProof failed: {e}")))
|
|
40
34
|
}
|
|
41
35
|
|
|
42
36
|
/// Verify a derived (selective disclosure) proof.
|
|
@@ -47,10 +41,10 @@ impl BbsBlsSignatureProof2020 {
|
|
|
47
41
|
&self,
|
|
48
42
|
options: VerifyDerivedProofOptions,
|
|
49
43
|
) -> Result<serde_json::Value> {
|
|
50
|
-
let
|
|
44
|
+
let loader = loader_from_contexts(options.contexts.as_ref());
|
|
51
45
|
|
|
52
46
|
let purpose = vc::jsonld::signatures::AssertionProofPurpose::new();
|
|
53
|
-
let result = vc::jsonld::signatures::verify(&options.document, &purpose, loader
|
|
47
|
+
let result = vc::jsonld::signatures::verify(&options.document, &purpose, loader)
|
|
54
48
|
.await
|
|
55
49
|
.map_err(|e| napi::Error::from_reason(format!("verifyProof failed: {e}")))?;
|
|
56
50
|
|