deriveKey method

  1. @override
Future<SecretKey> deriveKey({
  1. required SecretKey secretKey,
  2. required List<int> nonce,
  3. List<int> k = const <int>[],
  4. List<int> ad = const <int>[],
})
override

Calculates output of Argon2id algorithm.

Parameter secretKey is the hashed password, which can have any length.

Parameter nonce is the password salt, which can have any length.

Parameters k and ad are optional additional parameters specified by Argon2. They are usually left empty.

Implementation

@override
Future<SecretKey> deriveKey({
  required SecretKey secretKey,
  required List<int> nonce,
  List<int> k = const <int>[],
  List<int> ad = const <int>[],
}) async {
  // h0
  final secretKeyBytes = await secretKey.extractBytes();
  final h0Sink = Blake2b().newHashSink();
  _addUint32(h0Sink, parallelism);
  _addUint32(h0Sink, hashLength);
  _addUint32(h0Sink, memorySize);
  _addUint32(h0Sink, iterations);
  _addUint32(h0Sink, version);
  _addSequence(h0Sink, secretKeyBytes);
  _addSequence(h0Sink, nonce);
  _addSequence(h0Sink, k);
  _addSequence(h0Sink, ad);
  h0Sink.close();
  final h0 = (await h0Sink.hash()).bytes;

  final blocks = List<Uint8List?>.filled(parallelism, null);
  blocks[0] = Uint8List.fromList(h0);
  final columnCount = memorySize ~/ parallelism;

  // Initialize parallel lanes
  for (var i = 0; i < parallelism; i++) {
    throw UnimplementedError();
  }

  // First iteration
  for (var i = 0; i < parallelism; i++) {
    for (var j = 2; j < columnCount; j++) {
      throw UnimplementedError();
    }
  }

  // Second and further iterations
  for (var iteration = 1; iteration < iterations; iteration++) {
    for (var i = 0; i < parallelism; i++) {
      for (var j = 0; j < columnCount; j++) {
        throw UnimplementedError();
      }
    }
  }

  // XOR lanes
  final c = blocks[0];
  for (var i = 1; i < blocks.length; i++) {
    final block = blocks[i]!;
    for (var j = 0; j < block.length; j++) {
      c![j] ^= block[j];
    }
  }

  // Final hash
  SecretKey(Uint8List.fromList(await _hash(c!, hashLength)));

  throw UnimplementedError('Does not pass tests yet.');
}