signSchnorr method

List<int> signSchnorr(
  1. List<int> digest, {
  2. List<int>? extraEntropy,
})

Implementation

List<int> signSchnorr(List<int> digest, {List<int>? extraEntropy}) {
  if (digest.length != BitcoinSignerUtils.baselen) {
    throw CryptoSignException(
        "The digest must be a ${BitcoinSignerUtils.baselen}-byte array.");
  }
  BigInt d = privateKey.secretMultiplier;
  final BigInt order = CryptoSignerConst.generatorSecp256k1.order!;

  if (!(BigInt.one <= d && d <= order - BigInt.one)) {
    throw const CryptoSignException(
        "The secret key must be an integer in the range 1..n-1.");
  }
  extraEntropy ??= CryptoSignerConst.bchSchnorrRfc6979ExtraData;
  BigInt k = RFC6979.generateK(
      order: order,
      secexp: privateKey.secretMultiplier,
      hashFunc: () => SHA256(),
      data: digest,
      extraEntropy: extraEntropy);

  final R = (CryptoSignerConst.generatorSecp256k1 * k);
  if (ECDSAUtils.jacobi(R.y, CryptoSignerConst.curveSecp256k1.p).isNegative) {
    k = order - k;
  }
  final eHash = QuickCrypto.sha256Hash(
      [...R.toXonly(), ...privateKey.publicKey.toBytes(), ...digest]);
  final BigInt e = BigintUtils.fromBytes(eHash) % order;

  // Step 5: Compute Schnorr Signature: s = k + e * d (mod n)
  final BigInt s = (k + e * d) % order;
  final signature = BitcoinSchnorrSignature(r: R.x, s: s).toBytes();

  // Step 6: Return Signature (64 bytes: R.x || s)
  return signature;
}