Skip to content

Commit 070a91a

Browse files
authored
Merge pull request #156 from alan-turing-institute/115-selective-disclosure-ssi-update
Pulling upstream changes from the ssi fork (addition of selective disclosure with RSS) into trustchain, handling RSS credentials with ffi functions and over the trustchain-http server.
2 parents b66e12f + fc98ba0 commit 070a91a

File tree

25 files changed

+619
-187
lines changed

25 files changed

+619
-187
lines changed

trustchain-api/Cargo.toml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,17 @@ edition = "2021"
88
[dependencies]
99
trustchain-core = { path = "../trustchain-core" }
1010
trustchain-ion = { path = "../trustchain-ion" }
11+
ps_sig = { git = "https://github.com/alan-turing-institute/RSS.git", rev = "ec9386e125d87c5f54898b34fbe0883b3b36ffd4" }
1112

1213
async-trait = "0.1"
1314
serde_json = "1.0"
14-
ssi = {git="https://github.com/alan-turing-institute/ssi.git", branch="modify-encode-sign-jwt", features = ["http-did", "secp256k1"]}
15-
did-ion = {git="https://github.com/alan-turing-institute/ssi.git", branch="modify-encode-sign-jwt"}
15+
ssi = { git = "https://github.com/alan-turing-institute/ssi.git", rev = "1aa3223a384ee71df1333bbce04af445e852eab5", features = [
16+
"http-did",
17+
"secp256k1",
18+
"rss",
19+
] }
20+
did-ion = { git = "https://github.com/alan-turing-institute/ssi.git", rev = "1aa3223a384ee71df1333bbce04af445e852eab5" }
1621
futures = "0.3.28"
1722

1823
[dev-dependencies]
19-
tokio = {version = "1.20.1", features = ["full"]}
24+
tokio = { version = "1.20.1", features = ["full"] }

trustchain-api/src/api.rs

