verifyPresentation function
Future<bool>
verifyPresentation(
- dynamic presentation,
- String challenge, {
- Erc1056? erc1056,
- RevocationRegistry? revocationRegistry,
- Signer? signer,
- Signer signerSelector() = _determineSignerForType,
- dynamic loadDocumentFunction(
- Uri url,
- LoadDocumentOptions? options
- Future<
DidDocument> didResolver() = resolveDidDocument, - Map<
String, Map< ? issuerJwks,String, dynamic> >
Verifies the presentation
.
It uses erc1056 to look up the current owner of the dids a proof is given in presentation
.
Implementation
Future<bool> verifyPresentation(dynamic presentation, String challenge,
{Erc1056? erc1056,
RevocationRegistry? revocationRegistry,
Signer? signer,
Signer Function(
String typeMatch,
Function(Uri url, LoadDocumentOptions? options)
loadDocumentFunction)
signerSelector = _determineSignerForType,
Function(Uri url, LoadDocumentOptions? options) loadDocumentFunction =
loadDocumentStrict,
Future<DidDocument> Function(String) didResolver = resolveDidDocument,
Map<String, Map<String, dynamic>>? issuerJwks}) async {
// datatype conversion
Map<String, dynamic> presentationMap;
if (presentation is VerifiablePresentation) {
presentationMap = presentation.toJson();
} else {
presentationMap = credentialToMap(presentation);
}
// get proof(s) as List
var proofs = presentationMap['proof'];
if (proofs is Map<String, dynamic>) {
proofs = [proofs];
}
proofs as List;
presentationMap.remove('proof');
List<String> holderDids = [];
var credentials = [];
// verify credentials
if (presentationMap.containsKey('verifiableCredential')) {
credentials = presentationMap['verifiableCredential'] as List;
// get potential issuer jwks
Map<String, Map<String, dynamic>> issuerJwk = {};
for (var vc in credentials) {
var asVc = VerifiableCredential.fromJson(vc);
if (asVc.type.contains('PublicKeyCertificate')) {
issuerJwk[asVc.credentialSubject['id']] = asVc
.credentialSubject['publicKey']['publicKeyJwk']
.cast<String, dynamic>();
}
}
if (issuerJwks != null) {
issuerJwk.addAll(issuerJwks);
}
print(issuerJwk);
await Future.forEach(credentials, (dynamic element) async {
bool verified = true;
if (!VerifiableCredential.fromJson(element)
.type
.contains('PublicKeyCertificate')) {
verified = await verifyCredential(element,
erc1056: erc1056,
revocationRegistry: revocationRegistry,
signerSelector: signerSelector,
loadDocumentFunction: loadDocumentFunction,
issuerJwk: issuerJwk[getIssuerDidFromCredential(element)]);
}
if (!verified) {
throw Exception('A credential could not been verified');
} else {
var did = getHolderDidFromCredential(element);
if (erc1056 != null) did = await erc1056.identityOwner(did);
if (did.isNotEmpty && did.startsWith('did:')) {
if (!VerifiableCredential.fromJson(element)
.type
.contains('PublicKeyCertificate')) {
holderDids.add(did);
}
}
}
});
}
// check for holder property
if (presentationMap.containsKey('holder')) {
var holder = presentationMap['holder'];
if (holder is String && holder.startsWith('did:')) {
holderDids.add(holder);
}
}
// verify proofs from presentation
await Future.forEach(proofs, (dynamic element) async {
String verifMeth = element['verificationMethod'];
if (verifMeth.contains('#')) verifMeth = verifMeth.split('#').first;
if (erc1056 != null) verifMeth = await erc1056.identityOwner(verifMeth);
var signer = signerSelector.call(element['type'], loadDocumentFunction);
if (holderDids.contains(verifMeth)) holderDids.remove(verifMeth);
if (!await signer.verifyProof(element, presentationMap, verifMeth,
challenge: challenge)) {
throw Exception('Proof for $verifMeth could not been verified');
}
});
if (holderDids.isNotEmpty) throw Exception('There are dids without a proof');
presentationMap['proof'] = (proofs.length == 1) ? proofs.first : proofs;
// compare plaintext credentials (if given)
if (presentationMap.containsKey('disclosedCredentials')) {
var disclosedCredentials = presentationMap['disclosedCredentials'] as List;
Map<String?, Map<String, dynamic>> credsToId = {};
for (var element in credentials) {
var did = getHolderDidFromCredential(element);
credsToId[did] = element;
}
for (var element in disclosedCredentials) {
compareW3cCredentialAndPlaintext(credsToId[element['id']], element);
}
}
return true;
}