verifySchnorr method

bool verifySchnorr(
  1. List<int> message,
  2. List<int> signature, {
  3. List? tapleafScripts,
  4. required bool isTweak,
})

Verifies a Schnorr-based signature against a given message, considering optional Taproot scripts.

Implementation

bool verifySchnorr(List<int> message, List<int> signature,
    {List<dynamic>? tapleafScripts, required bool isTweak}) {
  if (message.length != 32) {
    throw const ArgumentException("The message must be a 32-byte array.");
  }

  if (signature.length != 64 && signature.length != 65) {
    throw const ArgumentException(
        "The signature must be a 64-byte array or 65-bytes with sighash");
  }

  final P = isTweak
      ? P2TRUtils.tweakPublicKey(verifyKey.publicKey.point,
          script: tapleafScripts)
      : P2TRUtils.liftX(verifyKey.publicKey.point);

  final r = BigintUtils.fromBytes(signature.sublist(0, 32));

  final s = BigintUtils.fromBytes(signature.sublist(32, 64));

  final ProjectiveECCPoint generator = verifyKey.publicKey.generator;
  final BigInt prime = BitcoinSignerUtils._generator.curve.p;

  if (r >= prime || s >= BitcoinSignerUtils._order) {
    return false;
  }
  final eHash = P2TRUtils.taggedHash(
    "BIP0340/challenge",
    List<int>.from([
      ...signature.sublist(0, 32),
      ...BigintUtils.toBytes(P.x, length: BitcoinSignerUtils.baselen),
      ...message
    ]),
  );
  BigInt e = BigintUtils.fromBytes(eHash) % BitcoinSignerUtils._order;
  final sp = generator * s;

  if (P.y.isEven) {
    e = BitcoinSignerUtils._order - e;
  }
  ProjectiveECCPoint eP = P * e;

  final R = sp + eP;

  if (R.y.isOdd || R.x != r) {
    return false;
  }

  return true;
}