Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AnonCreds Credentials using the W3C Standard - wrappers #273

Merged
merged 28 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
fbc2ecf
W3C: Updated Python wrapper
Artemkaaas Nov 13, 2023
dfbca25
Added JS wrapper
Artemkaaas Nov 14, 2023
6fb3c16
Updated wrappers
Artemkaaas Nov 15, 2023
1bed31e
Added missing method to NodeJS wrapper
Artemkaaas Nov 15, 2023
0e817d6
Fixes in Python and Node wrappers
Artemkaaas Nov 16, 2023
2f97949
fix: Replace with w3c call, change order of enum variants
Abdulbois Nov 21, 2023
19ca275
Python: Added classes for W3CCredentialOffer and W3CCredentialRequest
Artemkaaas Dec 4, 2023
00d3a15
Reverted lerna version change
Artemkaaas Dec 8, 2023
2b903fe
Run prettier
Artemkaaas Dec 8, 2023
c436949
Use `W3c` instead of capitalized `W3C`
Artemkaaas Dec 11, 2023
c276c2a
Use `W3c` instead of capitalized `W3C` in python wrapper
Artemkaaas Dec 11, 2023
e9e7229
Dropped redundant methods for non-anoncreds proof and offer/request c…
Artemkaaas Dec 11, 2023
3e1f184
Added convert helper in node package
Artemkaaas Dec 12, 2023
a3ce38c
Clean up
Artemkaaas Dec 20, 2023
7fed651
Merge branch 'anoncreds-w3c-format-changes' into anoncreds-wc3-wrappers
Artemkaaas Dec 20, 2023
87312b5
Updated python wrapper
Artemkaaas Dec 20, 2023
d04299f
Updated JavaScript wrappers
Artemkaaas Dec 20, 2023
189afbe
Merge branch 'anoncreds-w3c-format-changes' into anoncreds-wc3-wrappers
Artemkaaas Dec 20, 2023
1c3c30b
Corrected context definition
Artemkaaas Dec 20, 2023
67d456b
Returned rust version to 1.65.0
Artemkaaas Dec 20, 2023
5094192
Fixed prettier error
Artemkaaas Dec 20, 2023
b39c2c8
Merge remote-tracking branch 'dsr/anoncreds-w3c-format-changes' into …
Artemkaaas Dec 21, 2023
5648b15
Merge remote-tracking branch 'dsr/anoncreds-w3c-format-changes' into …
Artemkaaas Dec 21, 2023
f4b975c
Merge branch 'anoncreds-w3c-format-changes' into anoncreds-wc3-wrappers
Artemkaaas Dec 21, 2023
65c7ca6
Renamed parameter from version to w3cVersion
Artemkaaas Dec 21, 2023
93801c8
Merge remote-tracking branch 'dsr/anoncreds-w3c-format-changes' into …
Artemkaaas Jan 11, 2024
9e6875d
Merge remote-tracking branch 'origin/main' into anoncreds-wc3-wrappers
Artemkaaas Jan 12, 2024
f0c2901
Fixed couple comments
Artemkaaas Jan 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
340 changes: 0 additions & 340 deletions docs/design/w3c/w3c-representation.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,52 +104,6 @@ The reasons for adding duplication methods:
- only credential conversion method to do migration for previously issued credentials

```rust
/// Create Credential Offer according to the AnonCreds specification
/// Note that Credential Offer still will be legacy styled (the same as result of anoncreds_create_credential_offer)
///
/// # Params
/// schema_id: id of schema future credential refers to
/// cred_def_id: id of credential definition future credential refers to
/// key_proof: object handle pointing to credential definition key correctness proof
/// cred_offer_p: reference that will contain created credential offer (in legacy form) instance pointer
///
/// # Returns
/// Error code
#[no_mangle]
pub extern "C" fn anoncreds_create_w3c_credential_offer(
schema_id: FfiStr,
cred_def_id: FfiStr,
key_proof: ObjectHandle,
cred_offer_p: *mut ObjectHandle,
) -> ErrorCode {}

/// Create Credential Request according to the AnonCreds specification
/// Note that Credential Request still will be legacy styled (the same as result of anoncreds_create_credential_request)
///
/// # Params
/// entropy: entropy string to use for request creation
/// prover_did: DID of the credential holder
/// cred_def: object handle pointing to credential definition
/// link_secret: holder link secret
/// link_secret_id: id of holder's link secret
/// credential_offer: object handle pointing to credential offer
/// cred_req_p: Reference that will contain created credential request (in legacy form) instance pointer.
/// cred_req_meta_p: Reference that will contain created credential request metadata (in legacy form) instance pointer.
///
/// # Returns
/// Error code
#[no_mangle]
pub extern "C" fn anoncreds_create_w3c_credential_request(
entropy: FfiStr,
prover_did: FfiStr,
cred_def: ObjectHandle,
link_secret: FfiStr,
link_secret_id: FfiStr,
cred_offer: ObjectHandle,
cred_req_p: *mut ObjectHandle,
cred_req_meta_p: *mut ObjectHandle,
) -> ErrorCode {}

/// Create Credential in W3C form according to the specification.
///
/// # Params
Expand Down Expand Up @@ -343,297 +297,3 @@ w3c_presentation_request = Verifier.w3c_create_presentation_request()
w3c_presentation = Holder.anoncreds_w3c_create_presentation(w3c_presentation_request, w3c_credential)
Verifier.anoncreds_w3c_verify_presentation(w3c_presentation)
```

