hmacDrbg static method

HmacDrbgFunction hmacDrbg(
  1. HmacFnSync hashFuncSync
)

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!;
  };
}