variableLengthHash method

  1. @visibleForTesting
void variableLengthHash({
  1. required Uint8List output,
  2. required Uint8List input,
})

RFC 9106 function H'^T(A).

Implementation

@visibleForTesting
void variableLengthHash({
  required Uint8List output,
  required Uint8List input,
}) {
  final outputLength = output.length;
  final blake2b = const DartBlake2b().replace(
    hashLength: min<int>(outputLength, 64),
  );
  var sink = blake2b.newHashSink();
  sink.add([
    0xFF & outputLength,
    0xFF & (outputLength >>> 8),
    0xFF & (outputLength >>> 16),
    0xFF & (outputLength >>> 24),
  ]);
  sink.add(input);
  sink.close();
  if (outputLength <= 64) {
    output.setAll(0, sink.hashBytes);
    return;
  }

  input = Uint8List.fromList(sink.hashBytes);
  output.setAll(0, sink.hashBytes.take(32));
  var remainingLength = outputLength - 32;
  var outputIndex = 32;
  input = Uint8List.fromList(sink.hashBytes);
  sink.reset();

  while (remainingLength > 64) {
    sink.add(input);
    sink.close();
    output.setAll(outputIndex, sink.hashBytes);
    outputIndex += 32;
    remainingLength -= 32;
    input.setAll(0, sink.hashBytes);
    sink.reset();
  }

  if (output.length % 64 != 0) {
    sink = blake2b.replace(hashLength: remainingLength).newHashSink();
  }
  sink.add(input);
  sink.close();
  output.setAll(outputIndex, sink.hashBytes);
}