2014-04-21 2 views
0

샘플 응용 프로그램에서 간단한 값의 암호를 해독하는 데 문제가 있습니다. 이 값은 동일한 샘플 응용 프로그램으로 암호화되었습니다. 나는 아래 코드를 열거했다..NET AES-128 암호 해독은 빈 문자열을 반환합니다.

코드 블록이 완료되면 plain은 빈 문자열입니다. 예외는 발생하지 않습니다.

string plain = null; 

using (AesManaged alg = new AesManaged()) 
{ 
    // Extract the initialization vector from the entire ciphertext 
    byte[] IV = new byte[alg.IV.Length]; 
    Buffer.BlockCopy(cipherText, 0, IV, 0, alg.IV.Length); 

    alg.IV = IV; 
    alg.Key = GetKey(); 

    ICryptoTransform transform = alg.CreateDecryptor(); 

    // Extract the encrypted value from the entire ciphertext 
    byte[] encrypted = new byte[cipherText.Length - alg.IV.Length]; 
    Buffer.BlockCopy(cipherText, alg.IV.Length, encrypted, 0, cipherText.Length - alg.IV.Length); 

    using (MemoryStream ms = new MemoryStream(encrypted)) 
    { 
     using (CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Read)) 
     { 
      using (StreamReader r = new StreamReader(cs)) 
      { 
       cs.Flush(); 
       plain = r.ReadToEnd(); 
      } 
     } 
    } 
} 

I는 cipherText (32 바이트 바이트 [] 매개 변수로 전달 된)는 바이트 단위 동일한 값 암호화 기인 것과을 갖는 것을 확인 하였다. IV와 Key 역시 byte-for-byte입니다. 참고 : IV는 암호화 논리에 의해 암호화 된 값 앞에 추가됩니다. 이것이 첫 번째 줄이 코드 블록에서 코드를 추출하는 이유입니다.

또한 encrypted 바이트 []의 내용이 암호화 루틴에서 나오는 내용과 동일하다는 것도 확인했습니다. 내용은 단지 16 바이트입니다.

메모리 스트림 ms에있는 Position이 0임을 확인했습니다. 루틴 이후에 16이됩니다. 따라서 MemoryStream이 읽힌 것으로 보입니다. 내 의심은 내가 StreamReader을 잘못 사용하고 있지만 내가 실수 한 부분을 볼 수 없다는 것이다.

암호화 된 바이트 []의 바이트 중 하나를 수정하려고했는데 예상 한대로 CryptographicException (패딩이 유효하지 않습니다)이 표시됩니다. 따라서 암호화 관점에서 볼 때 모든 것이 IV, 키 및 암호화 된 값으로 정렬되어있는 것으로 보입니다. 웬일인지, 그것이 처리되지 않을지도 모른다?

어떤 통찰력에도 감사드립니다.

완전성을 위해 아래의 암호화 루틴 : byte [] encrypted = null;

using (AesManaged alg = new AesManaged()) 
{ 
    System.Diagnostics.Debug.WriteLine("Key size: {0}", alg.KeySize); 

    alg.GenerateIV(); 
    alg.Key = GetKey(); 

    ICryptoTransform transform = alg.CreateEncryptor(alg.Key, alg.IV); 

    using (MemoryStream ms = new MemoryStream()) 
    using (CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Write)) 
    using (StreamWriter w = new StreamWriter(cs)) 
    { 
     w.Write(plainText); 
     cs.FlushFinalBlock(); 

     // Create a byte array big enough to hold the IV and the encrypted value 
     encrypted = new byte[alg.IV.Length + ms.Length]; 
     // Copy the random generated initialization vector to the start of the encrypted bytes 
     Buffer.BlockCopy(alg.IV, 0, encrypted, 0, alg.IV.Length); 
     // Copy the encrypted value at the end 
     Buffer.BlockCopy(ms.ToArray(), 0, encrypted, alg.IV.Length, (int)ms.Length); 
    } 
} 

답변

0

제가 실수 한 것을 알아 냈습니다. 나는 매우 짧은 문자열로 테스트를하고 있었고 암호화 된 크기가 항상 16 바이트라고 이상하지 않다고 생각했습니다.

긴 문자열로 테스트했을 때 옳지 않다고 생각했습니다. 내 문제가 암호화 논리에있는 것으로 나타났습니다. CryptoStream 외에도 StreamWriter을 플러시해야했습니다. 아래는 현재 작동중인 암호화 및 암호 해독 논리입니다.

