Я совершенно новый для криптографии, но обучения. Я собрал много разных предложений из моего исследования в Интернете и сделал свой собственный класс для обработки хеша, соли, растяжения клавиш и сравнения/преобразования связанных данных.Как использовать SHA-512 с Rfc2898DeriveBytes в моем солевом и хеш-коде?
После изучения встроенной библиотеки .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 заключается в том, чтобы зашифрованная форма пароля проходила между этим классом и другими классами и страницами в моем веб-приложении. Хотя этот сайт будет зависеть от HTTPS, всегда приятно пройти лишнюю милю, чтобы обеспечить безопасность как можно безопаснее, пока все еще находится в пределах разумного.
В моем коде я установил ключевую строку на 128 байт (хотя иногда она увеличивается, а это нормально), размер хэша до 1 Кбайт и количество итераций в 3000. Это немного больше, чем типичная 64-байтовая соль, 512-байтовый хеш и 1000 или 2 000 итераций, но опять же скорость входа в систему и производительность приложения - чрезвычайно низкий приоритет.
Мысли?
Аналогичный вопрос при проверке кода: [Безопасное шифрование пароля] (http://codereview.stackexchange.com/questions/32856/secure-password-hashing) – CodesInChaos