如何在我的盐和盐中使用SHA-512和Rfc2898DeriveBytes;哈希码?

时间:2014-09-17 19:42:23

标签: c# hash cryptography salt sha

我对密码学来说是全新的,但学习。我已经在线研究了许多不同的建议,并且已经创建了我自己的类来处理相关数据的哈希,盐,键拉伸和比较/转换。

在研究了用于加密的内置.NET库之后,我发现我所拥有的只是SHA-1。但我得出的结论是,它不坏,因为我使用了哈希过程的多次迭代。这是对的吗?

但如果我想从更强大的SHA-512开始,我怎么能在下面的代码中实现它?提前谢谢。

using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography;

public class CryptoSaltAndHash
{
    private string strHash;
    private string strSalt;
    public const int SaltSizeInBytes = 128;
    public const int HashSizeInBytes = 1024;
    public const int Iterations = 3000;

    public string Hash { get { return strHash; } }
    public string Salt { get { return strSalt; } }

    public CryptoSaltAndHash(SecureString ThisPassword)
    {
        byte[] bytesSalt = new byte[SaltSizeInBytes];
        using (RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider())
        {
            crypto.GetBytes(bytesSalt);
        }
        strSalt = Convert.ToBase64String(bytesSalt);
        strHash = ComputeHash(strSalt, ThisPassword);
    }

    public static string ComputeHash(string ThisSalt, SecureString ThisPassword)
    {
        byte[] bytesSalt = Convert.FromBase64String(ThisSalt);
        Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(
            convertSecureStringToString(ThisPassword), bytesSalt, Iterations);
        using (pbkdf2)
        {
            return Convert.ToBase64String(pbkdf2.GetBytes(HashSizeInBytes));
        }
    }

    public static bool Verify(string ThisSalt, string ThisHash, SecureString ThisPassword)
    {
        if (slowEquals(getBytes(ThisHash), getBytes(ComputeHash(ThisSalt, ThisPassword))))
        {
            return true;
        }
        return false;
    }

    private static string convertSecureStringToString(SecureString MySecureString)
    {
        IntPtr ptr = IntPtr.Zero;
        try
        {
            ptr = Marshal.SecureStringToGlobalAllocUnicode(MySecureString);
            return Marshal.PtrToStringUni(ptr);
        }
        finally
        {
            Marshal.ZeroFreeGlobalAllocUnicode(ptr);
        }
    }

    private static bool slowEquals(byte[] A, byte[] B)
    {
        int intDiff = A.Length ^ B.Length;
        for (int i = 0; i < A.Length && i < B.Length; i++)
        {
            intDiff |= A[i] ^ B[i];
        }
        return intDiff == 0;
    }

    private static byte[] getBytes(string MyString)
    {
        byte[] b = new byte[MyString.Length * sizeof(char)];
        System.Buffer.BlockCopy(MyString.ToCharArray(), 0, b, 0, b.Length);
        return b;
    }
}

注意:我引用了https://crackstation.net/hashing-security.htm的许多做法。 slowEquals比较方法是通过阻止分支来规范化执行时间。 SecureString的用法是在此类与我的Web应用程序中的其他类和页面之间传递加密形式的密码。虽然这个网站将通过HTTPS进行,但为了确保事情尽可能安全,同时仍然在合理范围内,我们总是很高兴。

在我的代码中,我将密钥字符串设置为128个字节(虽然它有时变大,这很好),散列大小为1KB,迭代次数为3,000。它比典型的64字节盐,512字节散列和1,000或2,000次迭代略大,但是再次登录速度和应用程序性能是一个极低的优先级。

思想?

3 个答案:

答案 0 :(得分:10)

  1. 3000次迭代非常低。即使10000也很低。但是,您需要通过尝试经常登录来增加额外迭代的安全性,以抵御攻击者对您的服务器造成的风险,这会为每次尝试触发昂贵的哈希值。
  2. 大于128位/ 16字节的盐没有意义。盐应该是独一无二的,仅此而已。
  3. 大于本机大小的哈希大小(SHA-1为20个字节)会降低防御者的性能,但不会降低攻击者的性能。因为这意味着您可以承受更少的迭代,实际上会削弱安全性。

    例如,与具有3000次迭代的1024字节散列相同的成本,你可以提供20个字节的散列,156000次迭代,这是破解成本的52倍。

  4. 要使用SHA-2,您需要一个完全不同的PBKDF2实现,.net中包含的实现是硬编码使用SHA-1。

    如果您懒得使用第三方库,我宁愿使用bcrypt库,因为这对基于GPU的攻击者要强得多。

  5. 您的API难以使用,因为您将盐管理推送到调用方而不是在Create / Verify函数中处理它。

  6. 使用SecureString然后将其转换为String是愚蠢的。这抵消了首先使用SecureString的全部意义。

    就个人而言,我不会在典型的应用程序中使用SecureString。只有将它与广泛的整体堆栈安全性审核相结合才有意义,该检查会检查密码是否永远不会存储在String中,并且一旦不再需要,就会从可变存储中删除。

  7. 我不会在实例变量中存储密码/ salt。只需将它们保留在相关功能的本地。我只在实例变量中存储配置(例如迭代计数)。

  8. 虽然SHA-1以加密方式被削弱,但攻击会产生冲突。对于密码哈希冲突是无关紧要的,您关心的是第一次预映像攻击。在这方面,SHA-1仍然非常强大。

    SHA-512的主要优势并不在于它的加密性更强(尽管它是),因为防御者可能会使用64位Intel CPU来提供快速64位,因此64位算术比攻击者花费更多。位算术。

答案 1 :(得分:6)

回答问题:从“SecurityDriven.NET”书中下载免费代码示例。找到 PBKDF2 类,其中包含 HMAC 工厂。 HMACSHA512 工厂可供选择。

由于您不熟悉加密技术,我还强烈建议您阅读本书(例如,完全理解CodesInChaos所做的观点)。

答案 2 :(得分:4)

如果有人通过搜索遇到这个问题,现在Microsoft提供了Microsoft.AspNetCore.Cryptography.KeyDerivation NuGet包,它允许将PBKDF2与SHA-256和SHA-512哈希函数一起使用。文档可在docs.microsoft.com获得。