Lines changed: 145 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -248,10 +248,11 @@ pub trait TrustchainVPAPI {
248248
mod tests {
249249
use crate::api::{TrustchainVCAPI, TrustchainVPAPI};
250250
use crate::TrustchainAPI;
251+
use did_ion::sidetree::PublicKeyEntry;
251252
use ssi::jsonld::ContextLoader;
252253
use ssi::ldp::now_ns;
253254
use ssi::one_or_many::OneOrMany;
254-
use ssi::vc::{Credential, CredentialOrJWT, Presentation, VCDateTime};
255+
use ssi::vc::{Credential, CredentialOrJWT, CredentialSubject, Presentation, VCDateTime};
255256
use trustchain_core::utils::init;
256257
use trustchain_core::vc::CredentialError;
257258
use trustchain_core::vp::PresentationError;
@@ -269,14 +270,8 @@ mod tests {
269270
"https://www.w3.org/2018/credentials/examples/v1",
270271
"https://w3id.org/citizenship/v1"
271272
],
272-
"credentialSchema": {
273-
"id": "did:example:cdf:35LB7w9ueWbagPL94T9bMLtyXDj9pX5o",
274-
"type": "did:example:schema:22KpkXgecryx9k7N6XN1QoN3gXwBkSU8SfyyYQG"
275-
},
276273
"type": ["VerifiableCredential"],
277274
"issuer": "did:ion:test:EiAtHHKFJWAk5AsM3tgCut3OiBY4ekHTf66AAjoysXL65Q",
278-
"issuanceDate": "2023-09-06T12:15:08.630033Z",
279-
"image": "some_base64_representation",
280275
"credentialSubject": {
281276
"givenName": "Jane",
282277
"familyName": "Doe",
@@ -289,6 +284,33 @@ mod tests {
289284
}
290285
"#;
291286

287+
const UNSIGNED_DRIVERS_LICENCE_VC: &str = r###"{
288+
"@context": [
289+
"https://www.w3.org/2018/credentials/v1",
290+
"https://w3id.org/vdl/v1"
291+
],
292+
"type": [
293+
"VerifiableCredential",
294+
"Iso18013DriversLicense"
295+
],
296+
"issuer": "did:ion:test:EiAtHHKFJWAk5AsM3tgCut3OiBY4ekHTf66AAjoysXL65Q",
297+
"issuanceDate": "2023-11-23T11:43:26.806224Z",
298+
"credentialSubject": {
299+
"id": "did:example:12347abcd",
300+
"Iso18013DriversLicense": {
301+
"height": 1.8,
302+
"weight": 70,
303+
"nationality": "France",
304+
"given_name": "Test",
305+
"family_name": "A",
306+
"issuing_country": "US",
307+
"birth_date": "1958-07-17",
308+
"age_in_years": 30,
309+
"age_birth_year": 1958
310+
}
311+
}
312+
}"###;
313+
292314
#[ignore = "requires a running Sidetree node listening on http://localhost:3000"]
293315
#[tokio::test]
294316
async fn test_verify_credential() {
@@ -328,6 +350,110 @@ mod tests {
328350
}
329351
}
330352

353+
#[ignore = "requires a running Sidetree node listening on http://localhost:3000"]
354+
#[tokio::test]
355+
async fn test_verify_rss_credential() {
356+
init();
357+
358+
// DID with RSS verification method
359+
let issuer_did_suffix = "EiAtHHKFJWAk5AsM3tgCut3OiBY4ekHTf66AAjoysXL65Q";
360+
let resolver = trustchain_resolver("http://localhost:3000/");
361+
let vc: Credential = serde_json::from_str(UNSIGNED_DRIVERS_LICENCE_VC).unwrap();
362+
let attestor = IONAttestor::new(issuer_did_suffix);
363+
364+
let signed_vc = attestor
365+
.sign(
366+
&vc,
367+
None,
368+
Some("QDsGIX_7NfNEaXdEeV7PJ5e_CwoH5LlF3srsCp5dcHA"),
369+
&resolver,
370+
&mut ContextLoader::default(),
371+
)
372+
.await
373+
.unwrap();
374+
println!("{}", serde_json::to_string_pretty(&signed_vc).unwrap());
375+
let mut context_loader = ContextLoader::default();
376+
let verifier = TrustchainVerifier::new(resolver);
377+
let res = TrustchainAPI::verify_credential(
378+
&signed_vc,
379+
None,
380+
ROOT_EVENT_TIME_1,
381+
&verifier,
382+
&mut context_loader,
383+
)
384+
.await;
385+
// println!("{:?}", &res);
386+
assert!(res.is_ok());
387+
}
388+
389+
#[ignore = "requires a running Sidetree node listening on http://localhost:3000"]
390+
#[tokio::test]
391+
async fn test_redact_verify_rss_credential() {
392+
init();
393+
394+
// DID with RSS verification method
395+
let issuer_did_suffix = "did:ion:test:EiAtHHKFJWAk5AsM3tgCut3OiBY4ekHTf66AAjoysXL65Q";
396+
let resolver = trustchain_resolver("http://localhost:3000/");
397+
let vc: Credential = serde_json::from_str(UNSIGNED_DRIVERS_LICENCE_VC).unwrap();
398+
let attestor = IONAttestor::new(issuer_did_suffix);
399+
400+
let mut signed_vc = attestor
401+
.sign(
402+
&vc,
403+
None,
404+
Some("QDsGIX_7NfNEaXdEeV7PJ5e_CwoH5LlF3srsCp5dcHA"),
405+
&resolver,
406+
&mut ContextLoader::default(),
407+
)
408+
.await
409+
.unwrap();
410+
// println!("{}", serde_json::to_string_pretty(&signed_vc).unwrap());
411+
// derive redacted RSignature
412+
let masked_cred_sub: CredentialSubject = serde_json::from_str(
413+
r###"{
414+
"id": "did:example:12347abcd",
415+
"Iso18013DriversLicense": {
416+
"height": null,
417+
"weight": null,
418+
"nationality": null,
419+
"given_name": null,
420+
"family_name": null,
421+
"issuing_country": "US",
422+
"birth_date": null,
423+
"age_in_years": 30,
424+
"age_birth_year": null
425+
}
426+
}"###,
427+
)
428+
.unwrap();
429+
let mut masked_copy = signed_vc.clone();
430+
masked_copy.credential_subject = OneOrMany::One(masked_cred_sub);
431+
432+
// produce redacted vc from redacted json
433+
let mut context_loader = ContextLoader::default();
434+
let verifier = TrustchainVerifier::new(resolver);
435+
signed_vc
436+
.rss_redact(
437+
masked_copy,
438+
&trustchain_resolver("http://localhost:3000/"),
439+
&mut context_loader,
440+
)
441+
.await
442+
.unwrap();
443+
// println!("{}", serde_json::to_string_pretty(&signed_vc).unwrap());
444+
445+
let res = TrustchainAPI::verify_credential(
446+
&signed_vc,
447+
None,
448+
ROOT_EVENT_TIME_1,
449+
&verifier,
450+
&mut context_loader,
451+
)
452+
.await;
453+
454+
assert!(res.is_ok());
455+
}
456+
331457
#[ignore = "requires a running Sidetree node listening on http://localhost:3000"]
332458
#[tokio::test]
333459
async fn test_verify_presentation() {
@@ -444,4 +570,16 @@ mod tests {
444570
.await
445571
.unwrap()
446572
}
573+
574+
#[test]
575+
fn get_key_entry() {
576+
use ps_sig::keys::Params;
577+
use ssi::jwk::rss::generate_keys_jwk;
578+
use ssi::jwk::JWK;
579+
580+
let key: JWK = generate_keys_jwk(64, &Params::new("test".to_string().as_bytes())).unwrap();
581+
println!("{}", serde_json::to_string_pretty(&key).unwrap());
582+
let entry: PublicKeyEntry = key.try_into().unwrap();
583+
println!("{}", serde_json::to_string_pretty(&entry).unwrap());
584+
}
447585
}

trustchain-cli/Cargo.toml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,15 @@ trustchain-core = { path = "../trustchain-core" }
1313
trustchain-ion = { path = "../trustchain-ion" }
1414
trustchain-api = { path = "../trustchain-api" }
1515

16-
clap = { version = "4.0.32", features=["derive", "cargo"] }
17-
did-ion = {git="https://github.com/alan-turing-institute/ssi.git", branch="modify-encode-sign-jwt"}
18-
lazy_static="1.4.0"
16+
clap = { version = "4.0.32", features = ["derive", "cargo"] }
17+
did-ion = { git = "https://github.com/alan-turing-institute/ssi.git", rev = "1aa3223a384ee71df1333bbce04af445e852eab5" }
18+
lazy_static = "1.4.0"
1919
serde = { version = "1.0", features = ["derive"] }
2020
serde_json = "1.0"
21-
ssi = {git="https://github.com/alan-turing-institute/ssi.git", branch="modify-encode-sign-jwt", features = ["http-did", "secp256k1"]}
22-
tokio = {version = "1.20.1", features = ["full"]}
23-
toml="0.7.2"
21+
ssi = { git = "https://github.com/alan-turing-institute/ssi.git", rev = "1aa3223a384ee71df1333bbce04af445e852eab5", features = [
22+
"http-did",
23+
"secp256k1",
24+
"rss",
25+
] }
26+
tokio = { version = "1.20.1", features = ["full"] }
27+
toml = "0.7.2"

trustchain-cli/src/bin/main.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
227227
println!("Proof... Invalid");
228228
err?;
229229
}
230+
err @ Err(CredentialError::NoProofPresent) => {
231+
println!("Proof... ❌ (missing proof)");
232+
err?;
233+
}
234+
err @ Err(CredentialError::MissingVerificationMethod) => {
235+
println!("Proof... ❌ (missing verification method)");
236+
err?;
237+
}
230238
err @ Err(CredentialError::NoIssuerPresent) => {
231239
println!("Proof... ✅");
232240
println!("Issuer... ❌ (missing issuer)");

trustchain-core/Cargo.toml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,27 @@ edition = "2021"
66

77

88
[dependencies]
9+
ps_sig = { git = "https://github.com/alan-turing-institute/RSS.git", rev = "ec9386e125d87c5f54898b34fbe0883b3b36ffd4" }
10+
911
async-trait = "0.1"
1012
base64 = "0.13"
1113
canonical_json = "0.4.0"
1214
chrono = "0.4"
13-
did-method-key = {git="https://github.com/alan-turing-institute/ssi.git", branch="modify-encode-sign-jwt"}
15+
did-method-key = { git = "https://github.com/alan-turing-institute/ssi.git", rev = "1aa3223a384ee71df1333bbce04af445e852eab5" }
1416
futures = "0.3.21"
15-
petgraph = {version = "0.6"}
17+
petgraph = { version = "0.6" }
1618
serde = { version = "1.0", features = ["derive"] }
1719
serde_jcs = "0.1.0"
1820
serde_json = "1.0"
1921
sha2 = "0.10.7"
20-
ssi = {git="https://github.com/alan-turing-institute/ssi.git", branch="modify-encode-sign-jwt", features = ["http-did", "secp256k1"]}
22+
ssi = { git = "https://github.com/alan-turing-institute/ssi.git", rev = "1aa3223a384ee71df1333bbce04af445e852eab5", features = [
23+
"http-did",
24+
"secp256k1",
25+
"rss",
26+
] }
2127
tempfile = { version = "3.3" }
2228
thiserror = "1.0"
23-
tokio = {version = "1.20.1", features = ["full"]}
29+
tokio = { version = "1.20.1", features = ["full"] }
2430

2531
[dev-dependencies]
2632
mockall = "0.11.2"

0 commit comments

Comments
 (0)