저는 완전히 암호화에 익숙하지 만 배우고 있습니다. 저는 온라인에서 저의 연구 결과를 여러 가지 방법으로 결합 해 해시, 소금, 키 스트레칭 및 관련 데이터의 비교/변환을 처리하기위한 자체 클래스를 만들었습니다.소금 & 해시 코드에서 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 바이트 (가끔은 더 커지더라도 괜찮습니다), 해시 크기를 1KB로, 반복 횟수를 3,000으로 설정했습니다. 일반적인 64 바이트 소금, 512 바이트 해시 및 1,000 회 또는 2,000 회 반복보다 약간 크지 만 로그인 속도와 앱 성능은 매우 낮은 우선 순위입니다.
생각하십니까?
코드 검토에 관한 비슷한 질문 [보안 암호 해싱] (http://codereview.stackexchange.com/questions/32856/secure-password-hashing) – CodesInChaos