signBip340Const method

List<int> signBip340Const({
  1. required List<int> digest,
  2. List<int>? tapTweakHash,
  3. List<int>? aux,
})

Implementation

List<int> signBip340Const(
    {required List<int> digest, List<int>? tapTweakHash, List<int>? aux}) {
  if (digest.length != BitcoinSignerUtils.baselen) {
    throw CryptoSignException(
        "The digest must be a ${BitcoinSignerUtils.baselen}-byte array.");
  }
  if (aux != null && aux.length != 32) {
    throw CryptoSignException("The aux must be a 32-byte array.");
  }

  final tKey = _tweakConst(privateKey.toBytes(), ecMultContext,
      tapTweakHash: tapTweakHash);
  aux ??= QuickCrypto.sha256Hash(
      [...digest, ...Secp256k1Utils.scalarToBytes(tKey)]);

  Secp256k1Ge mid = Secp256k1Ge();
  Secp256k1Gej res = Secp256k1Gej();
  Secp256k1.secp256k1ECmultGen(ecMultContext, res, tKey);
  Secp256k1.secp256k1GeSetGej(mid, res);
  if (Secp256k1.secp256k1FeIsOdd(mid.y) == 1) {
    Secp256k1.secp256k1ScalarNegate(tKey, tKey);
  }
  final d = Secp256k1Utils.scalarToBytes(tKey);
  final t = BytesUtils.xor(d, P2TRUtils.taggedHash("BIP0340/aux", aux));
  Secp256k1.secp256k1FeNormalize(mid.x);
  final xBytes = Secp256k1Utils.feToBytes(mid.x);

  final kHash =
      P2TRUtils.taggedHash("BIP0340/nonce", [...t, ...xBytes, ...digest]);
  final k0 = Secp256k1Utils.scalarFromBytes(kHash);

  if (!Secp256k1Utils.scCheck(k0)) {
    throw const CryptoSignException(
        'Schnorr signing failed due to an unexpected error.');
  }
  Secp256k1Ge midR = Secp256k1Ge();
  Secp256k1Gej resR = Secp256k1Gej();
  Secp256k1.secp256k1ECmultGen(ecMultContext, resR, k0);
  Secp256k1.secp256k1GeSetGej(midR, resR);

  if (Secp256k1.secp256k1FeIsOdd(midR.y) == 1) {
    Secp256k1.secp256k1ScalarNegate(k0, k0);
  }
  Secp256k1.secp256k1FeNormalize(midR.x);
  final rBytes = Secp256k1Utils.feToBytes(midR.x);
  final eHash = P2TRUtils.taggedHash(
      "BIP0340/challenge", [...rBytes, ...xBytes, ...digest]);
  final eSclar = Secp256k1Utils.scalarFromBytes(eHash);
  if (!Secp256k1Utils.scCheck(eSclar)) {
    throw const CryptoSignException(
        'Schnorr signing failed due to an unexpected error.');
  }
  Secp256k1Scalar n = Secp256k1Scalar();
  Secp256k1Scalar sigs = Secp256k1Scalar();
  Secp256k1.secp256k1ScalarMul(n, eSclar, tKey);
  Secp256k1.secp256k1ScalarAdd(sigs, k0, n);
  if (!Secp256k1Utils.scCheck(sigs)) {
    throw const CryptoSignException(
        'Schnorr signing failed due to an unexpected error.');
  }
  List<int> sBytes = List<int>.filled(32, 0);
  Secp256k1.secp256k1ScalarGetB32(sBytes, sigs);

  return [...rBytes, ...sBytes];
}