@nuggetslife/vc 0.0.21 → 0.0.24
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/generate_golden_files.mjs +181 -0
- package/index.d.ts +154 -0
- package/index.js +27 -1
- package/package.json +8 -11
- package/src/bbs_2023.rs +71 -0
- package/src/bbs_ietf.rs +255 -0
- package/src/bls_signatures/bbs_bls_holder_bound_signature_2022/mod.rs +7 -38
- package/src/bls_signatures/bbs_bls_holder_bound_signature_proof_2022/mod.rs +3 -13
- package/src/bls_signatures/bbs_bls_signature_2020/mod.rs +4 -34
- package/src/bls_signatures/bbs_bls_signature_2020/types.rs +0 -1
- package/src/bls_signatures/bbs_bls_signature_proof_2020/mod.rs +3 -13
- package/src/bls_signatures/bls_12381_g2_keypair/mod.rs +16 -16
- package/src/bls_signatures/bound_bls_12381_g2_keypair/mod.rs +3 -3
- package/src/jose.rs +415 -0
- package/src/jsonld.rs +4 -26
- package/src/ld_signatures.rs +29 -24
- package/src/lib.rs +4 -0
- package/src/sd_jwt.rs +133 -0
- package/test-data/golden/inputDocument-minimal.json +17 -0
- package/test-data/golden/inputDocument-rich.json +29 -0
- package/test-data/golden/mattrglobal-derived-prc.json +36 -0
- package/test-data/golden/mattrglobal-signed-minimal.json +30 -0
- package/test-data/golden/mattrglobal-signed-prc.json +42 -0
- package/test-data/golden/mattrglobal-signed-rich.json +42 -0
- package/test.mjs +38 -0
- package/test_backward_compat.mjs +287 -0
- package/test_bbs_2023.mjs +195 -0
- package/test_bbs_ietf.mjs +168 -0
- package/test_fuzz.mjs +202 -0
- package/test_jose.mjs +497 -0
- package/test_jsonld_crossverify.mjs +1 -1
- package/test_sd_jwt.mjs +197 -0
package/src/bbs_ietf.rs
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
use napi::bindgen_prelude::Buffer;
|
|
2
|
+
use serde_json::Value;
|
|
3
|
+
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Result types
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
#[napi(object)]
|
|
9
|
+
pub struct BbsIetfKeyPair {
|
|
10
|
+
/// Hex-encoded secret key (32 bytes)
|
|
11
|
+
pub secret_key: String,
|
|
12
|
+
/// Hex-encoded public key (96 bytes, compressed G2)
|
|
13
|
+
pub public_key: String,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Key Generation
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
#[napi(js_name = "bbsIetfKeygen")]
|
|
21
|
+
pub fn bbs_ietf_keygen(
|
|
22
|
+
ikm: Option<Buffer>,
|
|
23
|
+
key_info: Option<Buffer>,
|
|
24
|
+
ciphersuite: Option<String>,
|
|
25
|
+
) -> napi::Result<BbsIetfKeyPair> {
|
|
26
|
+
let ikm_bytes = ikm.as_deref();
|
|
27
|
+
let key_info_bytes = key_info.as_deref().unwrap_or(&[]);
|
|
28
|
+
let cs = ciphersuite.as_deref().unwrap_or("SHA-256");
|
|
29
|
+
|
|
30
|
+
let kp = match cs {
|
|
31
|
+
"SHAKE-256" => vc::bbs_ietf::keygen::<vc::bbs_ietf::Bls12381Shake256>(
|
|
32
|
+
ikm_bytes,
|
|
33
|
+
key_info_bytes,
|
|
34
|
+
),
|
|
35
|
+
_ => vc::bbs_ietf::keygen::<vc::bbs_ietf::Bls12381Sha256>(
|
|
36
|
+
ikm_bytes,
|
|
37
|
+
key_info_bytes,
|
|
38
|
+
),
|
|
39
|
+
}
|
|
40
|
+
.map_err(|e| napi::Error::from_reason(format!("bbsIetfKeygen: {e}")))?;
|
|
41
|
+
|
|
42
|
+
Ok(BbsIetfKeyPair {
|
|
43
|
+
secret_key: hex::encode(vc::bbs_ietf::serialize::scalar_to_bytes(&kp.secret_key.0)),
|
|
44
|
+
public_key: hex::encode(vc::bbs_ietf::serialize::point_to_octets_g2(&kp.public_key.0)),
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// Sign
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
#[napi(js_name = "bbsIetfSign")]
|
|
53
|
+
pub fn bbs_ietf_sign(
|
|
54
|
+
secret_key: Buffer,
|
|
55
|
+
public_key: Buffer,
|
|
56
|
+
header: Option<Buffer>,
|
|
57
|
+
messages: Vec<String>,
|
|
58
|
+
ciphersuite: Option<String>,
|
|
59
|
+
) -> napi::Result<Buffer> {
|
|
60
|
+
let sk = vc::bbs_ietf::serialize::bytes_to_scalar(&secret_key)
|
|
61
|
+
.map_err(|e| napi::Error::from_reason(format!("bbsIetfSign invalid SK: {e}")))?;
|
|
62
|
+
let pk_point = vc::bbs_ietf::serialize::octets_to_point_g2(&public_key)
|
|
63
|
+
.map_err(|e| napi::Error::from_reason(format!("bbsIetfSign invalid PK: {e}")))?;
|
|
64
|
+
|
|
65
|
+
let header = header.as_deref().unwrap_or(&[]);
|
|
66
|
+
let cs = ciphersuite.as_deref().unwrap_or("SHA-256");
|
|
67
|
+
|
|
68
|
+
let sk = vc::bbs_ietf::SecretKey(sk);
|
|
69
|
+
let pk = vc::bbs_ietf::PublicKey(pk_point);
|
|
70
|
+
|
|
71
|
+
let sig = match cs {
|
|
72
|
+
"SHAKE-256" => {
|
|
73
|
+
let scalars: Vec<_> = messages
|
|
74
|
+
.iter()
|
|
75
|
+
.map(|m| vc::bbs_ietf::map_message_to_scalar::<vc::bbs_ietf::Bls12381Shake256>(m.as_bytes()))
|
|
76
|
+
.collect();
|
|
77
|
+
vc::bbs_ietf::sign::<vc::bbs_ietf::Bls12381Shake256>(&sk, &pk, header, &scalars)
|
|
78
|
+
}
|
|
79
|
+
_ => {
|
|
80
|
+
let scalars: Vec<_> = messages
|
|
81
|
+
.iter()
|
|
82
|
+
.map(|m| vc::bbs_ietf::map_message_to_scalar::<vc::bbs_ietf::Bls12381Sha256>(m.as_bytes()))
|
|
83
|
+
.collect();
|
|
84
|
+
vc::bbs_ietf::sign::<vc::bbs_ietf::Bls12381Sha256>(&sk, &pk, header, &scalars)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
.map_err(|e| napi::Error::from_reason(format!("bbsIetfSign: {e}")))?;
|
|
88
|
+
|
|
89
|
+
let bytes = vc::bbs_ietf::serialize_signature(&sig);
|
|
90
|
+
Ok(Buffer::from(bytes.to_vec()))
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
// Verify
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
|
|
97
|
+
#[napi(js_name = "bbsIetfVerify")]
|
|
98
|
+
pub fn bbs_ietf_verify(
|
|
99
|
+
public_key: Buffer,
|
|
100
|
+
signature: Buffer,
|
|
101
|
+
header: Option<Buffer>,
|
|
102
|
+
messages: Vec<String>,
|
|
103
|
+
ciphersuite: Option<String>,
|
|
104
|
+
) -> napi::Result<bool> {
|
|
105
|
+
let pk_point = vc::bbs_ietf::serialize::octets_to_point_g2(&public_key)
|
|
106
|
+
.map_err(|e| napi::Error::from_reason(format!("bbsIetfVerify invalid PK: {e}")))?;
|
|
107
|
+
let sig = vc::bbs_ietf::deserialize_signature(&signature)
|
|
108
|
+
.map_err(|e| napi::Error::from_reason(format!("bbsIetfVerify invalid sig: {e}")))?;
|
|
109
|
+
|
|
110
|
+
let header = header.as_deref().unwrap_or(&[]);
|
|
111
|
+
let cs = ciphersuite.as_deref().unwrap_or("SHA-256");
|
|
112
|
+
let pk = vc::bbs_ietf::PublicKey(pk_point);
|
|
113
|
+
|
|
114
|
+
match cs {
|
|
115
|
+
"SHAKE-256" => {
|
|
116
|
+
let scalars: Vec<_> = messages
|
|
117
|
+
.iter()
|
|
118
|
+
.map(|m| vc::bbs_ietf::map_message_to_scalar::<vc::bbs_ietf::Bls12381Shake256>(m.as_bytes()))
|
|
119
|
+
.collect();
|
|
120
|
+
vc::bbs_ietf::verify::<vc::bbs_ietf::Bls12381Shake256>(&pk, &sig, header, &scalars)
|
|
121
|
+
}
|
|
122
|
+
_ => {
|
|
123
|
+
let scalars: Vec<_> = messages
|
|
124
|
+
.iter()
|
|
125
|
+
.map(|m| vc::bbs_ietf::map_message_to_scalar::<vc::bbs_ietf::Bls12381Sha256>(m.as_bytes()))
|
|
126
|
+
.collect();
|
|
127
|
+
vc::bbs_ietf::verify::<vc::bbs_ietf::Bls12381Sha256>(&pk, &sig, header, &scalars)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
.map_err(|e| napi::Error::from_reason(format!("bbsIetfVerify: {e}")))
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
// ProofGen
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
|
|
137
|
+
#[napi(js_name = "bbsIetfProofGen")]
|
|
138
|
+
pub fn bbs_ietf_proof_gen(
|
|
139
|
+
public_key: Buffer,
|
|
140
|
+
signature: Buffer,
|
|
141
|
+
header: Option<Buffer>,
|
|
142
|
+
presentation_header: Option<Buffer>,
|
|
143
|
+
messages: Vec<String>,
|
|
144
|
+
disclosed_indices: Vec<u32>,
|
|
145
|
+
ciphersuite: Option<String>,
|
|
146
|
+
) -> napi::Result<Buffer> {
|
|
147
|
+
let pk_point = vc::bbs_ietf::serialize::octets_to_point_g2(&public_key)
|
|
148
|
+
.map_err(|e| napi::Error::from_reason(format!("bbsIetfProofGen invalid PK: {e}")))?;
|
|
149
|
+
let sig = vc::bbs_ietf::deserialize_signature(&signature)
|
|
150
|
+
.map_err(|e| napi::Error::from_reason(format!("bbsIetfProofGen invalid sig: {e}")))?;
|
|
151
|
+
|
|
152
|
+
let header = header.as_deref().unwrap_or(&[]);
|
|
153
|
+
let ph = presentation_header.as_deref().unwrap_or(&[]);
|
|
154
|
+
let cs = ciphersuite.as_deref().unwrap_or("SHA-256");
|
|
155
|
+
let indices: Vec<usize> = disclosed_indices.iter().map(|&i| i as usize).collect();
|
|
156
|
+
let pk = vc::bbs_ietf::PublicKey(pk_point);
|
|
157
|
+
|
|
158
|
+
let proof = match cs {
|
|
159
|
+
"SHAKE-256" => {
|
|
160
|
+
let scalars: Vec<_> = messages
|
|
161
|
+
.iter()
|
|
162
|
+
.map(|m| vc::bbs_ietf::map_message_to_scalar::<vc::bbs_ietf::Bls12381Shake256>(m.as_bytes()))
|
|
163
|
+
.collect();
|
|
164
|
+
vc::bbs_ietf::proof_gen::<vc::bbs_ietf::Bls12381Shake256>(
|
|
165
|
+
&pk, &sig, header, ph, &scalars, &indices,
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
_ => {
|
|
169
|
+
let scalars: Vec<_> = messages
|
|
170
|
+
.iter()
|
|
171
|
+
.map(|m| vc::bbs_ietf::map_message_to_scalar::<vc::bbs_ietf::Bls12381Sha256>(m.as_bytes()))
|
|
172
|
+
.collect();
|
|
173
|
+
vc::bbs_ietf::proof_gen::<vc::bbs_ietf::Bls12381Sha256>(
|
|
174
|
+
&pk, &sig, header, ph, &scalars, &indices,
|
|
175
|
+
)
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
.map_err(|e| napi::Error::from_reason(format!("bbsIetfProofGen: {e}")))?;
|
|
179
|
+
|
|
180
|
+
Ok(Buffer::from(proof))
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// ---------------------------------------------------------------------------
|
|
184
|
+
// ProofVerify
|
|
185
|
+
// ---------------------------------------------------------------------------
|
|
186
|
+
|
|
187
|
+
#[napi(js_name = "bbsIetfProofVerify")]
|
|
188
|
+
pub fn bbs_ietf_proof_verify(
|
|
189
|
+
public_key: Buffer,
|
|
190
|
+
proof: Buffer,
|
|
191
|
+
header: Option<Buffer>,
|
|
192
|
+
presentation_header: Option<Buffer>,
|
|
193
|
+
disclosed_messages: Value, // { "0": "msg0", "2": "msg2", ... }
|
|
194
|
+
total_message_count: u32,
|
|
195
|
+
ciphersuite: Option<String>,
|
|
196
|
+
) -> napi::Result<bool> {
|
|
197
|
+
let pk_point = vc::bbs_ietf::serialize::octets_to_point_g2(&public_key)
|
|
198
|
+
.map_err(|e| napi::Error::from_reason(format!("bbsIetfProofVerify invalid PK: {e}")))?;
|
|
199
|
+
|
|
200
|
+
let header = header.as_deref().unwrap_or(&[]);
|
|
201
|
+
let ph = presentation_header.as_deref().unwrap_or(&[]);
|
|
202
|
+
let cs = ciphersuite.as_deref().unwrap_or("SHA-256");
|
|
203
|
+
let pk = vc::bbs_ietf::PublicKey(pk_point);
|
|
204
|
+
|
|
205
|
+
let obj = disclosed_messages
|
|
206
|
+
.as_object()
|
|
207
|
+
.ok_or_else(|| napi::Error::from_reason("disclosedMessages must be an object"))?;
|
|
208
|
+
|
|
209
|
+
match cs {
|
|
210
|
+
"SHAKE-256" => {
|
|
211
|
+
let disclosed: Vec<(usize, vc::bbs_ietf::Scalar)> = obj
|
|
212
|
+
.iter()
|
|
213
|
+
.map(|(k, v)| {
|
|
214
|
+
let idx: usize = k.parse().map_err(|_| {
|
|
215
|
+
napi::Error::from_reason(format!("invalid index: {k}"))
|
|
216
|
+
})?;
|
|
217
|
+
let msg_str = v.as_str().unwrap_or("");
|
|
218
|
+
let scalar = vc::bbs_ietf::map_message_to_scalar::<vc::bbs_ietf::Bls12381Shake256>(msg_str.as_bytes());
|
|
219
|
+
Ok((idx, scalar))
|
|
220
|
+
})
|
|
221
|
+
.collect::<napi::Result<_>>()?;
|
|
222
|
+
vc::bbs_ietf::proof_verify::<vc::bbs_ietf::Bls12381Shake256>(
|
|
223
|
+
&pk,
|
|
224
|
+
&proof,
|
|
225
|
+
header,
|
|
226
|
+
ph,
|
|
227
|
+
&disclosed,
|
|
228
|
+
total_message_count as usize,
|
|
229
|
+
)
|
|
230
|
+
.map_err(|e| napi::Error::from_reason(format!("bbsIetfProofVerify: {e}")))
|
|
231
|
+
}
|
|
232
|
+
_ => {
|
|
233
|
+
let disclosed: Vec<(usize, vc::bbs_ietf::Scalar)> = obj
|
|
234
|
+
.iter()
|
|
235
|
+
.map(|(k, v)| {
|
|
236
|
+
let idx: usize = k.parse().map_err(|_| {
|
|
237
|
+
napi::Error::from_reason(format!("invalid index: {k}"))
|
|
238
|
+
})?;
|
|
239
|
+
let msg_str = v.as_str().unwrap_or("");
|
|
240
|
+
let scalar = vc::bbs_ietf::map_message_to_scalar::<vc::bbs_ietf::Bls12381Sha256>(msg_str.as_bytes());
|
|
241
|
+
Ok((idx, scalar))
|
|
242
|
+
})
|
|
243
|
+
.collect::<napi::Result<_>>()?;
|
|
244
|
+
vc::bbs_ietf::proof_verify::<vc::bbs_ietf::Bls12381Sha256>(
|
|
245
|
+
&pk,
|
|
246
|
+
&proof,
|
|
247
|
+
header,
|
|
248
|
+
ph,
|
|
249
|
+
&disclosed,
|
|
250
|
+
total_message_count as usize,
|
|
251
|
+
)
|
|
252
|
+
.map_err(|e| napi::Error::from_reason(format!("bbsIetfProofVerify: {e}")))
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
#![allow(dead_code)]
|
|
2
1
|
use napi::bindgen_prelude::*;
|
|
3
2
|
use serde_json::json;
|
|
4
3
|
use types::{BoundCreateProofOptions, BoundSignatureSuiteOptions, BoundVerifyProofOptions};
|
|
5
4
|
|
|
5
|
+
use super::bbs_bls_signature_2020::napi_key_to_rust_key;
|
|
6
6
|
use super::bls_12381_g2_keypair::Bls12381G2KeyPair;
|
|
7
|
-
use crate::ld_signatures::
|
|
7
|
+
use crate::ld_signatures::loader_from_contexts;
|
|
8
8
|
|
|
9
9
|
pub mod types;
|
|
10
10
|
|
|
@@ -80,22 +80,9 @@ impl BbsBlsHolderBoundSignature2022 {
|
|
|
80
80
|
&self,
|
|
81
81
|
options: BoundCreateProofOptions,
|
|
82
82
|
) -> Result<serde_json::Value> {
|
|
83
|
-
let
|
|
84
|
-
.contexts
|
|
85
|
-
.as_ref()
|
|
86
|
-
.map(|v| parse_contexts(&json!({ "contexts": v })))
|
|
87
|
-
.unwrap_or_default();
|
|
88
|
-
let (loader, cr) = create_document_loader(additional_contexts);
|
|
83
|
+
let (loader, cr) = loader_from_contexts(options.contexts.as_ref());
|
|
89
84
|
|
|
90
|
-
let rust_key =
|
|
91
|
-
vc::jsonld::signatures::bbs::bls_12381_g2_keypair::Bls12381G2KeyPair::new(Some(
|
|
92
|
-
vc::jsonld::signatures::bbs::bls_12381_g2_keypair::types::KeyPairOptions {
|
|
93
|
-
id: self.key.id.clone(),
|
|
94
|
-
controller: self.key.controller.clone(),
|
|
95
|
-
public_key_base58: self.key.public_key(),
|
|
96
|
-
private_key_base58: self.key.private_key(),
|
|
97
|
-
},
|
|
98
|
-
));
|
|
85
|
+
let rust_key = napi_key_to_rust_key(&self.key);
|
|
99
86
|
|
|
100
87
|
// Commitment/blinded not needed for counting messages — use empty placeholders.
|
|
101
88
|
let bound_key = vc::jsonld::signatures::bbs::bound_keypair::BoundBls12381G2KeyPair::new(
|
|
@@ -128,12 +115,7 @@ impl BbsBlsHolderBoundSignature2022 {
|
|
|
128
115
|
&self,
|
|
129
116
|
options: BoundCreateProofOptions,
|
|
130
117
|
) -> Result<serde_json::Value> {
|
|
131
|
-
let
|
|
132
|
-
.contexts
|
|
133
|
-
.as_ref()
|
|
134
|
-
.map(|v| parse_contexts(&json!({ "contexts": v })))
|
|
135
|
-
.unwrap_or_default();
|
|
136
|
-
let (loader, cr) = create_document_loader(additional_contexts);
|
|
118
|
+
let (loader, cr) = loader_from_contexts(options.contexts.as_ref());
|
|
137
119
|
|
|
138
120
|
let commitment = self
|
|
139
121
|
.commitment
|
|
@@ -144,15 +126,7 @@ impl BbsBlsHolderBoundSignature2022 {
|
|
|
144
126
|
.as_ref()
|
|
145
127
|
.ok_or_else(|| napi::Error::from_reason("No blinded indices set on suite"))?;
|
|
146
128
|
|
|
147
|
-
let rust_key =
|
|
148
|
-
vc::jsonld::signatures::bbs::bls_12381_g2_keypair::Bls12381G2KeyPair::new(Some(
|
|
149
|
-
vc::jsonld::signatures::bbs::bls_12381_g2_keypair::types::KeyPairOptions {
|
|
150
|
-
id: self.key.id.clone(),
|
|
151
|
-
controller: self.key.controller.clone(),
|
|
152
|
-
public_key_base58: self.key.public_key(),
|
|
153
|
-
private_key_base58: self.key.private_key(),
|
|
154
|
-
},
|
|
155
|
-
));
|
|
129
|
+
let rust_key = napi_key_to_rust_key(&self.key);
|
|
156
130
|
|
|
157
131
|
let bound_key = vc::jsonld::signatures::bbs::bound_keypair::BoundBls12381G2KeyPair::new(
|
|
158
132
|
rust_key,
|
|
@@ -189,12 +163,7 @@ impl BbsBlsHolderBoundSignature2022 {
|
|
|
189
163
|
&self,
|
|
190
164
|
options: BoundVerifyProofOptions,
|
|
191
165
|
) -> Result<serde_json::Value> {
|
|
192
|
-
let
|
|
193
|
-
.contexts
|
|
194
|
-
.as_ref()
|
|
195
|
-
.map(|v| parse_contexts(&json!({ "contexts": v })))
|
|
196
|
-
.unwrap_or_default();
|
|
197
|
-
let (loader, cr) = create_document_loader(additional_contexts);
|
|
166
|
+
let (loader, cr) = loader_from_contexts(options.contexts.as_ref());
|
|
198
167
|
|
|
199
168
|
let blinding_factor = options.blinding_factor.to_vec();
|
|
200
169
|
let blinded_messages: Vec<Vec<u8>> =
|
|
@@ -2,7 +2,7 @@ use napi::bindgen_prelude::*;
|
|
|
2
2
|
use serde_json::json;
|
|
3
3
|
use types::{BoundDeriveProofOptions, BoundVerifyDerivedProofOptions};
|
|
4
4
|
|
|
5
|
-
use crate::ld_signatures::
|
|
5
|
+
use crate::ld_signatures::loader_from_contexts;
|
|
6
6
|
|
|
7
7
|
pub mod types;
|
|
8
8
|
|
|
@@ -27,12 +27,7 @@ impl BbsBlsHolderBoundSignatureProof2022 {
|
|
|
27
27
|
&self,
|
|
28
28
|
options: BoundDeriveProofOptions,
|
|
29
29
|
) -> Result<serde_json::Value> {
|
|
30
|
-
let
|
|
31
|
-
.contexts
|
|
32
|
-
.as_ref()
|
|
33
|
-
.map(|v| parse_contexts(&json!({ "contexts": v })))
|
|
34
|
-
.unwrap_or_default();
|
|
35
|
-
let (loader, cr) = create_document_loader(additional_contexts);
|
|
30
|
+
let (loader, cr) = loader_from_contexts(options.contexts.as_ref());
|
|
36
31
|
|
|
37
32
|
let blinding_factor = options.blinding_factor.to_vec();
|
|
38
33
|
let blinded_messages: Vec<Vec<u8>> =
|
|
@@ -60,12 +55,7 @@ impl BbsBlsHolderBoundSignatureProof2022 {
|
|
|
60
55
|
&self,
|
|
61
56
|
options: BoundVerifyDerivedProofOptions,
|
|
62
57
|
) -> Result<serde_json::Value> {
|
|
63
|
-
let
|
|
64
|
-
.contexts
|
|
65
|
-
.as_ref()
|
|
66
|
-
.map(|v| parse_contexts(&json!({ "contexts": v })))
|
|
67
|
-
.unwrap_or_default();
|
|
68
|
-
let (loader, cr) = create_document_loader(additional_contexts);
|
|
58
|
+
let (loader, cr) = loader_from_contexts(options.contexts.as_ref());
|
|
69
59
|
|
|
70
60
|
let purpose = vc::jsonld::signatures::AssertionProofPurpose::new();
|
|
71
61
|
let result = vc::jsonld::signatures::verify(&options.document, &purpose, loader, cr)
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
#![allow(dead_code)]
|
|
2
1
|
use base64::{engine::general_purpose::STANDARD, Engine as _};
|
|
3
2
|
use chrono::Utc;
|
|
4
3
|
use napi::bindgen_prelude::*;
|
|
@@ -11,12 +10,12 @@ use types::{
|
|
|
11
10
|
use super::bls_12381_g2_keypair::{
|
|
12
11
|
Bls12381G2KeyPair, KeyPairSigner, KeyPairSignerOptions, KeyPairVerifier, KeyPairVerifierOptions,
|
|
13
12
|
};
|
|
14
|
-
use crate::ld_signatures::
|
|
13
|
+
use crate::ld_signatures::loader_from_contexts;
|
|
15
14
|
|
|
16
15
|
pub mod types;
|
|
17
16
|
|
|
18
17
|
/// Convert a NAPI Bls12381G2KeyPair to a Rust core Bls12381G2KeyPair.
|
|
19
|
-
fn napi_key_to_rust_key(
|
|
18
|
+
pub(crate) fn napi_key_to_rust_key(
|
|
20
19
|
napi_key: &Bls12381G2KeyPair,
|
|
21
20
|
) -> vc::jsonld::signatures::bbs::bls_12381_g2_keypair::Bls12381G2KeyPair {
|
|
22
21
|
vc::jsonld::signatures::bbs::bls_12381_g2_keypair::Bls12381G2KeyPair::new(Some(
|
|
@@ -166,12 +165,7 @@ impl BbsBlsSignature2020 {
|
|
|
166
165
|
/// Returns just the proof object (matching JS reference behavior).
|
|
167
166
|
#[napi]
|
|
168
167
|
pub async fn create_proof(&self, options: CreateProofOptions) -> Result<serde_json::Value> {
|
|
169
|
-
let
|
|
170
|
-
.contexts
|
|
171
|
-
.as_ref()
|
|
172
|
-
.map(|v| parse_contexts(&json!({ "contexts": v })))
|
|
173
|
-
.unwrap_or_default();
|
|
174
|
-
let (loader, cr) = create_document_loader(additional_contexts);
|
|
168
|
+
let (loader, cr) = loader_from_contexts(options.contexts.as_ref());
|
|
175
169
|
|
|
176
170
|
let rust_key = napi_key_to_rust_key(&self.key);
|
|
177
171
|
let suite = vc::jsonld::signatures::bbs::BbsBlsSignature2020::new(
|
|
@@ -200,12 +194,7 @@ impl BbsBlsSignature2020 {
|
|
|
200
194
|
/// Returns `{ verified: boolean, error?: string }`.
|
|
201
195
|
#[napi]
|
|
202
196
|
pub async fn verify_proof(&self, options: VerifyProofOptions) -> Result<serde_json::Value> {
|
|
203
|
-
let
|
|
204
|
-
.contexts
|
|
205
|
-
.as_ref()
|
|
206
|
-
.map(|v| parse_contexts(&json!({ "contexts": v })))
|
|
207
|
-
.unwrap_or_default();
|
|
208
|
-
let (loader, cr) = create_document_loader(additional_contexts);
|
|
197
|
+
let (loader, cr) = loader_from_contexts(options.contexts.as_ref());
|
|
209
198
|
|
|
210
199
|
let purpose = vc::jsonld::signatures::AssertionProofPurpose::new();
|
|
211
200
|
let result = vc::jsonld::signatures::verify(&options.document, &purpose, loader, cr)
|
|
@@ -308,22 +297,3 @@ impl BbsBlsSignature2020 {
|
|
|
308
297
|
Ok(verified)
|
|
309
298
|
}
|
|
310
299
|
}
|
|
311
|
-
|
|
312
|
-
#[cfg(test)]
|
|
313
|
-
mod tests {
|
|
314
|
-
|
|
315
|
-
use super::*;
|
|
316
|
-
#[test]
|
|
317
|
-
pub fn it_works() {
|
|
318
|
-
let mut j = json!({});
|
|
319
|
-
|
|
320
|
-
let Some(obj) = j.as_object_mut() else {
|
|
321
|
-
return ();
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
obj.insert(String::from("hello"), "there".into());
|
|
325
|
-
let _x = STANDARD.decode("hello");
|
|
326
|
-
|
|
327
|
-
println!("{j}")
|
|
328
|
-
}
|
|
329
|
-
}
|
|
@@ -2,7 +2,7 @@ use napi::bindgen_prelude::*;
|
|
|
2
2
|
use serde_json::json;
|
|
3
3
|
use types::{DeriveProofOptions, VerifyDerivedProofOptions};
|
|
4
4
|
|
|
5
|
-
use crate::ld_signatures::
|
|
5
|
+
use crate::ld_signatures::loader_from_contexts;
|
|
6
6
|
|
|
7
7
|
pub mod types;
|
|
8
8
|
|
|
@@ -24,12 +24,7 @@ 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
|
|
28
|
-
.contexts
|
|
29
|
-
.as_ref()
|
|
30
|
-
.map(|v| parse_contexts(&json!({ "contexts": v })))
|
|
31
|
-
.unwrap_or_default();
|
|
32
|
-
let (loader, cr) = create_document_loader(additional_contexts);
|
|
27
|
+
let (loader, cr) = loader_from_contexts(options.contexts.as_ref());
|
|
33
28
|
|
|
34
29
|
let nonce = options.nonce.map(|s| s.as_bytes().to_vec());
|
|
35
30
|
|
|
@@ -52,12 +47,7 @@ impl BbsBlsSignatureProof2020 {
|
|
|
52
47
|
&self,
|
|
53
48
|
options: VerifyDerivedProofOptions,
|
|
54
49
|
) -> Result<serde_json::Value> {
|
|
55
|
-
let
|
|
56
|
-
.contexts
|
|
57
|
-
.as_ref()
|
|
58
|
-
.map(|v| parse_contexts(&json!({ "contexts": v })))
|
|
59
|
-
.unwrap_or_default();
|
|
60
|
-
let (loader, cr) = create_document_loader(additional_contexts);
|
|
50
|
+
let (loader, cr) = loader_from_contexts(options.contexts.as_ref());
|
|
61
51
|
|
|
62
52
|
let purpose = vc::jsonld::signatures::AssertionProofPurpose::new();
|
|
63
53
|
let result = vc::jsonld::signatures::verify(&options.document, &purpose, loader, cr)
|
|
@@ -58,12 +58,8 @@ impl Bls12381G2KeyPair {
|
|
|
58
58
|
// }
|
|
59
59
|
// };
|
|
60
60
|
|
|
61
|
-
let private_key_inner = o
|
|
62
|
-
|
|
63
|
-
.map(|v| bs58::decode(v).into_vec().unwrap());
|
|
64
|
-
let public_key_inner = o
|
|
65
|
-
.public_key_base58
|
|
66
|
-
.map(|v| bs58::decode(v).into_vec().unwrap());
|
|
61
|
+
let private_key_inner = o.private_key_base58.and_then(|v| bs58::decode(v).into_vec().ok());
|
|
62
|
+
let public_key_inner = o.public_key_base58.and_then(|v| bs58::decode(v).into_vec().ok());
|
|
67
63
|
|
|
68
64
|
Self {
|
|
69
65
|
id: o.id,
|
|
@@ -246,13 +242,21 @@ impl Bls12381G2KeyPair {
|
|
|
246
242
|
}
|
|
247
243
|
|
|
248
244
|
#[napi(getter)]
|
|
249
|
-
pub fn public_key_buffer(&self) -> Buffer {
|
|
250
|
-
self
|
|
245
|
+
pub fn public_key_buffer(&self) -> Result<Buffer> {
|
|
246
|
+
self
|
|
247
|
+
.public_key_inner
|
|
248
|
+
.clone()
|
|
249
|
+
.map(|b| b.into())
|
|
250
|
+
.ok_or_else(|| napi::Error::from_reason("no public key set"))
|
|
251
251
|
}
|
|
252
252
|
|
|
253
253
|
#[napi(getter)]
|
|
254
|
-
pub fn private_key_buffer(&self) -> Buffer {
|
|
255
|
-
self
|
|
254
|
+
pub fn private_key_buffer(&self) -> Result<Buffer> {
|
|
255
|
+
self
|
|
256
|
+
.private_key_inner
|
|
257
|
+
.clone()
|
|
258
|
+
.map(|b| b.into())
|
|
259
|
+
.ok_or_else(|| napi::Error::from_reason("no private key set"))
|
|
256
260
|
}
|
|
257
261
|
|
|
258
262
|
#[napi]
|
|
@@ -377,12 +381,8 @@ impl Bls12381G2KeyPair {
|
|
|
377
381
|
.ok_or(napi::Error::from_reason("public key buffer is missing"))?;
|
|
378
382
|
|
|
379
383
|
let leader = hex::encode(&fingerprint_buffer[..2]);
|
|
380
|
-
let leader_match =
|
|
381
|
-
let bytes_match =
|
|
382
|
-
true
|
|
383
|
-
} else {
|
|
384
|
-
false
|
|
385
|
-
};
|
|
384
|
+
let leader_match = leader == "eb01";
|
|
385
|
+
let bytes_match = public_key_inner == fingerprint_buffer[2..];
|
|
386
386
|
|
|
387
387
|
if leader_match && bytes_match {
|
|
388
388
|
Ok(())
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
#![allow(dead_code)]
|
|
2
1
|
use napi::bindgen_prelude::*;
|
|
3
2
|
|
|
4
3
|
use super::bls_12381_g2_keypair::Bls12381G2KeyPair;
|
|
@@ -64,12 +63,12 @@ impl BoundBls12381G2KeyPair {
|
|
|
64
63
|
}
|
|
65
64
|
|
|
66
65
|
#[napi(getter)]
|
|
67
|
-
pub fn public_key_buffer(&self) -> Buffer {
|
|
66
|
+
pub fn public_key_buffer(&self) -> Result<Buffer> {
|
|
68
67
|
self.inner.public_key_buffer()
|
|
69
68
|
}
|
|
70
69
|
|
|
71
70
|
#[napi(getter)]
|
|
72
|
-
pub fn private_key_buffer(&self) -> Buffer {
|
|
71
|
+
pub fn private_key_buffer(&self) -> Result<Buffer> {
|
|
73
72
|
self.inner.private_key_buffer()
|
|
74
73
|
}
|
|
75
74
|
|
|
@@ -84,6 +83,7 @@ impl BoundBls12381G2KeyPair {
|
|
|
84
83
|
}
|
|
85
84
|
|
|
86
85
|
/// Convert to a Rust core BoundBls12381G2KeyPair for use in signing.
|
|
86
|
+
#[allow(dead_code)] // Used by holder-bound suite after refactoring
|
|
87
87
|
pub(crate) fn to_rust_bound_key(
|
|
88
88
|
&self,
|
|
89
89
|
) -> vc::jsonld::signatures::bbs::bound_keypair::BoundBls12381G2KeyPair {
|