2017-12-11 25 views
1

C#でデータを暗号化および復号化する簡単なクラスをテストしようとしています。スタックと埋め込みが無効であり、削除できません。AES PKCS7

Message: System.Security.Cryptography.CryptographicException : Padding is invalid and cannot be removed. 

`

{ [TestFixture] 
    public class CryptTest 
    { 
     [Test] 
     public void TestMethod() 
     { 
      String text = "Hello World!"; 

      String crypt = EncryptionService.Encrypt(text, Config.KEY_STRING); 
      Console.WriteLine(crypt); 
      String clear = EncryptionService.Decrypt(crypt, Config.KEY_STRING); 
      Console.WriteLine(clear); 
      Assert.That(clear, Is.EqualTo(text)); 


     } 

は`しかし、私は次の例外を受け付けております

 StackTrace " at System.Security.Cryptography.CapiSymmetricAlgorithm.DepadBlock(Byte[] block, Int32 offset, Int32 count)\r\n at System.Security.Cryptography.CapiSymmetricAlgorithm.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)\r\n at System.Security.Cryptography.CryptoStream.Read(Byte[] buffer, Int32 offset, Int32 count)\r\n at System.IO.StreamReader.ReadBuffer()\r\n at System.IO.StreamReader.ReadToEnd()\r\n at InsuranceMidAm.Services.EncryptionService.Decrypt(String cipher, String key) in C:\\Visual Studio Projects\\InsuranceMidAm\\InsuranceMidAm\\Services\\EncryptionService.cs:line 72\r\n at InsuranceMidAm.Tests.CryptTest.TestMethod() in C:\\Visual Studio Projects\\InsuranceMidAm\\InsuranceMidAm.Tests\\CryptTest.cs:line 20" string 

これは、テスト対象のクラスです:

namespace InsuranceMidAm.Services 
{ 
    public class EncryptionService 
    { 
     // Reference: https://stackoverflow.com/questions/273452/using-aes-encryption-in-c-sharp 
     public static String Encrypt(String text, String key) 
     { 

      byte[] value = UTF8Encoding.UTF8.GetBytes(text); 
      byte[] crypt; 
      byte[] iv; 
      using (Aes myAes = Aes.Create()) 
      { 

       myAes.KeySize = 256; 
       myAes.Mode = CipherMode.CBC; 
       myAes.Key = HexToBin(key); 
       myAes.GenerateIV(); 
       myAes.Padding = PaddingMode.PKCS7; 

       using (MemoryStream ms = new MemoryStream()) 
       { 
        using (CryptoStream cs = new CryptoStream(ms, myAes.CreateEncryptor(), CryptoStreamMode.Write)) 
        { 
         cs.Write(value, 0, value.Length); 
         cs.FlushFinalBlock(); 
         crypt = ms.ToArray(); 
        } 
       } 
       iv = myAes.IV; 
       myAes.Clear(); 
      } 
      return ByteArrayToString(crypt) + ":" + ByteArrayToString(iv); 

     } 

     public static string Decrypt(String cipher, String key) 
     { 
      String outputString = ""; 
      byte[] ivBytes = HexToBin(getIV(cipher)); 
      byte[] valBytes = HexToBin(getSSN(cipher)); 

      using (Aes myAes = Aes.Create()) 
      { 
       int size = valBytes.Count(); 

       myAes.KeySize = 256; 
       myAes.Mode = CipherMode.CBC; 
       myAes.Key = HexToBin(key); 
       myAes.IV = ivBytes; 
       myAes.Padding = PaddingMode.PKCS7; 

       char[] output = new char[256]; 

       ICryptoTransform myDecrypter = myAes.CreateDecryptor(myAes.Key, myAes.IV); 

       using (MemoryStream memory = new MemoryStream(ivBytes)) 
       { 
        using (CryptoStream cryptStream = new CryptoStream(memory, myDecrypter, CryptoStreamMode.Read)) 
        { 
         using (StreamReader reader = new StreamReader(cryptStream)) 
         { 

          outputString = reader.ReadToEnd(); 
         } 

         return outputString; 
        } 
       } 

      } 
     } 

     private static byte[] HexToBin(String hexString) 
     { 


      int charCount = hexString.Length; 
      byte[] output = new byte[charCount/2]; 
      for (int i = 0; i < charCount; i += 2) 
      { 
       output[i/2] = Convert.ToByte(hexString.Substring(i, 2), 16); 
      } 


      return output; 
     } 

     private static String getSSN(String cipher) 
     { 
      int delimiterIndex = cipher.IndexOf(":"); 
      String SSN = cipher.Substring(0, delimiterIndex); 
      return SSN; 
     } 


     private static String getIV(String cipher) 
     { 
      int delimiterIndex = cipher.IndexOf(":"); 
      String IV = cipher.Substring(delimiterIndex + 1); 
      return IV; 
     } 




     // Reference: https://stackoverflow.com/questions/311165/how-do-you-convert-a-byte-array-to-a-hexadecimal-string-and-vice-versa 
     private static string ByteArrayToString(byte[] ba) 
     { 
      string hex = BitConverter.ToString(ba); 
      return hex.Replace("-", ""); 
     } 

    } 
} 

ライン73は、(例外が発生した場合)復号化法でのStreamReaderのため使用してブロックの終わりである:

using (StreamReader reader = new StreamReader(cryptStream)) 
        { 

         outputString = reader.ReadToEnd(); 
        } 

私はfollowing questionを参照するが、私の問題を解決することができませんでした。

元々、データはPHPアプリケーションで暗号化され、C#アプリケーションを使用して暗号化されていました(上記とほぼ同じ解読方法を使用しています)。さて、私はC#を使ってデータを暗号化して解読したいと思っています。しかし、私はまだ(PHPを使って暗号化された)既存のデータを適切に解読できる必要があります。そのため、解読メソッドをあまり変更しないでください。

アドバイスをいただければ幸いです。

答えて

1

あなたはここにマイナーな間違いがあります。

ICryptoTransform myDecrypter = myAes.CreateDecryptor(myAes.Key, myAes.IV); 
using (MemoryStream memory = new MemoryStream(ivBytes)) 

あなたが代わりに実際に暗号化されたバイトで、復号化するために、あなたのIV値を渡します。修正:

ICryptoTransform myDecrypter = myAes.CreateDecryptor(myAes.Key, myAes.IV); 
using (MemoryStream memory = new MemoryStream(valBytes)) 
+0

ありがとうございました。それはそれを解決した。さまざまなミスが同じ例外を引き起こす可能性があるように見えます。素晴らしい観察。 :) – KellyMarchewa

+1

@Kellyはい、復号化されたテキストの末尾をぶち壊す間違いは、間違ったタイプのパディングを使用するように、「Bad Padding」例外を与えます。どちらの方法でも、復号化コードは正しいパディングを認識できず、例外をスローします。 – rossum

+1

@KellyMarchewaあなたがランダムに生成された値を復号(IV)に渡しているので、何らかのエラーが発生する可能性があります。運が良ければパディングが正しかったです。例えば、ゴミを解読するかもしれません。あなたがスーパーラッキーで、生成されたIVが暗号化されたデータと同じであれば、正しく復号化することさえできます。 – Evk

関連する問題