- Home /
[SOLVED] Bad PKCS7 While encrypting a file
I have found a C# encryption/decryption code on the internetnet. This code works really well until i try to decrypt a byte array.
What i am hoping to achive is a system that will encrypt a image, then on game load, decrypt it into assest. I would use this system as a form of updating, to keep all the images safe from any custom texture packing that might happen.
However, every time run a byte array through the code, i get this error: CryptographicException: Bad PKCS7 padding. Invalid length 206. at Mono.Security.Cryptography.SymmetricTransform.ThrowBadPaddingException (PaddingMode padding, Int32 length, Int32 position) [0x00000] in :0
   at Mono.Security.Cryptography.SymmetricTransform.FinalDecrypt (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) [0x00000] in <filename unknown>:0 
 
   at Mono.Security.Cryptography.SymmetricTransform.TransformFinalBlock (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) [0x00000] in <filename unknown>:0 
 
   at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) [0x00000] in <filename unknown>:0 
 
   at System.Security.Cryptography.CryptoStream.FlushFinalBlock () [0x00000] in <filename unknown>:0 
 
   at System.Security.Cryptography.CryptoStream.Close () [0x00000] in <filename unknown>:0 
 
   at ImageCrypt.Decrypt (System.Byte[] cipherData, System.Byte[] Key, System.Byte[] IV) [0x00033] in C:\Users\Public\Documents\Unity Projects\Protypes\Assets\Scripts\ImageCrypt.cs:248 
 
   at ImageCrypt.Decrypt (System.Byte[] cipherData, System.String Password) [0x00019] in C:\Users\Public\Documents\Unity Projects\Protypes\Assets\Scripts\ImageCrypt.cs:325 
 
   at ImageCrypt.Start () [0x0004c] in C:\Users\Public\Documents\Unity Projects\Protypes\Assets\Scripts\ImageCrypt.cs:23 
  
 (Filename: Assets/Scripts/ImageCrypt.cs Line: 248)