#### Issue W3C Credential, set RSA Identity Proof signature, and present W3C Presentation using RSA Identity Proof

```
/// Issue W3C credential using new flow methods
w3c_credential_offer = Issuer.anoncreds_w3c_create_credential_offer(...)
w3c_credential_request = Holder.anoncreds_w3c_create_credential_request(w3c_credential_offer,...)
w3c_credential = Issuer.anoncreds_w3c_create_credential(w3c_credential_request,...)
w3c_credential = Holder.anoncreds_w3c_process_credential(w3c_credential,...)

/// Add RSA Identity Proof signature to credential
integrity_proof = extartnal_library.create_rsa_integrity_proof(w3c_credential)
w3c_credential = anoncreds_w3c_credential_add_non_anoncreds_integrity_proof(w3c_credential, integrity_proof)

/// Do wallets need to store both credential forms to handle legacy and DIF presentations requests?
Wallet.store_w3c_credential(w3c_credential)

/// Verifiy W3C presenttion using RSA Identity Proof signature
w3c_presentation_request = Verifier.w3c_create_presentation_request()
rsa_integrity_proof_presentation = extartnal_library.create_presentation_using_rsa_integrity_proof(w3c_presentation_request, w3c_credential)
extartnal_verifier.verify_rsa_integrity_proof_presentation(rsa_integrity_proof_presentation)
```

### Presentation validation

**Request**
```
{
"name":"pres_req_1",
"non_revoked":null,
"nonce":"358493544514389191968232",
"requested_attributes":{
"attr1_referent":{
"name":"first_name",
"non_revoked":null,
"restrictions":null
},
"attr2_referent":{
"name":"sex",
"non_revoked":null,
"restrictions":null
},
"attr3_referent":{
"names":[
"last_name",
"height"
],
"non_revoked":null,
"restrictions":null
}
},
"requested_predicates":{
"predicate1_referent":{
"name":"age",
"non_revoked":null,
"p_type":">=",
"p_value":18,
"restrictions":null
}
},
"ver":"1.0",
"version":"0.1"
}
```

**Presentation**
```
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://raw.githubusercontent.com/DSRCorporation/anoncreds-rs/design/w3c-support/docs/design/w3c/context.json"
],
"type": [
"VerifiablePresentation",
"AnonCredsPresentation"
],
"verifiableCredential": [
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://raw.githubusercontent.com/DSRCorporation/anoncreds-rs/design/w3c-support/docs/design/w3c/context.json"
],
"type": [
"VerifiableCredential",
"AnonCredsPresentation"
],
"issuer": "did:sov:3avoBCqDMFHFaKUHug9s8W",
"issuanceDate": "2023-10-26T01:17:32Z",
"credentialSchema": {
"type": "AnonCredsDefinition",
"definition": "did:sov:3avoBCqDMFHFaKUHug9s8W:3:CL:13:default",
"schema": "did:sov:3avoBCqDMFHFaKUHug9s8W:2:basic_person:0.1.0"
},
"credentialSubject": {
"first_name": "Alice"
"lastt_name": "Jons"
"height": "185"
},
"proof": {
"type": "AnonCredsPresentationProof2023",
"mapping": {
"revealedAttributes": ["attr1_referent"],
"unrevealedAttributes": ["attr2_referent"],
"revealedAttributeGroups": ["attr3_referent"],
"requestedPredicates": ["predicate1_referent"]
},
"proofValue": "AAEBAnr2Ql...0UhJ-bIIdWFKVWxjU3ePxv_7HoY5pUw"
}
}
],
"proof": {
"type": "AnonCredsPresentationProof2023",
"challenge": "182453895158932070575246",
"proofValue": "AAAgtMR4....J19l-agSA"
}
}
```

**Verifier validation steps is we keep mapping**:
```
// validate requested attributes
for (referent, requested) in presentation_request.requested_attributes {
credential = presentation.verifiableCredential.find((verifiableCredential) =>
verifiableCredential.proof.mapping.revealedAttributes.includes(referent) ||
verifiableCredential.proof.mapping.unrevealedAttributes.includes(referent) ||
verifiableCredential.proof.mapping.revealedAttributeGroups.includes(referent))

credential.checkRestrictions(requested.restrictions)

if !credential {
error
}
if requested.name {
assert(credential.credentialSubject[requested.name])
}
if requested.names {
names.forEach((name) => assert(credential.credentialSubject[name]))
}
}

// validate requested predicates
for (referent, requested) in presentation_request.requested_predicates {
credential = presentation.verifiableCredential.find((verifiableCredential) =>
verifiableCredential.proof.mapping.requestedPredicates.includes(referent))
credential.checkRestrictions(requested.restrictions)
assert(credential.credentialSubject[requested.name]) // if we include derived predicate into subject
}
```