논리에 대한 추가 개선 사항은 이제 키 생성 중에 임의의 소금을 생성한다는 것이며 그 무작위 소금도 암호화 된 바이트 []에 추가된다는 점에 유의하십시오.

private const int SaltLength = 8; 

public class KeyPackage 
{ 
    public byte[] KeySalt { get; set; } 
    public byte[] Key { get; set; } 
} 

public KeyPackage GetKey() 
{ 
    // Read the password from the configuration 
    string Key = System.Configuration.ConfigurationManager.AppSettings["EncryptionKey"]; 

    // Generate Key from the password stored in configuration using a random salt 
    using (Rfc2898DeriveBytes db = new Rfc2898DeriveBytes(Key, SaltLength)) 
    { 
     // Using AES-128, we need 128/8 bytes in the key 
     return new KeyPackage() { Key = db.GetBytes(128/8), KeySalt = db.Salt }; 
    } 
} 

public byte[] GetKey(byte[] keySalt) 
{ 
    // Read the password from the configuration 
    string Key = System.Configuration.ConfigurationManager.AppSettings["EncryptionKey"]; 

    // Generate Key from the password stored in configuration using the known salt 
    using (Rfc2898DeriveBytes db = new Rfc2898DeriveBytes(Key, keySalt)) 
    { 
     // Using AES-128, we need 128/8 bytes in the key 
     return db.GetBytes(128/8); 
    } 
} 

/// <summary> 
/// Encrypts the specified plain text using the 
/// encryption key found in the configuration file. 
/// </summary> 
/// <param name="plainText">The plain text to encrypted.</param> 
/// <returns>The cipher text.</returns> 
public byte[] Encrypt(string plainText) 
{ 
    byte[] encrypted = null; 

    using (AesManaged alg = new AesManaged()) 
    { 
     System.Diagnostics.Debug.WriteLine("Key size: {0}", alg.KeySize); 

     alg.GenerateIV(); 
     KeyPackage kp = GetKey(); 
     alg.Key = kp.Key; 

     ICryptoTransform transform = alg.CreateEncryptor(); 

     using (MemoryStream ms = new MemoryStream()) 
     using (CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Write)) 
     using (StreamWriter w = new StreamWriter(cs)) 
     { 
      w.Write(plainText); 
      w.Flush(); // This was missing from my first post 
      cs.FlushFinalBlock(); 

      // Create a byte array big enough to hold the IV and the encrypted value 
      encrypted = new byte[kp.KeySalt.Length + alg.IV.Length + ms.Length]; 
      // Copy the random generated salt to the start of the encrypted bytes 
      Buffer.BlockCopy(kp.KeySalt, 0, encrypted, 0, kp.KeySalt.Length); 
      // Copy the random generated initialization vector to the start of the encrypted bytes 
      Buffer.BlockCopy(alg.IV, 0, encrypted, kp.KeySalt.Length, alg.IV.Length); 
      // Copy the encrypted value at the end 
      Buffer.BlockCopy(ms.ToArray(), 0, encrypted, alg.IV.Length + kp.KeySalt.Length, (int)ms.Length); 
     } 
    } 
    return encrypted; 
} 

/// <summary> 
/// 
/// </summary> 
/// <param name="cipherText"></param> 
/// <returns></returns> 
public string Decrypt(byte[] cipherText) 
{ 
    string plain = null; 

    using (AesManaged alg = new AesManaged()) 
    { 
     // Extract the initialization vector from the entire ciphertext 
     byte[] IV = new byte[alg.IV.Length]; 
     byte[] KeySalt = new byte[SaltLength]; 

     Buffer.BlockCopy(cipherText, 0, KeySalt, 0, SaltLength); 
     Buffer.BlockCopy(cipherText, SaltLength, IV, 0, alg.IV.Length); 

     alg.IV = IV; 
     alg.Key= GetKey(KeySalt); 

     ICryptoTransform transform = alg.CreateDecryptor(); 

     // Extract the encrypted value from the entire ciphertext 
     int ActualCipherLength = cipherText.Length - alg.IV.Length - SaltLength; 
     byte[] encrypted = new byte[ActualCipherLength]; 
     Buffer.BlockCopy(cipherText, alg.IV.Length + SaltLength, encrypted, 0, ActualCipherLength); 

     using (MemoryStream ms = new MemoryStream(encrypted)) 
     using (CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Read)) 
     using (StreamReader r = new StreamReader(cs)) 
     { 
      plain = r.ReadToEnd(); 
     } 
    } 
    return plain; 
} 
} 
관련 문제