PBKDF2 在 .NET 中使用 SHA 256
PBKDF2 using SHA 256 in .NET
我需要更新一些在 .Net 中使用 PBKDF2 实现的代码,Rfc2898DeriveBytes
来散列用户凭据。
据我了解,此函数在后台使用 SHA-1。我需要更新系统密码哈希的底层哈希算法以使用 SHA-256(这是客户端 IT-SEC 要求)。
经过一些阅读,似乎最好的做法是继续使用密钥派生函数,但是 PBKDF2 不允许您指定应该使用的算法,这对我来说显然是个问题。
我们的系统使用的是 .NET 4.5.1,目前无法升级它,我有理由相信它不是引用任何我听说包含新的 .NET 核心 .dll 的选项允许您指定算法的 PBKDF2 实现。
我想不惜一切代价避免自制实现,因为这是 Crypto-Club 的第一条规则,对吗?
任何有关最佳做法的指导都将不胜感激。
谢谢
您现在可以指定一个算法,msdn page
注意:自 4.7.2 起可用
名字在System.Security.Cryptography.HashAlgorithmName
中可用
我会告诉你我会怎么做:我会使用 Rfc2898DeriveBytes
来自 corefx github
您需要完整代码:
- https://github.com/dotnet/corefx/blob/29cb063b95661470340b6ba7e1381495c05bfff2/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/Rfc2898DeriveBytes.cs
- https://github.com/dotnet/corefx/blob/45b724f6b6391910edea8a70f3f22a4a7996696d/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HashAlgorithmName.cs
- https://github.com/dotnet/corefx/blob/bffef76f6af208e2042a2f27bc081ee908bb390b/src/System.Security.Cryptography.Encoding/src/Internal/Cryptography/Helpers.cs
加上来自
的两种方法(GenerateRandom
和WriteInt
)
然后你将有一些对 SR.*something*
的调用,你必须将其替换为一些消息,例如 "some error"
,以及必须用 [= 替换的 SR.Format
17=].
然后你将拥有(几乎)最新版本的 Rfc2898DeriveBytes
,它有一个接受参数 HashAlgorithmName.SHA256
.
的构造函数
这应该是最终结果:https://ideone.com/lb2Qya
我把源代码放在命名空间 My.System
中是个坏主意...坏主意...我不得不在所有命名空间前加上 global::
前缀:-(
假设您使用的是 Win7+,您可以 P/Invoke 到 BCryptDeriveKeyPBKDF2。
private static void PBKDF2(
string password,
byte[] salt,
int iterationCount,
string hashName,
byte[] output)
{
int status = SafeNativeMethods.BCryptOpenAlgorithmProvider(
out SafeNativeMethods.SafeBCryptAlgorithmHandle hPrf,
hashName,
null,
SafeNativeMethods.BCRYPT_ALG_HANDLE_HMAC_FLAG);
using (hPrf)
{
if (status != 0)
{
throw new CryptographicException(status);
}
byte[] passBytes = Encoding.UTF8.GetBytes(password);
status = SafeNativeMethods.BCryptDeriveKeyPBKDF2(
hPrf,
passBytes,
passBytes.Length,
salt,
salt.Length,
iterationCount,
output,
output.Length,
0);
if (status != 0)
{
throw new CryptographicException(status);
}
}
}
[SuppressUnmanagedCodeSecurity]
private static class SafeNativeMethods
{
private const string BCrypt = "bcrypt.dll";
internal const int BCRYPT_ALG_HANDLE_HMAC_FLAG = 0x00000008;
[DllImport(BCrypt, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
internal static extern int BCryptDeriveKeyPBKDF2(
SafeBCryptAlgorithmHandle hPrf,
byte[] pbPassword,
int cbPassword,
byte[] pbSalt,
int cbSalt,
long cIterations,
byte[] derivedKey,
int cbDerivedKey,
int dwFlags);
[DllImport(BCrypt)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
private static extern int BCryptCloseAlgorithmProvider(IntPtr hAlgorithm, int flags);
[DllImport(BCrypt, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
internal static extern int BCryptOpenAlgorithmProvider(
out SafeBCryptAlgorithmHandle phAlgorithm,
string pszAlgId,
string pszImplementation,
int dwFlags);
internal sealed class SafeBCryptAlgorithmHandle : SafeHandleZeroOrMinusOneIsInvalid
{
public SafeBCryptAlgorithmHandle() : base(true)
{
}
protected override bool ReleaseHandle()
{
return BCryptCloseAlgorithmProvider(handle, 0) == 0;
}
}
}
我需要更新一些在 .Net 中使用 PBKDF2 实现的代码,Rfc2898DeriveBytes
来散列用户凭据。
据我了解,此函数在后台使用 SHA-1。我需要更新系统密码哈希的底层哈希算法以使用 SHA-256(这是客户端 IT-SEC 要求)。
经过一些阅读,似乎最好的做法是继续使用密钥派生函数,但是 PBKDF2 不允许您指定应该使用的算法,这对我来说显然是个问题。
我们的系统使用的是 .NET 4.5.1,目前无法升级它,我有理由相信它不是引用任何我听说包含新的 .NET 核心 .dll 的选项允许您指定算法的 PBKDF2 实现。
我想不惜一切代价避免自制实现,因为这是 Crypto-Club 的第一条规则,对吗?
任何有关最佳做法的指导都将不胜感激。
谢谢
您现在可以指定一个算法,msdn page
注意:自 4.7.2 起可用
名字在System.Security.Cryptography.HashAlgorithmName
我会告诉你我会怎么做:我会使用 Rfc2898DeriveBytes
来自 corefx github
您需要完整代码:
- https://github.com/dotnet/corefx/blob/29cb063b95661470340b6ba7e1381495c05bfff2/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/Rfc2898DeriveBytes.cs
- https://github.com/dotnet/corefx/blob/45b724f6b6391910edea8a70f3f22a4a7996696d/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HashAlgorithmName.cs
- https://github.com/dotnet/corefx/blob/bffef76f6af208e2042a2f27bc081ee908bb390b/src/System.Security.Cryptography.Encoding/src/Internal/Cryptography/Helpers.cs
加上来自
的两种方法(GenerateRandom
和WriteInt
)
然后你将有一些对 SR.*something*
的调用,你必须将其替换为一些消息,例如 "some error"
,以及必须用 [= 替换的 SR.Format
17=].
然后你将拥有(几乎)最新版本的 Rfc2898DeriveBytes
,它有一个接受参数 HashAlgorithmName.SHA256
.
这应该是最终结果:https://ideone.com/lb2Qya
我把源代码放在命名空间 My.System
中是个坏主意...坏主意...我不得不在所有命名空间前加上 global::
前缀:-(
假设您使用的是 Win7+,您可以 P/Invoke 到 BCryptDeriveKeyPBKDF2。
private static void PBKDF2(
string password,
byte[] salt,
int iterationCount,
string hashName,
byte[] output)
{
int status = SafeNativeMethods.BCryptOpenAlgorithmProvider(
out SafeNativeMethods.SafeBCryptAlgorithmHandle hPrf,
hashName,
null,
SafeNativeMethods.BCRYPT_ALG_HANDLE_HMAC_FLAG);
using (hPrf)
{
if (status != 0)
{
throw new CryptographicException(status);
}
byte[] passBytes = Encoding.UTF8.GetBytes(password);
status = SafeNativeMethods.BCryptDeriveKeyPBKDF2(
hPrf,
passBytes,
passBytes.Length,
salt,
salt.Length,
iterationCount,
output,
output.Length,
0);
if (status != 0)
{
throw new CryptographicException(status);
}
}
}
[SuppressUnmanagedCodeSecurity]
private static class SafeNativeMethods
{
private const string BCrypt = "bcrypt.dll";
internal const int BCRYPT_ALG_HANDLE_HMAC_FLAG = 0x00000008;
[DllImport(BCrypt, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
internal static extern int BCryptDeriveKeyPBKDF2(
SafeBCryptAlgorithmHandle hPrf,
byte[] pbPassword,
int cbPassword,
byte[] pbSalt,
int cbSalt,
long cIterations,
byte[] derivedKey,
int cbDerivedKey,
int dwFlags);
[DllImport(BCrypt)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
private static extern int BCryptCloseAlgorithmProvider(IntPtr hAlgorithm, int flags);
[DllImport(BCrypt, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
internal static extern int BCryptOpenAlgorithmProvider(
out SafeBCryptAlgorithmHandle phAlgorithm,
string pszAlgId,
string pszImplementation,
int dwFlags);
internal sealed class SafeBCryptAlgorithmHandle : SafeHandleZeroOrMinusOneIsInvalid
{
public SafeBCryptAlgorithmHandle() : base(true)
{
}
protected override bool ReleaseHandle()
{
return BCryptCloseAlgorithmProvider(handle, 0) == 0;
}
}
}