signSchnorrConst method

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

Implementation

List<int> signSchnorrConst({
  required List<int> digest,
  List<int>? extraEntropy,
}) {
  if (digest.length != Curves.curveSecp256k1.baselen) {
    throw ArgumentException.invalidOperationArguments(
      "signSchnorrConst",
      name: "digest",
      reason: "Invalid digest bytes length.",
    );
  }
  final sec = privateKey.toBytes();
  List<int> k = RFC6979.generateSecp256k1KBytes(
    secexp: sec,
    hashFunc: () => SHA256(),
    data: digest,
    extraEntropy: extraEntropy,
  );
  final kScalar = Secp256k1Utils.scalarFromBytes(k);
  if (!Secp256k1Utils.scCheck(kScalar)) {
    throw const CryptoSignException(
      'Schnorr signing failed due to an unexpected error.',
    );
  }
  Secp256k1Gej R = Secp256k1Gej();
  Secp256k1.secp256k1ECmultGen(ecMultContext, R, kScalar);
  Secp256k1Ge rg = Secp256k1Ge();
  Secp256k1.secp256k1GeSetGej(rg, R);
  Secp256k1.secp256k1FeNormalize(rg.x);
  Secp256k1.secp256k1FeNormalize(rg.y);
  List<int> nonce32 = List<int>.filled(32, 0);
  Secp256k1.secp256k1FeGetB32(nonce32, rg.x);
  final eHash = QuickCrypto.sha256Hash([
    ...nonce32,
    ...privateKey.publicKey.toBytes(),
    ...digest,
  ]);

  final sk = Secp256k1Utils.scalarFromBytes(sec);
  final eSclar = Secp256k1Utils.scalarFromBytes(eHash);
  if (!Secp256k1Utils.scCheck(sk) || !Secp256k1Utils.scCheck(eSclar)) {
    throw const CryptoSignException(
      'Schnorr signing failed due to an unexpected error.',
    );
  }
  Secp256k1Scalar n = Secp256k1Scalar();
  Secp256k1Scalar sigs = Secp256k1Scalar();
  Secp256k1.secp256k1ScalarMul(n, eSclar, sk);

  if (Secp256k1.secp256k1FeIsQuad(R.y) == 0) {
    Secp256k1.secp256k1ScalarNegate(kScalar, kScalar);
  }
  Secp256k1.secp256k1ScalarAdd(sigs, kScalar, 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 [...nonce32, ...sBytes];
}