This is the code i am using, i have created the Start, Awake and the fileLoad functions myself, the rest is from the internet.
 using UnityEngine;
 using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.Text;
 using System.Security.Cryptography;
 using System.IO;
 
 #pragma warning disable 0618
 
 public class ImageCrypt : MonoBehaviour {
     
 
     public Texture2D tex; public ImageCrypt crypt; private byte[] o0; private void Awake(){ crypt = this; o0 = UTF8Encoding.UTF8.GetBytes ("12345678901234567890123456789012"); }
     
     void Start()
     {
         
         tex = new Texture2D (100,100);
         Encrypt(Application.dataPath + "/in.png", Application.dataPath + "/out.pixel", "lachee");
     
         byte[] Encrypted = loadByte(Application.dataPath + "/out.pixel");
         byte[] Decypted = Decrypt(Encrypted, "lachee");    
         tex.LoadImage(Decypted);
     }
      // Encrypt a byte array into a byte array using a key and an IV 
     public static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV) 
     { 
         // Create a MemoryStream to accept the encrypted bytes 
         MemoryStream ms = new MemoryStream(); 
 
         // Create a symmetric algorithm. 
         // We are going to use Rijndael because it is strong and
         // available on all platforms. 
         // You can use other algorithms, to do so substitute the
         // next line with something like 
         //      TripleDES alg = TripleDES.Create(); 
         Rijndael alg = Rijndael.Create(); 
 
         // Now set the key and the IV. 
         // We need the IV (Initialization Vector) because
         // the algorithm is operating in its default 
         // mode called CBC (Cipher Block Chaining).
         // The IV is XORed with the first block (8 byte) 
         // of the data before it is encrypted, and then each
         // encrypted block is XORed with the 
         // following block of plaintext.
         // This is done to make encryption more secure. 
 
         // There is also a mode called ECB which does not need an IV,
         // but it is much less secure. 
         alg.Key = Key; 
         alg.IV = IV; 
 
         // Create a CryptoStream through which we are going to be
         // pumping our data. 
         // CryptoStreamMode.Write means that we are going to be
         // writing data to the stream and the output will be written
         // in the MemoryStream we have provided. 
         CryptoStream cs = new CryptoStream(ms, 
            alg.CreateEncryptor(), CryptoStreamMode.Write); 
 
         // Write the data and make it do the encryption 
         cs.Write(clearData, 0, clearData.Length); 
 
         // Close the crypto stream (or do FlushFinalBlock). 
         // This will tell it that we have done our encryption and
         // there is no more data coming in, 
         // and it is now a good time to apply the padding and
         // finalize the encryption process. 
         cs.Close(); 
 
         // Now get the encrypted data from the MemoryStream.
         // Some people make a mistake of using GetBuffer() here,
         // which is not the right way. 
         byte[] encryptedData = ms.ToArray();
 
         return encryptedData; 
     } 
 
     // Encrypt a string into a string using a password 
     //    Uses Encrypt(byte[], byte[], byte[]) 
 
     public static string Encrypt(string clearText, string Password) 
     { 
         // First we need to turn the input string into a byte array. 
         byte[] clearBytes = 
           System.Text.Encoding.Unicode.GetBytes(clearText); 
 
         // Then, we need to turn the password into Key and IV 
         // We are using salt to make it harder to guess our key
         // using a dictionary attack - 
         // trying to guess a password by enumerating all possible words. 
         PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, 
             new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
             0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); 
 
         // Now get the key/IV and do the encryption using the
         // function that accepts byte arrays. 
         // Using PasswordDeriveBytes object we are first getting
         // 32 bytes for the Key 
         // (the default Rijndael key length is 256bit = 32bytes)
         // and then 16 bytes for the IV. 
         // IV should always be the block size, which is by default
         // 16 bytes (128 bit) for Rijndael. 
         // If you are using DES/TripleDES/RC2 the block size is
         // 8 bytes and so should be the IV size. 
         // You can also read KeySize/BlockSize properties off
         // the algorithm to find out the sizes. 
         byte[] encryptedData = Encrypt(clearBytes, 
                  pdb.GetBytes(32), pdb.GetBytes(16)); 
 
         // Now we need to turn the resulting byte array into a string. 
         // A common mistake would be to use an Encoding class for that.
         //It does not work because not all byte values can be
         // represented by characters. 
         // We are going to be using Base64 encoding that is designed
         //exactly for what we are trying to do. 
         return Convert.ToBase64String(encryptedData); 
 
     }
     
     // Encrypt bytes into bytes using a password 
     //    Uses Encrypt(byte[], byte[], byte[]) 
 
     public static byte[] Encrypt(byte[] clearData, string Password) 
     { 
         // We need to turn the password into Key and IV. 
         // We are using salt to make it harder to guess our key
         // using a dictionary attack - 
         // trying to guess a password by enumerating all possible words. 
         PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, 
             new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
             0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); 
 
         // Now get the key/IV and do the encryption using the function
         // that accepts byte arrays. 
         // Using PasswordDeriveBytes object we are first getting
         // 32 bytes for the Key 
         // (the default Rijndael key length is 256bit = 32bytes)
         // and then 16 bytes for the IV. 
         // IV should always be the block size, which is by default
         // 16 bytes (128 bit) for Rijndael. 
         // If you are using DES/TripleDES/RC2 the block size is 8
         // bytes and so should be the IV size. 
         // You can also read KeySize/BlockSize properties off the
         // algorithm to find out the sizes. 
         return Encrypt(clearData, pdb.GetBytes(32), pdb.GetBytes(16)); 
 
     }
 
     // Encrypt a file into another file using a password 
     public static void Encrypt(string fileIn, 
                 string fileOut, string Password) 
     { 
 
         // First we are going to open the file streams 
         FileStream fsIn = new FileStream(fileIn, 
             FileMode.Open, FileAccess.Read); 
         FileStream fsOut = new FileStream(fileOut, 
             FileMode.OpenOrCreate, FileAccess.Write); 
 
         // Then we are going to derive a Key and an IV from the
         // Password and create an algorithm 
         PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, 
             new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
             0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); 
 
         Rijndael alg = Rijndael.Create(); 
         alg.Key = pdb.GetBytes(32); 
         alg.IV = pdb.GetBytes(16); 
 
         // Now create a crypto stream through which we are going
         // to be pumping data. 
         // Our fileOut is going to be receiving the encrypted bytes. 
         CryptoStream cs = new CryptoStream(fsOut, 
             alg.CreateEncryptor(), CryptoStreamMode.Write); 
 
         // Now will will initialize a buffer and will be processing
         // the input file in chunks. 
         // This is done to avoid reading the whole file (which can
         // be huge) into memory. 
         int bufferLen = 4096; 
         byte[] buffer = new byte[bufferLen]; 
         int bytesRead; 
 
         do { 
             // read a chunk of data from the input file 
             bytesRead = fsIn.Read(buffer, 0, bufferLen); 
 
             // encrypt it 
             cs.Write(buffer, 0, bytesRead); 
         } while(bytesRead != 0); 
 
         // close everything 
 
         // this will also close the unrelying fsOut stream
         cs.Close(); 
         fsIn.Close();     
     } 
 
     // Decrypt a byte array into a byte array using a key and an IV 
     public static byte[] Decrypt(byte[] cipherData, 
                                 byte[] Key, byte[] IV) 
     { 
         // Create a MemoryStream that is going to accept the
         // decrypted bytes 
         MemoryStream ms = new MemoryStream(); 
 
         // Create a symmetric algorithm. 
         // We are going to use Rijndael because it is strong and
         // available on all platforms. 
         // You can use other algorithms, to do so substitute the next
         // line with something like 
         //     TripleDES alg = TripleDES.Create(); 
         Rijndael alg = Rijndael.Create(); 
 
         // Now set the key and the IV. 
         // We need the IV (Initialization Vector) because the algorithm
         // is operating in its default 
         // mode called CBC (Cipher Block Chaining). The IV is XORed with
         // the first block (8 byte) 
         // of the data after it is decrypted, and then each decrypted
         // block is XORed with the previous 
         // cipher block. This is done to make encryption more secure. 
         // There is also a mode called ECB which does not need an IV,
         // but it is much less secure. 
         alg.Key = Key; 
         alg.IV = IV; 
 
         // Create a CryptoStream through which we are going to be
         // pumping our data. 
         // CryptoStreamMode.Write means that we are going to be
         // writing data to the stream 
         // and the output will be written in the MemoryStream
         // we have provided. 
         CryptoStream cs = new CryptoStream(ms, 
             alg.CreateDecryptor(), CryptoStreamMode.Write); 
 
         // Write the data and make it do the decryption 
         cs.Write(cipherData, 0, cipherData.Length); 
 
         // Close the crypto stream (or do FlushFinalBlock). 
         // This will tell it that we have done our decryption
         // and there is no more data coming in, 
         // and it is now a good time to remove the padding
         // and finalize the decryption process. 
         cs.Close(); 
 
         // Now get the decrypted data from the MemoryStream. 
         // Some people make a mistake of using GetBuffer() here,
         // which is not the right way. 
         byte[] decryptedData = ms.ToArray(); 
 
         return decryptedData; 
     }
 
     // Decrypt a string into a string using a password 
     //    Uses Decrypt(byte[], byte[], byte[]) 
 
     public static string Decrypt(string cipherText, string Password) 
     { 
         // First we need to turn the input string into a byte array. 
         // We presume that Base64 encoding was used 
         byte[] cipherBytes = Convert.FromBase64String(cipherText); 
 
         // Then, we need to turn the password into Key and IV 
         // We are using salt to make it harder to guess our key
         // using a dictionary attack - 
         // trying to guess a password by enumerating all possible words. 
         PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, 
             new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 
             0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); 
 
         // Now get the key/IV and do the decryption using
         // the function that accepts byte arrays. 
         // Using PasswordDeriveBytes object we are first
         // getting 32 bytes for the Key 
         // (the default Rijndael key length is 256bit = 32bytes)
         // and then 16 bytes for the IV. 
         // IV should always be the block size, which is by
         // default 16 bytes (128 bit) for Rijndael. 
         // If you are using DES/TripleDES/RC2 the block size is
         // 8 bytes and so should be the IV size. 
         // You can also read KeySize/BlockSize properties off
         // the algorithm to find out the sizes. 
         byte[] decryptedData = Decrypt(cipherBytes, 
             pdb.GetBytes(32), pdb.GetBytes(16)); 
 
         // Now we need to turn the resulting byte array into a string. 
         // A common mistake would be to use an Encoding class for that.
         // It does not work 
         // because not all byte values can be represented by characters. 
         // We are going to be using Base64 encoding that is 
         // designed exactly for what we are trying to do. 
         return System.Text.Encoding.Unicode.GetString(decryptedData); 
     }
 
     // Decrypt bytes into bytes using a password 
     //    Uses Decrypt(byte[], byte[], byte[]) 
 
     public static byte[] Decrypt(byte[] cipherData, string Password) 
     { 
         // We need to turn the password into Key and IV. 
         // We are using salt to make it harder to guess our key
         // using a dictionary attack - 
         // trying to guess a password by enumerating all possible words. 
         PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, 
             new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
             0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); 
 
         // Now get the key/IV and do the Decryption using the 
         //function that accepts byte arrays. 
         // Using PasswordDeriveBytes object we are first getting
         // 32 bytes for the Key 
         // (the default Rijndael key length is 256bit = 32bytes)
         // and then 16 bytes for the IV. 
         // IV should always be the block size, which is by default
         // 16 bytes (128 bit) for Rijndael. 
         // If you are using DES/TripleDES/RC2 the block size is
         // 8 bytes and so should be the IV size. 
 
         // You can also read KeySize/BlockSize properties off the
         // algorithm to find out the sizes. 
         return Decrypt(cipherData, pdb.GetBytes(32), pdb.GetBytes(16)); 
     }
 
     // Decrypt a file into another file using a password 
     public static void Decrypt(string fileIn, 
                 string fileOut, string Password) 
     { 
     
         // First we are going to open the file streams 
         FileStream fsIn = new FileStream(fileIn,
                     FileMode.Open, FileAccess.Read); 
         FileStream fsOut = new FileStream(fileOut,
                     FileMode.OpenOrCreate, FileAccess.Write); 
   
         // Then we are going to derive a Key and an IV from
         // the Password and create an algorithm 
         PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, 
             new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
             0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); 
         Rijndael alg = Rijndael.Create(); 
 
         alg.Key = pdb.GetBytes(32); 
         alg.IV = pdb.GetBytes(16); 
 
         // Now create a crypto stream through which we are going
         // to be pumping data. 
         // Our fileOut is going to be receiving the Decrypted bytes. 
         CryptoStream cs = new CryptoStream(fsOut, 
             alg.CreateDecryptor(), CryptoStreamMode.Write); 
   
         // Now will will initialize a buffer and will be 
         // processing the input file in chunks. 
         // This is done to avoid reading the whole file (which can be
         // huge) into memory. 
         int bufferLen = 4096; 
         byte[] buffer = new byte[bufferLen]; 
         int bytesRead; 
 
         do { 
             // read a chunk of data from the input file 
             bytesRead = fsIn.Read(buffer, 0, bufferLen); 
 
             // Decrypt it 
             cs.Write(buffer, 0, bytesRead); 
 
         } while(bytesRead != 0); 
 
         // close everything 
         cs.Close(); // this will also close the unrelying fsOut stream 
         fsIn.Close();     
     }
         
     public static byte[] loadByte(string fileIn)
     {
         /*    byte[] chunk = null;
             if ((fileIn.Length == 0) || !File.Exists(fileIn))
             {
                 Debug.LogError("Please provide an existing file name.");
             }
             else
             {
                 using (FileStream fs = new FileStream(fileIn, FileMode.Open, FileAccess.Read))
                 {
                     using (BinaryReader br = new BinaryReader(fs, new ASCIIEncoding()))
                     {
                         
     
                         chunk = br.ReadBytes(CHUNK_SIZE);
                       
                         
                     }
                 }
             }    
             return chunk;*/
         
         if (File.Exists(fileIn)){
             return File.ReadAllBytes(fileIn);
         }else{
             Debug.LogError("Cannot Read From A Null File");
             return null;
         }
     }
 }
 #pragma warning restore 0618
 
