Skip to content

Commit

Permalink
Merge pull request #273 from DSRCorporation/anoncreds-wc3-wrappers
Browse files Browse the repository at this point in the history
AnonCreds Credentials using the W3C Standard - wrappers
  • Loading branch information
swcurran authored Jan 15, 2024
2 parents c9f0e15 + f0c2901 commit c5b4f1d
Show file tree
Hide file tree
Showing 20 changed files with 2,810 additions and 464 deletions.
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

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

0 comments on commit c5b4f1d

Please sign in to comment.