generateK static method
Generates a deterministic K value for ECDSA signatures.
This method implements the RFC6979 deterministic K value generation algorithm for use in ECDSA signatures. It takes various input parameters, including the curve order, secret exponent, a hash function, data, and optional extra entropy.
Parameters:
order: The order of the elliptic curve.secexp: The secret exponent.hashFunc: A hash function to use in the HMAC operations.data: Additional data for K generation.retryGn: The number of retries allowed in case of invalid K values.extraEntropy: Optional extra entropy for K generation.
Implementation
static BigInt generateK({
required BigInt order,
required BigInt secexp,
required HashFunc hashFunc,
required List<int> data,
int retryGn = 0,
List<int>? extraEntropy,
}) {
final int qlen = order.bitLength;
final hx = hashFunc();
final int holen = hx.getDigestLength;
final int rolen = (qlen + 7) ~/ 8;
final List<List<int>> bx = [
BigintUtils.toBytes(secexp, length: BigintUtils.bitlengthInBytes(order)),
bitsToOctetsWithOrderPadding(data, order),
extraEntropy ?? [],
];
List<int> v = List<int>.filled(holen, 0);
v.fillRange(0, holen, 0x01);
List<int> k = List<int>.filled(holen, 0);
HMAC hmac = HMAC(hashFunc, k);
hmac.update([...v, 0x00]);
for (final i in bx) {
hmac.update(i);
}
k = hmac.digest();
hmac.clean();
hmac = HMAC(hashFunc, k);
hmac.update(v);
v = hmac.digest();
hmac.clean();
hmac = HMAC(hashFunc, k);
hmac.update([...v, 0x01]);
for (final i in bx) {
hmac.update(i);
}
k = hmac.digest();
// Step G
v = HMAC.hmac(hashFunc, k, v);
// Step H
while (true) {
// Step H1
List<int> t = List.empty();
// Step H2
while (t.length < rolen) {
v = HMAC.hmac(hashFunc, k, v);
t = [...t, ...v];
}
// Step H3
final BigInt secret = bitsToBigIntWithLengthLimit(t, qlen);
if (secret >= BigInt.one && secret < order) {
if (retryGn <= 0) {
return secret;
}
retryGn -= 1;
}
k = HMAC.hmac(hashFunc, k, [...v, 0x00]);
v = HMAC.hmac(hashFunc, k, v);
}
}