**Verifier validation steps is we drop mapping**:
```
// validate requested attributes
for (referent, requested) in presentation_request.requested_attributes {
if requested.name {
// or filter if requted same attribute multiple times?
credential = presentation.verifiableCredential.find((verifiableCredential) =>
credentialSubject.contains(requested[name])
)
if credential {
credential.checkRestrictions(requested.restrictions)
assert(credential.credentialSubject[requested.name])
}
if !credential {
// consider attribute as unrevealed
// If we need to support and validate unrevealed attributes
credential_with_attribute = presentation.verifiableCredential.find((verifiableCredential) =>
schema = get_schema(verifiableCredential.schema_id) // all schemas already passed into verification function
schema.attributes.includes(requested.name)
verifiableCredential.matches(restrictions)
)
if !credential_with_attribute {
error
}
}
}
if requested.names {
for (referent, requested) in requested.names {
// do same as for single attribute above
// make sure that all come from single credential
}
}
}

// validate requested predicates - we put predicate derived string or object into credentialSubject
// {
// "age" ">= 18"
// }
for (referent, requested) in presentation_request.requested_predicates {
// or filter if requted same attribute multiple times?
credential = presentation.verifiableCredential.find((verifiableCredential) =>
credentialSubject.contains(requested[name])
)
if !credential {
error
}
credential.checkRestrictions(requested.restrictions)
assert(credential.credentialSubject[requested.name])
}
```

### Examples
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we not want to keep the examples?


Example of an AnonCreds W3C credential:

```json
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://raw.githubusercontent.com/hyperledger/anoncreds-spec/main/data/anoncreds-w3c-context.json"
],
"type": [
"VerifiableCredential",
"AnonCredsCredential"
],
"issuer": "did:sov:3avoBCqDMFHFaKUHug9s8W",
"issuanceDate": "2023-11-15T10:00:00.036203Z",
"credentialSchema": {
"type": "AnonCredsDefinition",
"definition": "did:sov:3avoBCqDMFHFaKUHug9s8W:3:CL:13:default",
"schema": "did:sov:3avoBCqDMFHFaKUHug9s8W:2:basic_person:0.1.0"
},
"credentialSubject": {
"firstName": "Alice",
"lastName": "Jones",
"age": "18"
},
"proof": [
{
"type": "AnonCredsProof2023",
"signature": "AAAgf9w5.....8Z_x3FqdwRHoWruiF0FlM"
},
{
"type": "Ed25519Signature2020",
"created": "2021-11-13T18:19:39Z",
"verificationMethod": "did:sov:3avoBCqDMFHFaKUHug9s8W#key-1",
"proofPurpose": "assertionMethod",
"proofValue": "z58DAdFfa9SkqZMVPxAQpic7ndSayn1PzZs6ZjWp1CktyGesjuTSwRdoWhAfGFCF5bppETSTojQCrfFPP2oumHKtz"
}
]
}
```

Example of an AnonCreds W3C presentation:

```json
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://raw.githubusercontent.com/hyperledger/anoncreds-spec/main/data/anoncreds-w3c-context.json"
],
"type": [
"VerifiablePresentation",
"AnonCredsPresentation"
],
"verifiableCredential": [
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://raw.githubusercontent.com/hyperledger/anoncreds-spec/main/data/anoncreds-w3c-context.json"
],
"type": [
"VerifiableCredential",
"AnonCredsCredential"
],
"credentialSchema": {
"type": "AnonCredsDefinition",
"definition": "did:sov:3avoBCqDMFHFaKUHug9s8W:3:CL:13:default",
"schema": "did:sov:3avoBCqDMFHFaKUHug9s8W:2:basic_person:0.1.0"
},
"credentialSubject": {
"firstName": "Alice",
"age": [
{
"type": "AnonCredsPredicate",
"predicate": ">=",
"value": 18
}
]
},
"issuanceDate": "2023-11-15T10:59:48.036203Z",
"issuer": "did:sov:3avoBCqDMFHFaKUHug9s8W",
"proof": {
"type": "AnonCredsPresentationProof2023",
"proofValue": "eyJzdWJfcHJvb2Yi...zMTc1NzU0NDAzNDQ0ODUifX1dfX19"
}
}
],
"proof": {
"type": "AnonCredsPresentationProof2023",
"challenge": "413296376279822794586260",
"proofValue": "eyJhZ2dyZWdhdGVkIjp7ImNfaGFzaCI6IjEwMT...IsMzAsMTM1LDE4MywxMDcsMTYwXV19fQ=="
}
}
```
Loading