Rijndael Padding Error

Hello, I am trying to encrypt / decrypt a string through Rijaendal. I just can't understand why decryption explodes. I always get the wrong fill error. One thing that pushes me away is the result of my encryption, which I return as an HEX array. It has a length of 14 bytes. In my decryption function, the same byte array ends with 16 bytes when converting from HEX.

Any help would be appreciated:

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace rjandal { class Program { static void Main(string[] args) { string DataForEncrypting = "this is a test"; string key = string.Empty; string iv = string.Empty; using (System.Security.Cryptography.RijndaelManaged rmt = new System.Security.Cryptography.RijndaelManaged()) { rmt.KeySize = 256; rmt.BlockSize = 128; rmt.Mode = System.Security.Cryptography.CipherMode.CBC; rmt.Padding = System.Security.Cryptography.PaddingMode.ISO10126; rmt.GenerateKey(); rmt.GenerateIV(); key = Convert.ToBase64String(rmt.Key); iv = Convert.ToBase64String(rmt.IV); } string encryptedData = _encrypt(DataForEncrypting, key, iv); string unencryptedData = _decrypt(key, iv, HexString2Ascii(encryptedData)); Console.WriteLine(unencryptedData); Console.WriteLine(encryptedData); Console.ReadKey(); } private static string _encrypt(string value, string key, string initVector) { byte[] buffer = ASCIIEncoding.ASCII.GetBytes(value); byte[] encBuffer; using (System.Security.Cryptography.RijndaelManaged rmt = new System.Security.Cryptography.RijndaelManaged()) { rmt.KeySize = 256; rmt.BlockSize = 128; rmt.Mode = System.Security.Cryptography.CipherMode.CBC; rmt.Padding = System.Security.Cryptography.PaddingMode.ISO10126; encBuffer = rmt.CreateEncryptor(Convert.FromBase64String(key), Convert.FromBase64String(initVector)).TransformFinalBlock(buffer, 0, buffer.Length); } string encryptValue = ConvertToHex(ASCIIEncoding.ASCII.GetString(encBuffer)); return encryptValue; } private static string _decrypt(string key, string initVector, string value) { byte[] hexBuffer = ASCIIEncoding.ASCII.GetBytes(value); byte[] decBuffer; using (System.Security.Cryptography.RijndaelManaged rmt = new System.Security.Cryptography.RijndaelManaged()) { rmt.KeySize = 256; rmt.BlockSize = 128; rmt.Mode = System.Security.Cryptography.CipherMode.CBC; rmt.Padding = System.Security.Cryptography.PaddingMode.ISO10126; decBuffer = rmt.CreateDecryptor(Convert.FromBase64String(key), Convert.FromBase64String(initVector)).TransformFinalBlock(hexBuffer, 0, hexBuffer.Length); } return System.Text.ASCIIEncoding.ASCII.GetString(decBuffer); } private static string ConvertToHex(string asciiString) { string hex = ""; foreach (char c in asciiString) { int tmp = c; hex += String.Format("{0:x2}", (uint)System.Convert.ToUInt32(tmp.ToString())); } return hex; } private static string HexString2Ascii(string hexString) { StringBuilder sb = new StringBuilder(); for (int i = 0; i <= hexString.Length - 2; i += 2) { sb.Append(Convert.ToString(Convert.ToChar(Int32.Parse(hexString.Substring(i, 2), System.Globalization.NumberStyles.HexNumber)))); } return sb.ToString(); } } } 
+4
source share
3 answers

You should not use ASCII character encoding as an intermediate step; you must change your functions that go from hexadecimal to ASCII (and vice versa) in order to switch from byte[] to hexadecimal (and vice versa).

  private static string ConvertToHex(byte[] data) { string hex = ""; foreach (byte b in data) { hex += b.ToString("X2"); } return hex; } private static byte[] HexString2ByteArray(string hexString) { byte[] output = new byte[hexString.Length / 2]; for (int i = 0; i <= hexString.Length - 2; i += 2) { output[i/2] = Convert.ToByte(hexString.Substring(i, 2), 16); } return output; } 

As a side note, is there a reason you're looking for a hexadecimal representation of an array against something more compact than Base64? You use Base64 in your example to pass the key and IV, so I'm just curious that you want to return the encrypted data as hex here.

Anyway, something should work for you here:

  private static string _encrypt(string value, string key, string initVector) { byte[] buffer = Encoding.Unicode.GetBytes(value); byte[] encBuffer; using (System.Security.Cryptography.RijndaelManaged rmt = new System.Security.Cryptography.RijndaelManaged()) { rmt.KeySize = 256; rmt.BlockSize = 128; rmt.Mode = System.Security.Cryptography.CipherMode.CBC; rmt.Padding = System.Security.Cryptography.PaddingMode.ISO10126; encBuffer = rmt.CreateEncryptor(Convert.FromBase64String(key), Convert.FromBase64String(initVector)).TransformFinalBlock(buffer, 0, buffer.Length); } string encryptValue = ConvertToHex(encBuffer); return encryptValue; } private static string _decrypt(string key, string initVector, string value) { byte[] hexBuffer = HexString2ByteArray(value); byte[] decBuffer; using (System.Security.Cryptography.RijndaelManaged rmt = new System.Security.Cryptography.RijndaelManaged()) { rmt.KeySize = 256; rmt.BlockSize = 128; rmt.Mode = System.Security.Cryptography.CipherMode.CBC; rmt.Padding = System.Security.Cryptography.PaddingMode.ISO10126; decBuffer = rmt.CreateDecryptor(Convert.FromBase64String(key), Convert.FromBase64String(initVector)).TransformFinalBlock(hexBuffer, 0, hexBuffer.Length); } return Encoding.Unicode.GetString(decBuffer); } 
