Hello I am trying to encrypt / decrypt a string via Rijaendal. I simply can't figure out why the decryption blows up. I always end up with an incorrect padding error. One thing that throws me off is the result of my encryption which I return as HEX array. It has a length of 14 bytes. In my decryption function, the same byte array ends up having 16 bytes upon conversion 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();
}
}
}
You're doing way too much conversion between text and data, basically. Look at this, for example:
string encryptValue = ConvertToHex(ASCIIEncoding.ASCII.GetString(encBuffer));
Once you've got an ASCII string, why would you need to convert that into hex? It's already text! But by then you'll already have lost the data. Unless you really need it in hex (in which case follow Adam's suggestion and change your HexToAscii method to take a byte[] instead of a string) you should just use Convert.ToBase64String:
string encryptValue = Convert.ToBase64String(encBuffer);
Use Convert.FromBase64String
at the other end when decrypting. You can then get rid of your hex methods completely.
Oh, and in general I wouldn't use Encoding.ASCII
to start with... I'd almost always use Encoding.UTF8
instead. Currently you'll fail to encrypt (correctly) any strings containing non-ASCII characters such as accents.
Here's a rejigged version of your test program, with a few of those changes made. Note that the names "cipher text" and "plain text" are in terms of encryption... they're still binary data rather than 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);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With