signAndRecover static method
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;
}