public Rfc2898DeriveBytes(string password, int saltSize, int iterations, HashAlgorithmName hashAlgorithm) { if (saltSize < 0) { throw new ArgumentOutOfRangeException(nameof(saltSize), ArgumentOutOfRange_NeedNonNegNum); } if (saltSize < MinimumSaltSize) { throw new ArgumentException(Cryptography_PasswordDerivedBytes_FewBytesSalt, nameof(saltSize)); } if (iterations <= 0) { throw new ArgumentOutOfRangeException(nameof(iterations), ArgumentOutOfRange_NeedPosNum); } _salt = CryptographyHelpers.GenerateRandom(saltSize); _iterations = (uint)iterations; _password = Encoding.UTF8.GetBytes(password); HashAlgorithm = hashAlgorithm; _hmac = OpenHmac(); // _blockSize is in bytes, HashSize is in bits. _blockSize = _hmac.HashSize >> 3; Initialize(); }
// This function is defined as follows: // Func (S, i) = HMAC(S || i) | HMAC2(S || i) | ... | HMAC(iterations) (S || i) // where i is the block number. private byte[] Func() { byte[] temp = new byte[_salt.Length + sizeof(uint)]; Buffer.BlockCopy(_salt, 0, temp, 0, _salt.Length); CryptographyHelpers.WriteInt(_block, temp, _salt.Length); temp = _hmac.ComputeHash(temp); byte[] ret = temp; for (int i = 2; i <= _iterations; i++) { temp = _hmac.ComputeHash(temp); for (int j = 0; j < _blockSize; j++) { ret[j] ^= temp[j]; } } // increment the block count. _block++; return(ret); }