+2
source

Basically you do too many conversions between text and data. Take a look at this, for example:

 string encryptValue = ConvertToHex(ASCIIEncoding.ASCII.GetString(encBuffer)); 

Once you get the ASCII string, why do you need to convert it to hexadecimal? This is the text! But by then you had already lost the data. If you really don't need it in hexadecimal format (in this case, follow Adam’s suggestion and change the HexToAscii method to use the byte [] instead of the string), you should just use Convert.ToBase64String:

 string encryptValue = Convert.ToBase64String(encBuffer); 

Use Convert.FromBase64String on the other end when decrypting. You can completely get rid of your hexagonal methods.

Oh, and generally I would not use Encoding.ASCII for starters ... I would almost always use Encoding.UTF8 . Currently, you cannot encrypt (correctly) any lines containing non-ASCII characters, such as accents.

Here is a modified version of your test program with some of these changes. Note that the names “ciphertext” and “plain text” refer to encryption ... they are still binary data, not text!

 using System; using System.Security.Cryptography; using System.Text; class Program { static void Main(string[] args) { string DataForEncrypting = "this is a test"; string key = string.Empty; string iv = string.Empty; using (RijndaelManaged rmt = new RijndaelManaged()) { rmt.KeySize = 256; rmt.BlockSize = 128; rmt.Mode = CipherMode.CBC; rmt.Padding = PaddingMode.ISO10126; rmt.GenerateKey(); rmt.GenerateIV(); key = Convert.ToBase64String(rmt.Key); iv = Convert.ToBase64String(rmt.IV); } string encryptedData = _encrypt(DataForEncrypting, key, iv); string unencryptedData = _decrypt(key, iv, encryptedData); Console.WriteLine(unencryptedData); Console.WriteLine(encryptedData); Console.ReadKey(); } private static string _encrypt(string value, string key, string initVector) { using (RijndaelManaged rmt = new RijndaelManaged()) { rmt.KeySize = 256; rmt.BlockSize = 128; rmt.Mode = CipherMode.CBC; rmt.Padding = PaddingMode.ISO10126; byte[] plainText = Encoding.UTF8.GetBytes(value); byte[] cipherText = rmt.CreateEncryptor(Convert.FromBase64String(key), Convert.FromBase64String(initVector)) .TransformFinalBlock(plainText, 0, plainText.Length); return Convert.ToBase64String(cipherText); } } private static string _decrypt(string key, string initVector, string value) { using (RijndaelManaged rmt = new RijndaelManaged()) { rmt.KeySize = 256; rmt.BlockSize = 128; rmt.Mode = CipherMode.CBC; rmt.Padding = PaddingMode.ISO10126; byte[] cipherText = Convert.FromBase64String(value); byte[] plainText = rmt.CreateDecryptor(Convert.FromBase64String(key), Convert.FromBase64String(initVector)) .TransformFinalBlock(cipherText, 0, cipherText.Length); return Encoding.UTF8.GetString(plainText); } } } 
+5
source

You can avoid problems with Decypting / Encrypting and usign System.Text.Encoding and avoid using Base64 encoding by adding several methods that completely bypass the inconsistent conversion microwaves in System.Text.Encoding, allowing you to encrypt real bytes in memory without any translations .

Since I used these, I avoided padding errors caused by System.Text.Encoding methods without using Base64 transforms either.

  private static Byte[] GetBytes(String SomeString) { Char[] SomeChars = SomeString.ToCharArray(); Int32 Size = SomeChars.Length * 2; List<Byte> TempList = new List<Byte>(Size); foreach (Char Character in SomeChars) { TempList.AddRange(BitConverter.GetBytes(Character)); } return TempList.ToArray(); } private static String GetString(Byte[] ByteArray) { Int32 Size = ByteArray.Length / 2; List<Char> TempList = new List<Char>(Size); for (Int32 i = 0; i < ByteArray.Length; i += 2) { TempList.Add(BitConverter.ToChar(ByteArray, i)); } return new String(TempList.ToArray()); } 

And how are they used with encryption

  private static String Encrypt(String Test1, Byte[] Key, Byte[] IV) { Byte[] Encrypted; using (AesCryptoServiceProvider AesMan = new AesCryptoServiceProvider()) { AesMan.Mode = CipherMode.CBC; AesMan.Padding = PaddingMode.ISO10126; ICryptoTransform EncThis = AesMan.CreateEncryptor(Key, IV); using (MemoryStream msEncrypt = new MemoryStream()) { using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, EncThis, CryptoStreamMode.Write)) { using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) { //Write all data to the stream. swEncrypt.Write(Test1); } Encrypted = msEncrypt.ToArray(); } } }; return GetString(Encrypted); } private static String Decrypt(String Data, Byte[] Key, Byte[] IV) { String Decrypted; using (AesCryptoServiceProvider AesMan = new AesCryptoServiceProvider()) { AesMan.Mode = CipherMode.CBC; AesMan.Padding = PaddingMode.ISO10126; ICryptoTransform EncThis = AesMan.CreateDecryptor(Key, IV); using (MemoryStream msDecrypt = new MemoryStream(GetBytes(Data))) { using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, EncThis, CryptoStreamMode.Read)) { using (StreamReader srDecrypt = new StreamReader(csDecrypt)) { // Read the decrypted bytes from the decrypting stream // and place them in a string. Decrypted = srDecrypt.ReadToEnd(); } } } } return Decrypted; } 
+2
source

Source: https://habr.com/ru/post/1338764/


All Articles