2011-02-15 3 views
1
class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.WriteLine("Sergio"); 
     Console.WriteLine(HashString("Sergio")); 
     Console.WriteLine(HashString("Sergio")); 
     Console.WriteLine(HashString("Sergio")); 
     Console.ReadKey(); 
    } 

    public static string HashString(string value) 
    { 
     int minSaltSize = 4; 
     int maxSaltSize = 8; 
     Random random = new Random(); 
     int saltSize = random.Next(minSaltSize, maxSaltSize); 
     byte[] saltBytes = new byte[saltSize]; 

     RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); 
     rng.GetNonZeroBytes(saltBytes); 

     //Convert the string value into a byte array. 
     UTF8Encoding utf8Encoder = new UTF8Encoding(); 
     byte[] plainTextBytes = utf8Encoder.GetBytes(value); 

     //Allocate an array to hold the text bytes and the salt bytes. 
     byte[] plainTextWithSaltBytes = new Byte[saltBytes.Length + plainTextBytes.Length]; 

     for (int i = 0; i < plainTextBytes.Length; i++) 
     { 
      plainTextWithSaltBytes[i] = plainTextBytes[i]; 
     } 

     for (int i = 0; i < saltBytes.Length; i++) 
     { 
      plainTextWithSaltBytes[plainTextBytes.Length + i] = saltBytes[i]; 
     } 

     HashAlgorithm hash = new SHA256Managed(); 
     byte[] hashBytes = hash.ComputeHash(plainTextWithSaltBytes); 
     string hashedValue = Convert.ToBase64String(hashBytes); 
     return hashedValue; 
    } 
} 

내 코드의 결과는 해시 된 "Sergio"가 항상 다릅니다. 이것은 소금에 포함 된 임의의 요인에 의해 발생합니다. 내 질문은 내가 소금을 어딘가에 저장해야한다는거야? 아니면 내 코드에 상수를 정의합니까?암호를 해싱 할 때 소금을 어딘가에 저장해야합니까?

감사합니다.

+0

안녕하세요, 나는 당신이 그것을 알아야하거나 당신이 그것을 저장해야하거나 당신이 어딘가에 저장된 고정 값에 의존해야한다고 말하고 싶습니다. –

+4

그러한 코드를 직접 작성하면 안됩니다. 전문가조차도이를 망쳐 놓는다. 이미 검증 된 상용 인증 공급자를 사용하십시오. 바퀴의 재발견은 일반적으로 소프트웨어에서는 좋지 않지만 치명적일 수 있습니다. 귀하의 앱이 다음 Gawker가되지 않도록하십시오! –

+0

@Craig : 하하하, 사실. 그러나 나는 항상 사물이 어떻게 작동하는지, 심지어 표면적 인 수준에서도 배우는 것을 좋아합니다. 어느 쪽이든 upvote. –

답변

0

나는 해시에 대한 소금과 SHA512에 대한 GUID를의 팬이 됐어요 . CPU 시간은 인증 중에 만 있기 때문에 문제가되지 않습니다.

예, 들어오는 비밀번호에 추가 할 수 있도록 해쉬를 저장해야합니다.

storedpassword = 해시 (소금 + 비밀번호)는 소금을 잊어 버린 경우

, 당신은 값을 비교할 수 없습니다.

+1

실제로, 빠른 해시를 사용하지 않는 것이 좋은 이유가 있습니다. –

1

다른 소금을 사용하고 있다면 해시 된 암호와 소금을 db에 저장하는 것이 좋습니다. 소금이 같은 경우 app.config/web.config 파일에 소금을 저장하도록 선택할 수도 있습니다.

+2

같은 소금을 사용하는 것은 좋지 않습니다. 이는 기본적으로 소금의 목적을 부분적으로 무효화합니다 (암호 당 한 번이 아닌 모든 암호에 대해 한 번 사전을 반복 할 수있게하므로). 응용 프로그램 특정 소금을 사용하려면, 좋습니다. 그러나 사용자 당 소금도 사용하십시오 ('hash (password + userSalt + appSalt)') ... – ircmaxell

1

해시를 다시 계산할 때 같은 소금을 사용해야하므로 소금을 저장해야합니다. 그러나 소금의 효과가 줄어들 기 때문에 상수를 사용하고 싶지 않습니다.

0

절대적으로. 항상 해시 된 암호와 상수가 아닌 새로운 소금을 사용하십시오. 모든 암호에 대해 동일한 소금을 사용하면 안전하지 않을 수 있습니다 (defense against rainbow tables).

예 : 데이터베이스 필드에 추가 필드를 추가 할 수없는 경우 추가 필드의 데이터베이스 또는 해시 된 암호가있는 동일한 필드의 경우에도 마찬가지입니다 (예 : bcrypt).

그러나 항상 암호 당 새로운 임의의 소금을 사용하십시오.

1

당신은 소금/해시를 만들려면이 클래스를 사용하고 함께 두 개의 값을 결합 할 수 있습니다 :

public sealed class PasswordHash 
{ 
    const int SaltSize = 16, HashSize = 20, HashIter = 10000; 
    readonly byte[] _salt, _hash; 
    public PasswordHash(string password) 
    { 
     new RNGCryptoServiceProvider().GetBytes(_salt = new byte[SaltSize]); 
     _hash = new Rfc2898DeriveBytes(password, _salt, HashIter).GetBytes(HashSize); 
    } 
    public PasswordHash(byte[] hashBytes) 
    { 
     Array.Copy(hashBytes, 0, _salt = new byte[SaltSize], 0, SaltSize); 
     Array.Copy(hashBytes, SaltSize, _hash = new byte[HashSize], 0, HashSize); 
    } 
    public PasswordHash(byte[] salt, byte[] hash) 
    { 
     Array.Copy(salt, 0, _salt = new byte[SaltSize], 0, SaltSize); 
     Array.Copy(hash, 0, _hash = new byte[HashSize], 0, HashSize); 
    } 
    public byte[] ToArray() 
    { 
     byte[] hashBytes = new byte[SaltSize + HashSize]; 
     Array.Copy(_salt, 0, hashBytes, 0, SaltSize); 
     Array.Copy(_hash, 0, hashBytes, SaltSize, HashSize); 
     return hashBytes; 
    } 
    public byte[] Salt { get { return (byte[])_salt.Clone(); } } 
    public byte[] Hash { get { return (byte[])_hash.Clone(); } } 
    public bool Verify(string password) 
    { 
     byte[] test = new Rfc2898DeriveBytes(password, _salt, HashIter).GetBytes(HashSize); 
     for (int i = 0; i &lt; HashSize; i++) 
      if (test[i] != _hash[i]) 
       return false; 
     return true; 
    } 
} 

http://csharptest.net/?p=470

관련 문제