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 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 numberOfBlocks = (keyLength / _blockSize).ceil();
  final hmac = Hmac(hashAlgorithm, utf8.encode(password));
  final key = ByteData(keyLength);
  var offset = 0;

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

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

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

    offset += blockLength;
  }

  return key.buffer.asUint8List();
}