verifyPresentation function

Future<bool> verifyPresentation(
  1. dynamic presentation,
  2. String challenge, {
  3. Erc1056? erc1056,
  4. RevocationRegistry? revocationRegistry,
  5. Signer? signer,
  6. Signer signerSelector(
    1. String typeMatch,
    2. dynamic loadDocumentFunction(
      1. Uri url,
      2. LoadDocumentOptions? options
      )
    ) = _determineSignerForType,
  7. dynamic loadDocumentFunction(
    1. Uri url,
    2. LoadDocumentOptions? options
    ) = loadDocumentStrict,
})

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}) async {
  // datatype conversion
  Map<String, dynamic> presentationMap;
  if (presentation is VerifiablePresentation) {
    presentationMap = presentation.toJson();
  } else {
    presentationMap = credentialToMap(presentation);
  }

  var proofs = presentationMap['proof'] as List;
  presentationMap.remove('proof');

  // verify credentials
  var credentials = presentationMap['verifiableCredential'] as List;
  List<String> holderDids = [];
  await Future.forEach(credentials, (dynamic element) async {
    bool verified = await verifyCredential(element,
        erc1056: erc1056,
        revocationRegistry: revocationRegistry,
        signerSelector: signerSelector,
        loadDocumentFunction: loadDocumentFunction);
    if (!verified) {
      throw Exception('A credential could not been verified');
    } else {
      var did = getHolderDidFromCredential(element);
      if (erc1056 != null) did = await erc1056.identityOwner(did);
      holderDids.add(did);
    }
  });

  //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.verify(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;

  //compare plaintext credentials
  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;
}