/// <summary> /// Performs key derivation using the PBKDF2 algorithm. /// </summary> /// <param name="password">The password from which to derive the key.</param> /// <param name="salt">The salt to be used during the key derivation process.</param> /// <param name="prf">The pseudo-random function to be used in the key derivation process.</param> /// <param name="iterationCount">The number of iterations of the pseudo-random function to apply /// during the key derivation process.</param> /// <param name="numBytesRequested">The desired length (in bytes) of the derived key.</param> /// <returns>The derived key.</returns> /// <remarks> /// The PBKDF2 algorithm is specified in RFC 2898. /// </remarks> public static byte[] Pbkdf2(string password, byte[] salt, KeyDerivationPrf prf, int iterationCount, int numBytesRequested) { if (password == null) { throw new ArgumentNullException(nameof(password)); } if (salt == null) { throw new ArgumentNullException(nameof(salt)); } // parameter checking if (prf < KeyDerivationPrf.HMACSHA1 || prf > KeyDerivationPrf.HMACSHA512) { throw new ArgumentOutOfRangeException(nameof(prf)); } if (iterationCount <= 0) { throw new ArgumentOutOfRangeException(nameof(iterationCount)); } if (numBytesRequested <= 0) { throw new ArgumentOutOfRangeException(nameof(numBytesRequested)); } return(Pbkdf2Provider.DeriveKey(password, salt, prf, iterationCount, numBytesRequested)); }
public Pbkdf2ViewModel() { kdfProvider = new Pbkdf2Provider(); }
internal PinnedBuffer DeriveKey() { var result = (PinnedBuffer)null; try { using (var controlToken = StateControl.Enter()) { if (DerivationMode == SecureSymmetricKeyDerivationMode.Pbkdf2) { try { // Perform PBKDF2 key-derivation. result = new PinnedBuffer(Pbkdf2Provider.GetBytes(DerivedKeyLength), true); } finally { Pbkdf2Provider.Reset(); } return(result); } result = new PinnedBuffer(DerivedKeyLength, true); using (var sourceWords = new PinnedStructureArray <UInt32>(KeySourceWordCount, true)) { KeySource.Access((PinnedBuffer buffer) => { // Convert the source buffer to an array of 32-bit words. Buffer.BlockCopy(buffer, 0, sourceWords, 0, KeySourceLengthInBytes); }); using (var transformedWords = new PinnedStructureArray <UInt32>(BlockWordCount, true)) { // Copy out the first block. If nothing further is done, this satisfies truncation mode. Array.Copy(sourceWords, transformedWords, BlockWordCount); switch (DerivationMode) { case SecureSymmetricKeyDerivationMode.Truncation: break; case SecureSymmetricKeyDerivationMode.XorLayering: for (var i = 1; i < BlockCount; i++) { for (var j = 0; j < BlockWordCount; j++) { // Perform the XOR layering operation. transformedWords[j] = (transformedWords[j] ^ sourceWords[(i * BlockWordCount) + j]); } } break; case SecureSymmetricKeyDerivationMode.XorLayeringWithSubstitution: for (var i = 1; i < BlockCount; i++) { for (var j = 0; j < BlockWordCount; j++) { // Perform the XOR layering operation with substitution. transformedWords[j] = (SubstituteWord(transformedWords[j]) ^ sourceWords[(i * BlockWordCount) + j]); } } break; default: throw new InvalidOperationException($"The specified key derivation mode, {DerivationMode}, is not supported."); } // Copy out the key bits. Buffer.BlockCopy(transformedWords, 0, result, 0, DerivedKeyLength); } } return(result); } } catch { result?.Dispose(); throw new SecurityException("Key derivation failed."); } }