在.NET

时间:2018-06-11 11:18:15

标签: c# .net hash sha256 pbkdf2

我需要更新一些在.Net中使用PBKDF2实现的代码,Rfc2898DeriveBytes来散列用户凭据。 据我所知,这个功能使用SHA-1。我需要更新系统密码散列的底层散列算法以使用SHA-256(这是客户端IT-SEC要求)。

完成一些阅读之后,似乎最好继续使用Key派生函数,但是PBKDF2不允许您指定应该使用的算法,这对我来说显然是一个问题。

我们的系统使用的是.NET 4.5.1,目前不是升级的选项,我有理由相信它不是一个可以引用任何新的.NET核心的选项。我听说过包含一个新的实现PBKDF2允许您指定算法。

我想不惜一切代价避免自制的实施,因为这是Crypto-Club的第一条规则吗?

任何关于什么是最佳实践的指导将不胜感激。

由于

3 个答案:

答案 0 :(得分:1)

您现在可以指定算法msdn page

注意:自4.7.2起可用

名称可在System.Security.Cryptography.HashAlgorithmName

中找到

答案 1 :(得分:1)

假设您使用的是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;
        }
    }
}

答案 2 :(得分:0)

我会告诉你我会做什么:我会采用最新的来源(不完全是最新的,因为它使用Span<> ......只是有点旧:-)){{来自corefx github

的1}}

您需要完整的代码:

加上

中的两种方法(Rfc2898DeriveBytesGenerateRandom

然后,您有一些WriteInt的来电,您必须替换某些消息,例如SR.*something*,以及您需要替换的"some error" SR.Format

然后您将拥有(几乎)最新版本的string.Format,其中有一个构造函数可以作为参数Rfc2898DeriveBytes接受。

这应该是最终结果:https://ideone.com/lb2Qya

我错误地将源代码放在命名空间HashAlgorithmName.SHA256中......糟糕的坏主意......我必须在My.System前加上所有命名空间: - (