signature function

Signature signature(
  1. PrivateKey priv,
  2. List<int> hash
)

signature signs a hash (which should be the result of hashing a larger message) using the private key, priv. If the hash is longer than the bit-length of the private key's curve order, the hash will be truncated to that length. It returns the signature as a pair of integers.

Implementation

Signature signature(PrivateKey priv, List<int> hash) {
  var curve = priv.curve;

  var sig = Signature.fromRS(BigInt.zero, BigInt.zero);
  if (curve.n.sign == 0) {
    throw ErrInvalidCurve;
  }

  var random = Random.secure();
  late List<int> rand;
  var byteLen = curve.bitSize ~/ 8 + 8;

  late BigInt k, kInv;
  while (true) {
    while (true) {
      // note: no need to use csprng. Random.secure() is already an implement of csprng
      rand =
          List<int>.generate(byteLen, (i) => random.nextInt(256)); // bytes of k
      k = BigInt.parse(
          List<String>.generate(
              byteLen, (i) => rand[i].toRadixString(16).padLeft(2, '0')).join(),
          radix: 16);

      kInv = k.modInverse(curve.n);

      sig.R = priv.curve.scalarBaseMul(rand).X;
      sig.R = sig.R % curve.n;
      if (sig.R.sign != 0) {
        // valid r
        break;
      }
    }

    var e = bitsToInt(hash, curve.n.bitLength);
    sig.S = priv.D * sig.R;
    sig.S = sig.S + e;
    sig.S = sig.S * kInv;
    sig.S = sig.S % curve.n; // N != 0
    if (sig.S.sign != 0) {
      break;
    }
  }

  return sig;
}