verifyProof method

  1. @override
Future<bool> verifyProof(
  1. dynamic proof,
  2. dynamic data,
  3. String did, {
  4. String? challenge,
  5. Map<String, dynamic>? jwk,
  6. Future<DidDocument> didResolver(
    1. String
    ) = resolveDidDocument,
})
override

Verifies a LinkedDataProof / DataIntegrityProof

Implementation

@override
Future<bool> verifyProof(proof, data, String did,
    {String? challenge,
    Map<String, dynamic>? jwk,
    Future<DidDocument> Function(String) didResolver =
        resolveDidDocument}) async {
  //compare challenge
  if (challenge != null) {
    var containedChallenge = proof['challenge'];
    if (containedChallenge == null) {
      throw Exception('Expected challenge in this credential');
    }
    if (containedChallenge != challenge) {
      throw Exception('a challenge do not match expected challenge');
    }
  }

  //verify signature
  var signature = _getSignatureFromJws(proof['jws']);

  List<int> hash = await _dataToHash(data);

  String jws = proof.remove('jws');
  proof['@context'] = ecdsaRecoveryContextIri;

  var proofHash = sha256
      .convert(utf8.encode(await JsonLdProcessor.normalize(proof,
          options:
              JsonLdOptions(safeMode: true, documentLoader: loadDocument))))
      .bytes;
  var payload = proofHash + hash;

  proof['jws'] = jws;
  proof.remove('@context');

  var header = jws.split('.').first;

  var hashToSign = sha256.convert(utf8.encode('$header.') + payload).bytes;

  var pubKey = web3_crypto.ecRecover(hashToSign as Uint8List, signature);

  if (did.startsWith('did:ethr')) {
    var givenAddress = EthereumAddress.fromHex(did.split(':').last);

    return EthereumAddress.fromPublicKey(pubKey).hexEip55 ==
        givenAddress.hexEip55;
  } else if (did.startsWith('did:key')) {
    var c = el.getSecp256k1();
    var compressed = c.publicKeyToCompressedHex(el.PublicKey(
        c,
        web3_crypto.bytesToInt(pubKey.sublist(0, 32)),
        web3_crypto.bytesToInt(pubKey.sublist(32))));
    var recoveredDid = 'did:key:z${base58Bitcoin.encode(Uint8List.fromList([
          231,
          1
        ] + web3_crypto.hexToBytes(compressed)))}';
    print(recoveredDid);
    return did == recoveredDid;
  } else if (did.startsWith('did:jwk')) {
    var jwk = jsonDecode(utf8.decode(base64Decode(
        addPaddingToBase64(did.split(':')[2].split('#').first))));
    if (jwk['crv'] != 'secp256k1') {
      throw Exception('curve does not match');
    }

    var recoveredX = pubKey.sublist(0, 32);
    var recoveredY = pubKey.sublist(32);

    return removePaddingFromBase64(base64UrlEncode(recoveredX)) == jwk['x'] &&
        removePaddingFromBase64(base64UrlEncode(recoveredY)) == jwk['y'];
  } else if (did.startsWith('did:example')) {
    var recoveredX = pubKey.sublist(0, 32);
    var recoveredY = pubKey.sublist(32);
    print(base64Encode(recoveredX));
    print(base64Encode(recoveredY));
    print(EthereumAddress.fromPublicKey(pubKey).hexEip55);
    return true;
  } else {
    throw Exception('unsupported did method');
  }
}