gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 19:53:42 35 4
gpt4 key购买 nike

我对密码学完全陌生,但正在学习。我从我的在线研究中收集了许多不同的建议,并创建了我自己的类来处理哈希、salt、 key 拉伸(stretch)以及相关数据的比较/转换。

在研究了用于密码学的内置 .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,但在合理的范围内尽最大努力确保事情尽可能安全总是好的。

在我的代码中,我将 key 字符串设置为 128 字节(尽管它有时会变大,这很好),哈希大小设置为 1KB,迭代次数设置为 3,000。它比典型的 64 字节盐、512 字节哈希和 1,000 或 2,000 次迭代稍大,但登录速度和应用程序性能再次成为极低的优先级。

想法?

最佳答案

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

    例如,与具有 3000 次迭代的 1024 字节哈希的成本相同,您可以负担得起具有 156000 次迭代的 20 字节哈希,其破解成本要高出 52 倍。

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

    如果您费心使用第三方库,我宁愿使用 bcrypt 库,因为它对基于 GPU 的攻击者的抵抗力要强得多。

  5. 您的 API 使用起来很尴尬,因为您将 salt 管理推给了调用者,而不是在 Create/Verify 函数中处理它。

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

    就我个人而言,我不会在典型的应用程序中使用 SecureString。只有当您将它与广泛的全栈安全审查相结合时,它才有值(value),检查密码是否从未存储在 String 中,并且在不再需要时始终从可变存储中删除。

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

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

    SHA-512 的主要优势不是它的加密强度更高(尽管它确实如此),而是 64 位算法对攻击者的成本高于防御者,因为防御者可能会使用 64 位 Intel CPU,它提供快速的 64位运算。

关于c# - 如何在我的盐和哈希代码中使用 SHA-512 和 Rfc2898DeriveBytes?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25899014/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com