signature function
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;
}