C# 如何在salt&;中使用SHA-512和Rfc2898DeriveBytes;散列码?
我对密码学是个新手,但是学习。我从网上的研究中收集了许多不同的建议,并制作了自己的类,用于处理哈希、salt、键拉伸以及关联数据的比较/转换 在研究了内置的.NET密码学库之后,我发现我拥有的仍然只有SHA-1。但我得出的结论是,这并不坏,因为我使用了哈希过程的多次迭代。对吗 但如果我想从更健壮的SHA-512开始,我如何在下面的代码中实现它呢?提前谢谢C# 如何在salt&;中使用SHA-512和Rfc2898DeriveBytes;散列码?,c#,hash,cryptography,salt,sha,C#,Hash,Cryptography,Salt,Sha,我对密码学是个新手,但是学习。我从网上的研究中收集了许多不同的建议,并制作了自己的类,用于处理哈希、salt、键拉伸以及关联数据的比较/转换 在研究了内置的.NET密码学库之后,我发现我拥有的仍然只有SHA-1。但我得出的结论是,这并不坏,因为我使用了哈希过程的多次迭代。对吗 但如果我想从更健壮的SHA-512开始,我如何在下面的代码中实现它呢?提前谢谢 using System; using System.Runtime.InteropServices; using System.Securi
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;
}
}
使用系统;
使用System.Runtime.InteropServices;
使用系统安全;
使用System.Security.Cryptography;
公共类CryptoSaltAndHash
{
私有字符串strHash;
私有字符串strSalt;
公共常数int SaltSizeInBytes=128;
公共常量int HashSizeInBytes=1024;
公共常数int迭代次数=3000;
公共字符串哈希{get{return strHash;}}
公共字符串Salt{get{return strSalt;}}
公共CryptoSaltAndHash(SecureString ThisPassword)
{
byte[]bytesSalt=新字节[SaltSizeInBytes];
使用(RNGCryptoServiceProvider crypto=new RNGCryptoServiceProvider())
{
加密.GetBytes(bytesSalt);
}
strSalt=Convert.ToBase64String(bytesSalt);
strHash=ComputeHash(strSalt,ThisPassword);
}
公共静态字符串ComputeHash(字符串ThisSalt、SecureString ThisPassword)
{
字节[]bytesSalt=Convert.FromBase64String(ThisSalt);
Rfc2898DeriveBytes pbkdf2=新的Rfc2898DeriveBytes(
convertSecureStringToString(此密码)、bytesSalt、迭代);
使用(pbkdf2)
{
返回Convert.ToBase64String(pbkdf2.GetBytes(HashSizeInBytes));
}
}
公共静态bool验证(字符串ThisSalt、字符串ThisHash、安全字符串ThisPassword)
{
if(slowEquals(getBytes(ThisHash)、getBytes(ComputeHash(ThisSalt、ThisPassword)))
{
返回true;
}
返回false;
}
私有静态字符串转换器SecureStringToString(SecureString MySecureString)
{
IntPtr ptr=IntPtr.0;
尝试
{
ptr=封送。SecureStringToGlobalAllocUnicode(MySecureString);
返回Marshal.PtrToStringUni(ptr);
}
最后
{
ZeroFreeGlobalAllocUnicode元帅(ptr);
}
}
专用静态bool slowEquals(字节[]A,字节[]B)
{
int intDiff=A.长度^B.长度;
对于(int i=0;i
注意:我已经参考了许多来自的实践。slowEquals比较方法是通过防止分支来规范执行时间。SecureString的用途是在这个类和我的web应用程序中的其他类和页面之间有一个加密形式的密码传递。虽然这个网站将通过HTTPS,但在合理的范围内,尽可能多地确保事情尽可能安全总是很好的
在我的代码中,我将密钥字符串设置为128字节(尽管有时会变大,这很好),哈希大小设置为1KB,迭代次数设置为3000。它比典型的64字节salt、512字节hash和1000或2000次迭代稍微大一点,但登录速度和应用程序性能的优先级非常低
想法
Create
/Verify
函数中处理它SecureString
然后将其转换为String
是愚蠢的。这抵消了首先使用SecureString
的全部意义
就我个人而言,我不会在典型应用程序中使用SecureString
。只有将它与广泛的全堆栈安全性检查结合起来,检查密码是否从未存储在字符串中,并且在不再需要密码时总是从可变存储中删除密码,这才是值得的