generateKey method

List<int> generateKey(
  1. String password,
  2. String salt,
  3. int rounds,
  4. int keyLength,
)

Hashes a password with a given salt.

The length of this return value will be keyLength.

See Salt.generateAsBase64String for generating a random salt.

See also generateBase64Key, which base64 encodes the key returned from this method for storage.

Implementation

List<int> generateKey(
  String password,
  String salt,
  int rounds,
  int keyLength,
) {
  if (keyLength > (pow(2, 32) - 1) * _blockSize) {
    throw PBKDF2Exception('Derived key too long');
  }

  final int numberOfBlocks = (keyLength / _blockSize).ceil();
  final Hmac hmac = Hmac(hashAlgorithm, utf8.encode(password));
  final ByteData key = ByteData(keyLength);
  int offset = 0;

  final List<int> saltBytes = utf8.encode(salt);
  final int saltLength = saltBytes.length;
  final ByteData inputBuffer = ByteData(saltBytes.length + 4)
    ..buffer.asUint8List().setRange(0, saltBytes.length, saltBytes);

  for (int blockNumber = 1; blockNumber <= numberOfBlocks; blockNumber++) {
    inputBuffer
      ..setUint8(saltLength, blockNumber >> 24)
      ..setUint8(saltLength + 1, blockNumber >> 16)
      ..setUint8(saltLength + 2, blockNumber >> 8)
      ..setUint8(saltLength + 3, blockNumber);

    final Uint8List block =
        _XORDigestSink.generate(inputBuffer, hmac, rounds);
    int blockLength = _blockSize;
    if (offset + blockLength > keyLength) {
      blockLength = keyLength - offset;
    }
    key.buffer.asUint8List().setRange(offset, offset + blockLength, block);

    offset += blockLength;
  }

  return key.buffer.asUint8List();
}