verifySchnorrSignature static method

bool verifySchnorrSignature({
  1. required List<int> xOnly,
  2. required List<int> message,
  3. required List<int> signature,
  4. List<int>? tweak,
})

Implementation

static bool verifySchnorrSignature(
    {required List<int> xOnly,
    required List<int> message,
    required List<int> signature,
    List<int>? tweak}) {
  if (message.length != 32) {
    throw const CryptoSignException("The message must be a 32-byte array.");
  }

  if (signature.length != 64 && signature.length != 65) {
    throw const CryptoSignException(
        "The signature must be a 64-byte array or 65-bytes with sighash");
  }
  final x = BigintUtils.fromBytes(xOnly);
  final P =
      tweak != null ? tweakKey(xBig: x, tweak: tweak) : P2TRUtils.liftX(x);

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

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

  final ProjectiveECCPoint generator = BitcoinSignerUtils.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;
  }
  final ProjectiveECCPoint eP = P * e;

  final R = sp + eP;

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

  return true;
}