Tôi hoàn toàn mới về mật mã, nhưng học tập. Tôi đã ghép nối nhiều đề xuất khác nhau từ nghiên cứu trực tuyến của mình và đã tạo lớp riêng để xử lý băm, muối, kéo dài khóa và so sánh/chuyển đổi dữ liệu được liên kết.Làm cách nào để sử dụng SHA-512 với Rfc2898DeriveBytes trong mã muối và mã băm của tôi?
Sau khi nghiên cứu thư viện .NET tích hợp để mã hóa, tôi phát hiện ra rằng những gì tôi có vẫn chỉ là SHA-1. Nhưng tôi đi đến kết luận rằng nó không phải là xấu vì tôi đang sử dụng nhiều lần lặp của quá trình băm. Đúng không?
Nhưng nếu tôi muốn bắt đầu với SHA-512 mạnh hơn, làm cách nào tôi có thể triển khai mã trong mã dưới đây? Cảm ơn trước.
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;
}
}
Lưu ý: Tôi đã tham chiếu nhiều thực tiễn từ https://crackstation.net/hashing-security.htm. Phương thức so sánh slowEquals là bình thường hóa thời gian thực thi bằng cách ngăn chặn phân nhánh. Việc sử dụng SecureString là phải có một dạng mã hóa mật khẩu được chuyển giữa lớp này và các lớp và trang khác trong ứng dụng web của tôi. Mặc dù trang web này sẽ qua HTTPS, nhưng bạn nên sử dụng thêm dặm để đảm bảo mọi thứ an toàn nhất có thể trong khi vẫn đang trong vòng lý do.
Trong mã của mình, tôi đã đặt chuỗi khóa thành 128 byte (mặc dù nó phát triển lớn hơn đôi khi, đó là tốt), kích thước băm thành 1KB và số lần lặp lại là 3.000. Nó lớn hơn một chút so với muối 64 byte điển hình, băm 512 byte và 1.000 hoặc 2.000 lần lặp lại, nhưng sau đó lại có tốc độ đăng nhập và hiệu suất ứng dụng là ưu tiên cực kỳ thấp.
Suy nghĩ?
Câu hỏi tương tự về đánh giá mã: [Mật khẩu băm an toàn] (http://codereview.stackexchange.com/questions/32856/secure-password-hashing) – CodesInChaos