Skip to content
This repository has been archived by the owner on May 9, 2020. It is now read-only.

Commit

Permalink
Adding support for PBKDF2 on Win7/Server 2008. Updating version to 1.…
Browse files Browse the repository at this point in the history
…7.2 for release.
  • Loading branch information
gregz_codeplex_cp authored and gregz_codeplex_cp committed Nov 15, 2014
1 parent f4c192e commit 5466820
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 7 deletions.
4 changes: 2 additions & 2 deletions Security.Cryptography/AssemblyVersion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

using System.Reflection;

[assembly: AssemblyVersion("1.7.1.0")]
[assembly: AssemblyFileVersion("1.7.1.0")]
[assembly: AssemblyVersion("1.7.2.0")]
[assembly: AssemblyFileVersion("1.7.2.0")]
53 changes: 49 additions & 4 deletions Security.Cryptography/src/BCryptNative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,17 @@ internal static extern ErrorCode BCryptGenerateSymmetricKey(SafeBCryptAlgorithmH
[Out, MarshalAs(UnmanagedType.LPArray)] byte[] pbSecret,
int cbSecret,
int dwFlags);

[DllImport("bcrypt.dll", EntryPoint = "BCryptDeriveKeyPBKDF2")]
internal static extern ErrorCode BCryptDeriveKeyPBKDF2(SafeBCryptAlgorithmHandle hPrf,
[In, MarshalAs(UnmanagedType.LPArray)] byte[] pbPassword,
int cbPassword,
[In, MarshalAs(UnmanagedType.LPArray)] byte[] pbSalt,
int cbSalt,
ulong cIterations,
[Out, MarshalAs(UnmanagedType.LPArray)] byte[] pbDerivedKey,
int cbDerivedKey,
int dwFlags);

}

Expand Down Expand Up @@ -1084,12 +1095,13 @@ internal static byte[] SymmetricEncrypt(SafeBCryptKeyHandle key,
}

/// <summary>
/// Calls PBKDF2 via the <c>BCryptKeyDerivation</c> API. <paramref name="hashName"/> specifies which of HMAC-SHA256, HMAC-SHA384 or HMAC-SHA512 to use.
/// See the <see cref="AlgorithmName"/> class for supported hash functions.
/// Calls PBKDF2 via the <c>BCryptKeyDerivation</c> API. <param name="hashName"/> specifies which of HMAC-SHA256, HMAC-SHA384 or HMAC-SHA512 to use.
/// See the <see cref="AlgorithmName"/> class for supported hash functions. <param name="password"/> is the password, and <param name="salt"/>
/// is the salt and <param name="iterations"/> is the iteration count.
/// </summary>
[SecurityCritical]
[SecuritySafeCritical]
internal static byte[] PBKDF2(string hashName,
internal static byte[] PBKDF2BCryptKeyDerivation(string hashName,
byte[] password,
byte[] salt,
ulong iterations)
Expand Down Expand Up @@ -1153,7 +1165,40 @@ internal static byte[] PBKDF2(string hashName,

return derivedKey;
}




/// <summary>
/// Call PBKDF2 via the BCryptDeriveKeyPBKDF2 API. <param name="hashName"/> specifies which of HMAC-SHA256, HMAC-SHA384 or HMAC-SHA512 to use
/// See the <see cref="AlgorithmName"/> class for supported hash functions. <param name="password"/> is the password, and <param name="salt"/>
/// is the salt and <param name="iterations"/> is the iteration count.
/// </summary>
[SecurityCritical]
[SecurityTreatAsSafe]
internal static byte[] PBKDF2BCryptDeriveKeyPBKDF2(string hashName,
byte[] password,
byte[] salt,
ulong iterations)
{
// Open handle for HMAC-hashName, with the default algorithm provider
SafeBCryptAlgorithmHandle hPrf = OpenAlgorithm(hashName, null, AlgorithmProviderOptions.HmacAlgorithm);

// Get the hash length
int hashLength = GetInt32Property(hPrf, HashPropertyName.HashLength);
byte[] derivedKey = new byte[hashLength];

ErrorCode error = UnsafeNativeMethods.BCryptDeriveKeyPBKDF2(hPrf, password, password.Length, salt, salt.Length, iterations, derivedKey, derivedKey.Length, 0);
if (error != ErrorCode.Success)
{
throw new CryptographicException(Win32Native.GetNTStatusMessage((int)error));
}

hPrf.Close();

return derivedKey;
}


} // end class BCryptNative

/// <summary>
Expand Down
17 changes: 16 additions & 1 deletion Security.Cryptography/src/BCryptPBKDF2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,22 @@ public static byte[] ComputeHash(string hashName, byte[] password, byte[] salt,
if(!PBKDF2HashAlgorithm.ValidateHashName(hashName))
throw new ArgumentException("Invalid hash name for PBKDF2");

return BCryptNative.PBKDF2(hashName, password, salt, (UInt64) cIterations);
byte[] digest = null;

double vers = Environment.OSVersion.Version.Major + Environment.OSVersion.Version.Minor * 0.1;

if(vers > 6.1)
{
// The BCryptKeyDerivation API is only supported on Win8/Server 2012 and above
digest = BCryptNative.PBKDF2BCryptKeyDerivation(hashName, password, salt, (UInt64) cIterations);
}
else
{
// Fall back to BCryptDeriveKeyPBKDF2, which is roughly 2x slower on systems without the KeyDerivation API
digest = BCryptNative.PBKDF2BCryptDeriveKeyPBKDF2(hashName, password, salt, (UInt64)cIterations);
}

return digest;
}

}
Expand Down

0 comments on commit 5466820

Please sign in to comment.