Hello,
excuse me, I'm just struggling around with encrypting/decrypting and got the same error. Do you $$anonymous$$d posting your working code ?
Thanks in advance. Joe
Sure, no problems. I haven't used the files for a while so I'm not sure how they exactly work, but i'll give you what I have, they are located here: http://lacheedomain.netii.net/scripts/
You will need Cryptography.cs and Level$$anonymous$$asterCode.cs
Level$$anonymous$$asterCode.cs is actually part of one of my games, so I wish for you not to use any of the code unless link directly to the Cryptography.cs code, I spent a good amount of time on it you see, hate to see it stolen.
I may make a more use friendly Cryptography.cs version one day, however, I used another script for the majority of this one.
Have fun crypting. Note: $$anonymous$$y example codes save them as a picture.
Answer by Lachee1 · Jan 15, 2013 at 09:11 AM
It was erroring because the file encryption was different to the byte decryption. I resolved it by encrypting the data THEN saving it using the File Stream
had the same error just pop up. $$anonymous$$udos to posting an answer and the question.
I don't know how. But I resolved this error by setting up my max character limit of inputfiled . I set limit to 30.
Strange!!!!
I also got this error when I tried to decrypt with a password that was different than what I encrypted with. (Hopefully that helps others too).
Your answer
 
 
             Follow this Question
Related Questions
Downsize/compress image on upload to Firebase? 0 Answers
Loading Textures during runtime and applying to Raw Images 2 Answers
XML Encryption 1 Answer
Bitmaps in unity 4 Answers
 koobas.hobune.stream
koobas.hobune.stream 
                       
                
                       
			     
			 
                