2013-10-29 2 views
0

시드 값에서 암호 학적으로 강한 임의의 바이트 시퀀스를 생성하면 어떻게됩니까 (동일한 시드로부터 시퀀스를 다시 생성 할 수 있도록)? 거기에 C#에서 구현할 수있는 좋은 CSPRNG 알고리즘이 있습니까 (좋은 문서가 좋음).시드 (seed)에서 임의로 암호화 된 강력한 시퀀스를 생성하려면 어떻게해야합니까?

Niether Random가 강력하게 암호화하지 않고 RNGCryptoServiceProvider 당신이 시드 값을 설정하도록 허용하지 않습니다 때문에 RNGCryptoServiceProvider 또는 Random 클래스는, 내 한 요구 사항을 충족합니다.

+1

테스트 용이라고 가정합니다. 잘 알려진 일련의 숫자를 반환하는 특수 구현을 사용하지 않는 이유는 무엇입니까? 나는 씨앗을 기반으로 서로 다른 시퀀스를 생성해야하기 때문에 –

+0

@AlexeiLevenkov (그렇지 않으면 어떻게 반복 순서는? "강력한 암호"가 될 수 있습니다.) 'Random' 클래스는 암호 학적으로 강하면 괜찮을 것입니다. – Sam

+0

암호로 안전한 랜덤 제네레이터는 숫자를 예측할 수 없다는 것을 의미합니다. 또한, 숫자 (또는 바이트) [임의 수 없습니다] (http://xkcd.com/221/) - 발전기입니다. – ntoskrnl

답변

1

Rfc2898DeriveBytes은 작업에 가장 적합하며 대부분 암호 해싱 기능으로 사용되지만 원하는만큼의 바이트를 요청할 수 있으며 주어진 시드에 대해 동일한 일련의 바이트를 항상 반환합니다 비밀 번호, 소금 및 반복 횟수의 조합)

Rfc2898DeriveBytes의 두 인스턴스를 보여주는 예제는 다음과 같습니다. 첫 번째 시퀀스를 사용하여 대칭 암호화로 데이터 블록을 암호화하고 그것을 해독하는 두 번째 시퀀스).

using System; 
using System.IO; 
using System.Text; 
using System.Security.Cryptography; 

public class rfc2898test 
{ 
    // Generate a key k1 with password pwd1 and salt salt1. 
    // Generate a key k2 with password pwd1 and salt salt1. 
    // Encrypt data1 with key k1 using symmetric encryption, creating edata1. 
    // Decrypt edata1 with key k2 using symmetric decryption, creating data2. 
    // data2 should equal data1. 

    private const string usageText = "Usage: RFC2898 <password>\nYou must specify the password for encryption.\n"; 
    public static void Main(string[] passwordargs) 
    { 
     //If no file name is specified, write usage text. 
     if (passwordargs.Length == 0) 
     { 
      Console.WriteLine(usageText); 
     } 
     else 
     { 
      string pwd1 = passwordargs[0]; 
      // Create a byte array to hold the random value. 
      byte[] salt1 = new byte[8]; 
      using (RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider()) 
      { 
       // Fill the array with a random value. 
       rngCsp.GetBytes(salt1); 
      } 

      //data1 can be a string or contents of a file. 
      string data1 = "Some test data"; 
      //The default iteration count is 1000 so the two methods use the same iteration count. 
      int myIterations = 1000; 
      try 
      { 
       Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(pwd1, salt1, myIterations); 
       Rfc2898DeriveBytes k2 = new Rfc2898DeriveBytes(pwd1, salt1); 
       // Encrypt the data. 
       TripleDES encAlg = TripleDES.Create(); 
       encAlg.Key = k1.GetBytes(16); 
       MemoryStream encryptionStream = new MemoryStream(); 
       CryptoStream encrypt = new CryptoStream(encryptionStream, encAlg.CreateEncryptor(), CryptoStreamMode.Write); 
       byte[] utfD1 = new System.Text.UTF8Encoding(false).GetBytes(data1); 

       encrypt.Write(utfD1, 0, utfD1.Length); 
       encrypt.FlushFinalBlock(); 
       encrypt.Close(); 
       byte[] edata1 = encryptionStream.ToArray(); 
       k1.Reset(); 

       // Try to decrypt, thus showing it can be round-tripped. 
       TripleDES decAlg = TripleDES.Create(); 
       decAlg.Key = k2.GetBytes(16); 
       decAlg.IV = encAlg.IV; 
       MemoryStream decryptionStreamBacking = new MemoryStream(); 
       CryptoStream decrypt = new CryptoStream(decryptionStreamBacking, decAlg.CreateDecryptor(), CryptoStreamMode.Write); 
       decrypt.Write(edata1, 0, edata1.Length); 
       decrypt.Flush(); 
       decrypt.Close(); 
       k2.Reset(); 
       string data2 = new UTF8Encoding(false).GetString(decryptionStreamBacking.ToArray()); 

       if (!data1.Equals(data2)) 
       { 
        Console.WriteLine("Error: The two values are not equal."); 
       } 
       else 
       { 
        Console.WriteLine("The two values are equal."); 
        Console.WriteLine("k1 iterations: {0}", k1.IterationCount); 
        Console.WriteLine("k2 iterations: {0}", k2.IterationCount); 
       } 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine("Error: ", e); 
      } 

     } 
    } 
} 
+0

iterations = 1에서는 매우 느리고 1000 회 반복하면 느려집니다. 중요한 반복 횟수로 PBKDF2에서 20 바이트를 초과하여 소비하는 경우 잘못된 결과가 발생할 수 있습니다. – CodesInChaos