hmacDrbg static method
HMAC-DRBG
Implementation
static HmacDrbgFunction hmacDrbg(HmacFnSync hashFuncSync) {
// Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
Uint8List v = Uint8List(fLen);
// Steps B, C of RFC6979 3.2: set hashLen, in our case always same
Uint8List k = Uint8List(fLen);
// Iterations counter, will throw when over 1000
int i = 0;
void reset() {
v.fillRange(0, v.length, 1);
k.fillRange(0, k.length, 0);
i = 0;
}
const e = 'drbg: tried 1000 values';
h(List<Uint8List> b) {
return hashFuncSync(k, <Uint8List>[v, ...b]);
}
// HMAC-DRBG reseed() function. Steps D-G
void reseed([Uint8List? seed]) {
seed ??= Uint8List(0);
// k = hmac(k || v || 0x00 || seed)
k = h([
Uint8List.fromList(<int>[0x00]),
seed
]);
// v = hmac(k || v)
v = h([]);
if (seed.isEmpty) {
return;
}
// k = hmac(k || v || 0x01 || seed)
k = h([
Uint8List.fromList(<int>[0x01]),
seed
]);
// v = hmac(k || v)
v = h([]);
}
Uint8List gen() {
// HMAC-DRBG generate() function
if (i++ >= 1000) {
throw Exception(e);
}
v = h([]); // v = hmac(k || v)
return v;
}
return (Uint8List seed, K2SigFunc pred) {
reset();
reseed(seed); // Steps D-G
Signature? res; // Step H: grind until k is in [1..n-1]
while ((res = pred(gen())) == null) {
reseed();
} // test predicate until it returns ok
reset();
return res!;
};
}