signAndRecover static method

Future<List<PasskeyPublicKey>> signAndRecover(
  1. PasskeyProvider provider,
  2. Uint8List message
)

Signs message and returns every public key (up to 4) that could have produced the signature. Call twice with different messages and intersect the results (see findCommonPublicKey) to identify an existing passkey whose public key is not yet known to the wallet.

Implementation

static Future<List<PasskeyPublicKey>> signAndRecover(
  PasskeyProvider provider,
  Uint8List message,
) async {
  final credential = await provider.get(message);
  final clientDataHash = sha256(credential.clientDataJson);
  final payload = Uint8List.fromList([
    ...credential.authenticatorData,
    ...clientDataHash,
  ]);
  final messageHash = sha256(payload);

  final (r, s) = _decodeDerEcdsaSignature(credential.signature);
  final sig = ECSignature(r, s);
  final secp = Secp256.fromSecp256r1();

  final result = <PasskeyPublicKey>[];
  for (var i = 0; i < 4; i++) {
    try {
      final recovered = secp.recoverFromSignature(i, sig, messageHash, true);
      if (recovered != null && recovered.length == PASSKEY_PUBLIC_KEY_SIZE) {
        result.add(PasskeyPublicKey(recovered));
      }
    } catch (_) {
      continue;
    }
  }
  return result;
}