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 ArgumentException.invalidOperationArguments(
      "signSchnorr",
      name: "digest",
      reason: "Invalid digest bytes length.",
    );
  }
  BigInt d = privateKey.secretMultiplier;
  final BigInt order = CryptoSignerConst.generatorSecp256k1.order!;

  if (!(BigInt.one <= d && d <= order - BigInt.one)) {
    throw ArgumentException.invalidOperationArguments(
      "signSchnorr",
      reason: "Invalid signig key.",
    );
  }
  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;
}