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.
Returns:
- BigInt: The generated deterministic K value.
Details:
- This method follows the RFC6979 algorithm for deterministic K value generation in ECDSA signatures. It utilizes the provided parameters to create a secure and deterministic K value suitable for ECDSA signature operations.
- The optional 'extraEntropy' parameter allows you to introduce additional entropy for improved security if needed.
- The method handles the entire K generation process according to the RFC6979 specifications and returns the generated K value.
Note: The RFC6979 algorithm ensures that K values are generated deterministically and securely, which is essential for cryptographic operations.
Implementation
static BigInt generateK(
BigInt order, BigInt secexp, HashFunc hashFunc, List<int> data,
{int retryGn = 0, List<int>? extraEntropy}) {
int qlen = order.bitLength;
final hx = hashFunc();
int holen = hx.getDigestLength;
int rolen = (qlen + 7) ~/ 8;
List<List<int>> bx = [
BigintUtils.toBytes(secexp, length: BigintUtils.orderLen(order)),
BigintUtils.bitsToOctetsWithOrderPadding(data, order),
extraEntropy ?? List.empty(),
];
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(List<int>.from([...v, 0x00]));
for (var 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(List<int>.from([...v, 0x01]));
for (var i in bx) {
hmac.update(i);
}
k = hmac.digest();
// Step G
v = HMAC(hashFunc, k).update(v).digest();
// Step H
while (true) {
// Step H1
List<int> t = List.empty();
// Step H2
while (t.length < rolen) {
v = HMAC(hashFunc, k).update(v).digest();
t = List<int>.from([...t, ...v]);
}
// Step H3
BigInt secret = BigintUtils.bitsToBigIntWithLengthLimit(t, qlen);
if (secret >= BigInt.one && secret < order) {
if (retryGn <= 0) {
return secret;
}
retryGn -= 1;
}
k = HMAC(hashFunc, k).update(List<int>.from([...v, 0x00])).digest();
v = HMAC(hashFunc, k).update(v).digest();
}
}