2009-03-02 3 views
26

AesManaged에서 간단한 암호화/암호 해독 작업을 수행하려고하는데 암호 해독 스트림을 닫으려고 할 때 예외가 계속 발생합니다. 여기서 문자열은 올바르게 암호화되고 해독 된 다음 Console.WriteLine이 올바른 문자열을 출력 한 후 "Padding was invalid and can not be removed"라는 CryptographicException이 발생합니다.AesManaged를 사용하여 "채우기가 잘못되었습니다. 제거 할 수 없습니다."

아이디어가 있으십니까?

MemoryStream ms = new MemoryStream(); 
byte[] rawPlaintext = Encoding.Unicode.GetBytes("This is annoying!"); 

using (Aes aes = new AesManaged()) 
{ 
    aes.Padding = PaddingMode.PKCS7; 
    aes.Key = new byte[128/8]; 
    aes.IV = new byte[128/8]; 

    using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), 
              CryptoStreamMode.Write)) 
    { 
    cs.Write(rawPlaintext, 0, rawPlaintext.Length); 
    cs.FlushFinalBlock(); 
    } 

    ms = new MemoryStream(ms.GetBuffer()); 
    using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), 
              CryptoStreamMode.Read)) 
    { 
    byte[] rawData = new byte[rawPlaintext.Length]; 
    int len = cs.Read(rawData, 0, rawPlaintext.Length); 
    string s = Encoding.Unicode.GetString(rawData); 
    Console.WriteLine(s); 
    } 
} 

답변

44

트릭은 MemoryStream.ToArray()을 사용하는 것입니다. 또한 코드를 변경하여 CryptoStream을 사용하여 암호화하고 해독하는 방식으로 작성합니다. using() 문에 명시되어 있기 때문에 CryptoStream.FlushFinalBlock()에 명시 적으로 전화 할 필요가 없습니다. 플러시는 Dispose()에서 발생합니다. 다음은 나를 위해 일한다.

byte[] rawPlaintext = System.Text.Encoding.Unicode.GetBytes("This is all clear now!"); 

using (Aes aes = new AesManaged()) 
{ 
    aes.Padding = PaddingMode.PKCS7; 
    aes.KeySize = 128;   // in bits 
    aes.Key = new byte[128/8]; // 16 bytes for 128 bit encryption 
    aes.IV = new byte[128/8]; // AES needs a 16-byte IV 
    // Should set Key and IV here. Good approach: derive them from 
    // a password via Cryptography.Rfc2898DeriveBytes 
    byte[] cipherText= null; 
    byte[] plainText= null; 

    using (MemoryStream ms = new MemoryStream()) 
    { 
     using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write)) 
     { 
      cs.Write(rawPlaintext, 0, rawPlaintext.Length); 
     } 

     cipherText= ms.ToArray(); 
    } 


    using (MemoryStream ms = new MemoryStream()) 
    { 
     using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write)) 
     { 
      cs.Write(cipherText, 0, cipherText.Length); 
     } 

     plainText = ms.ToArray(); 
    } 
    string s = System.Text.Encoding.Unicode.GetString(plainText); 
    Console.WriteLine(s); 
} 

또한, 난 당신이 명시 적으로 AesManaged 인스턴스의 Mode 설정할 알고 생각하고, 비밀번호와 소금의 키와 IV를 유도하기 위해 System.Security.Cryptography.Rfc2898DeriveBytes를 사용합니다.

참조 :
- AesManaged

+4

동일한 문제가 있었지만 RijndaelManaged (대칭)를 사용하여 어떤 일이 일어나고 있는지 전혀 알 수 없었습니다. 그'MemoryStream.GetBuffer()'가 * unflushed * 버전의 데이터를 얻었고, 마지막 데이터 블록의 대부분이 널 (null) 이었기 때문에 내 패딩이 엉망이었습니다. 'MemoryStream.ToArray()'는 실제 배열을 얻습니다. 이 솔루션에 대한 많은 감사를드립니다! – Codesleuth

+0

이것은 지금까지 보아온 가장 우수하거나 작은 구현입니다. – tmanthey

+1

'Dispose'에 호의를 표합니다. CryptoStream을 삭제하기 전에'ms.ToArray() '를 호출했습니다. 그 라인을 사용하여 바깥쪽으로 옮기는 것은 나를 위해 그것을 고쳤다. – cadrell0

1

바이트 [] = RAWDATA 새로운 바이트 [rawPlaintext.Length];

필요한 패딩 (IIRC, 몇 년 동안)이 포함 된 버퍼의 길이를 읽어야합니다.

21

이 예외 암호화 파라미터의 수 중 어느 하나의 불일치에 의해 야기 될 수있다.

Security.Cryptography.Debug 인터페이스를 사용하여 암호화/암호 해독 방법에 사용 된 모든 매개 변수를 추적했습니다.

마지막으로, Key을 설정하여 클래스가 무작위 키를 다시 생성하고 처음에 설정 한 키를 사용하지 않도록 설정 한 후에 KeySize 속성을 설정했다는 것을 알게되었습니다.

+4

내 문제는 키를 설정 한 후에도 KeySize를 설정했습니다. 감사합니다. –

+2

+1 고맙습니다. 할 수만 있다면 100 번 투표 할 수 있습니다. 내가 왜 제대로 해독 할 수 없었는지 알아 내려고 노력한 결과, 코드에서 키 다음에 키 크기를 설정하는 것으로 나타났습니다. – LeopardSkinPillBoxHat

+0

고마워요,이게 내 문제를 해결했습니다 –

1

실제로 MemoryStream.GetBuffer는이 버퍼의 실제 데이터가 아니라 할당 된 버퍼를 반환합니다. 이 경우 256 바이트 버퍼를 반환하지만 32 바이트의 암호화 된 데이터 만 포함합니다.