Getting Bad Data exception during decryption (using .Net Cryptography) - c#

I am using symmetric TripleDES encryption from the class TripleDESCryptoServiceProvider (.Net 2.0) to encrypt the contents of a file.
The data gets encrypted perfectly but during decryption it throws the CryptographyException: Bad data
I am using key from current date time and IV from the randomly generated value by .Net class. Then I pass the same key and IV to the decryption method but it fails for some reason.
Here is my code :
static void Main(string[] args){
string fileName = "input.exe";
string newFileName = fileName + "crypted.exe";
byte[] iv;
var fileToEncrypt = File.ReadAllBytes(fileName);
var encryptionKey = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(DateTime.Now.ToString("ddMMyyHmmss")));
File.WriteAllBytes(newFileName, EncryptTripleDES(fileToEncrypt, encryptionKey, out iv));
File.WriteAllBytes(fileName + "decrypted.exe", DecryptTripleDES(File.ReadAllBytes(newFileName), encryptionKey,iv));
}
public static byte[] EncryptTripleDES(byte[] dataToEncrypt, byte[] key, out byte[] iv){
byte[] result;
var tdes = new TripleDESCryptoServiceProvider { Key = key, KeySize = 128, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 };
iv = tdes.IV;
using(ICryptoTransform cTransform = tdes.CreateEncryptor()){
result = cTransform.TransformFinalBlock(dataToEncrypt, 0, dataToEncrypt.Length);
tdes.Clear();
}
return result;
}
public static byte[] DecryptTripleDES(byte[] dataToDecrypt, byte[] key, byte[] iv){
byte[] result;
var tdes = new TripleDESCryptoServiceProvider { Key = key, KeySize = 128, Mode = CipherMode.CBC,IV = iv,Padding = PaddingMode.PKCS7 };
using (ICryptoTransform cTransform = tdes.CreateDecryptor()){
result = cTransform.TransformFinalBlock(dataToDecrypt, 0, dataToDecrypt.Length);
tdes.Clear();
}
return result;
}
UPDATE:
1. I have checked the value of IV being passed is valid and same as used in encryption.
2. Changing the padding to zero or none doesn't raise the exception but then the data isn't decrypted correctly. It comes out to be different than original.

The problem is in the way that you're constructing the TripleDESCryptoServiceProviders using an initializer. The Key is set first in the initializer, but then you set the KeySize, which causes the Key to be reset to a new (randomly generated) key, as a result, you're encrypting and decrypting with different keys (neither of which are the key you generate).
You can fix this by re-ordering the initializer so that KeySize is set first, or perhaps move the setting of the Key outside the initializer entirely to avoid any ambiguity:
public static byte[] EncryptTripleDES(byte[] dataToEncrypt, byte[] key, out byte[] iv){
byte[] result;
var tdes = new TripleDESCryptoServiceProvider { KeySize = 128, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 };
// Key explicitly set here, not in the initializer:
tdes.Key = key;
iv = tdes.IV;
using(ICryptoTransform cTransform = tdes.CreateEncryptor()){
result = cTransform.TransformFinalBlock(dataToEncrypt, 0, dataToEncrypt.Length);
tdes.Clear();
}
return result;
}
public static byte[] DecryptTripleDES(byte[] dataToDecrypt, byte[] key, byte[] iv){
byte[] result;
var tdes = new TripleDESCryptoServiceProvider { KeySize = 128, Mode = CipherMode.CBC,IV = iv,Padding = PaddingMode.PKCS7 };
// Key explicitly set here, not in the initializer:
tdes.Key = key;
using (ICryptoTransform cTransform = tdes.CreateDecryptor()){
result = cTransform.TransformFinalBlock(dataToDecrypt, 0, dataToDecrypt.Length);
tdes.Clear();
}
return result;
}

Related

RSAEngine Index was outside the bounds of the array

I need to encrypt the AES key with public RSA key, but I do have a problem on return engine.ProcessBlock. It keeps giving me the error 'Index was outside the bounds of the array' and the blocksize is only 245 bytes long.
'Source array was not long enough. Check srcIndex and length, and the array's lower bounds.'
public void Main()
{
var pem = #"C:\Temp\test\publickey.pem";
AesCryptoServiceProvider AES = new AesCryptoServiceProvider();
AES.Padding = PaddingMode.PKCS7;
AES.Mode = CipherMode.CBC;
AES.BlockSize = 128;
AES.KeySize = 256;
AES.GenerateKey();
AES.GenerateIV();
byte[] key = AES.Key;
byte[] iv = AES.IV;
encryptAES(AES, file, key, iv);
decryptAES(AES, file + ".encrypted", key, iv);
byte[] encryptedAes = Encrypt(key, ReadAsymmetricKeyParameter(pem));
}
public byte[] Encrypt(byte[] data, AsymmetricKeyParameter key)
{
var engine = new Pkcs1Encoding(new RsaEngine());
engine.Init(true, key);
var blockSize = engine.GetInputBlockSize();
byte[] enc = engine.ProcessBlock(data, 0, blockSize);
return enc;
}
public AsymmetricKeyParameter ReadAsymmetricKeyParameter(string pemFilename)
{
var fileStream = File.OpenText(pemFilename);
var pemReader = new PemReader(fileStream);
var KeyParameter = (AsymmetricKeyParameter)pemReader.ReadObject();
return KeyParameter;
}

Why does the decrypted string not match the input string?

In this code snippet I have used the RSACryptoServiceProvider class to encrypt a key and IV generated by Rfc2898DerivedBytes class. The key and IV are then decrypted, inserted into an AesManaged encryptor, and then I use the AesManaged encryptor to encrypt a string(converted into a byte array). The process is reversed to decrypt the array which succeeds but then the string returned does not match the input string. Why is this?
I have already tried changing the Encoding format of the byte arrays but that did not work. I have inspected the original byte array and what it looks like after it has gone through the entire process of being encrypted and decrypted and they are identical.
class EncryptionBestPracticeDemo
{
public static byte[] keys;
public static AesManaged aesAlgorithm = new AesManaged();
public struct KeyIV
{
public byte[] Key { get; private set; }
public byte[] IV { get; private set; }
public KeyIV(byte[] key, byte[] iV)
{
this.Key = key;
this.IV = iV;
}
}
public static KeyIV GetEncryptedKeyAndIV()
{
KeyIV keySalt;
var password = "Pa$$w0rd";
var salt = "S#lt";
var rgb = new Rfc2898DeriveBytes(password, Encoding.Unicode.GetBytes(salt));
aesAlgorithm.Padding = PaddingMode.None;
var rgbKey = rgb.GetBytes(aesAlgorithm.KeySize / 8);
var rgbIV = rgb.GetBytes(aesAlgorithm.BlockSize / 8);
//Encrypt the key and IV
using (var rsaProvider = new RSACryptoServiceProvider())
{
var setOaemPadding = true;
keys = rsaProvider.ExportCspBlob(true);
keySalt = new KeyIV(rsaProvider.Encrypt(rgbKey, setOaemPadding), rsaProvider.Encrypt(rgbIV, setOaemPadding));
}
return keySalt;
}
public static void AesWithRSA()
{
//Use RSACryptoProvider to decrypt the secret key of the AesAlgorithm algorithm
var message = "NET Cryptography";
var messageByteArray = Encoding.UTF8.GetBytes(message);
byte[] encryptedData;
byte[] decryptedData;
//Get the encrypted Key and IV
var keySalt = GetEncryptedKeyAndIV();
using (var rsaProvider = new RSACryptoServiceProvider())
{
var setOaemPadding = true;
rsaProvider.ImportCspBlob(keys);
//Decrypt the key and IV
var key = rsaProvider.Decrypt(keySalt.Key, setOaemPadding);
var iV = rsaProvider.Decrypt(keySalt.IV, setOaemPadding);
//Use the decrypted key and IV in the AES encryptor
var encryptor = aesAlgorithm.CreateEncryptor(key, iV);
using (var bufferStream = new MemoryStream())
using (var cryptoStream = new CryptoStream(bufferStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(messageByteArray, 0, messageByteArray.Length);
encryptedData = bufferStream.ToArray();
}
}
using (var rsaProvider = new RSACryptoServiceProvider())
{
var setOaemPadding = true;
rsaProvider.ImportCspBlob(keys);
//Decrypt the key and IV
var key = rsaProvider.Decrypt(keySalt.Key, setOaemPadding);
var iV = rsaProvider.Decrypt(keySalt.IV, setOaemPadding);
//Use the decrypted key and IV in the AES decryptor
var decryptor = aesAlgorithm.CreateEncryptor(key, iV);
using (var bufferStream = new MemoryStream())
using (var cryptoStream = new CryptoStream(bufferStream, decryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(encryptedData, 0, encryptedData.Length);
decryptedData = bufferStream.ToArray();
Console.WriteLine(Encoding.UTF8.GetString(decryptedData));
}
}
}
}
Input string: "NET Cryptography".
Expected output string: "NET Cryptography".
Output string: "????b!?k?!? ?+X".

How to decode huge base64 string

I am looking for a way to decode very big (1.5Gb) base64 string from a file without getting OutOfMemoryException. I've tried this method for encoding.
Can you suggest me a way to do it?
Thanks in advance!!
EDIT:
Encrytion code:
public static string HighLevelEncryptionAES(byte[] plainDataBytes, byte[] keyBytes)
{
CryptoSecurityClass cryptoSecurity = new CryptoSecurityClass();
AesCryptoServiceProvider serviceProvider = cryptoSecurity.GetAesProvider(keyBytes);
ICryptoTransform encryptor = serviceProvider.CreateEncryptor();
byte[] encryptedBytes = encryptor.TransformFinalBlock(plainDataBytes, 0, plainDataBytes.Length);
string encryptedString = Convert.ToBase64String(encryptedBytes);
return encryptedString;
}
AES provider class:
private AesCryptoServiceProvider GetAesProvider(byte[] key)
{
return new AesCryptoServiceProvider()
{
KeySize = 256,
Key = key,
BlockSize = 128,
Padding = PaddingMode.PKCS7,
Mode = CipherMode.ECB
};
}

Replace mcrypt MCRYPT_RIJNDAEL_256 with openssl or change it to AES

I'm building a simple PHP script that need to decode input from C# application.
I've created C# app with below encrypting function (I've also included my decrypting function):
public static string Encrypt(string input, string key)
{
var aes = new RijndaelManaged
{
KeySize = 256,
BlockSize = 256,
Padding = PaddingMode.PKCS7,
Mode = CipherMode.CBC,
Key = Encoding.UTF8.GetBytes(key)
};
aes.GenerateIV();
var encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] buffer;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
byte[] bytes = Encoding.UTF8.GetBytes(input);
cs.Write(bytes, 0, bytes.Length);
}
buffer = ms.ToArray();
}
buffer = buffer.Concat(aes.IV).ToArray();
return Convert.ToBase64String(buffer);
}
private static String Decrypt(string text, string key)
{
RijndaelManaged aes = new RijndaelManaged
{
KeySize = 256,
BlockSize = 256,
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7,
Key = Encoding.UTF8.GetBytes(key)
};
byte[] encoded = Convert.FromBase64String(text);
byte[] buffer = encoded.Take(encoded.Length - aes.IV.Length).ToArray();
aes.IV = encoded.Skip(encoded.Length - aes.IV.Length).ToArray();
var decrypt = aes.CreateDecryptor();
byte[] xBuff;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
{
cs.Write(buffer, 0, buffer.Length);
}
xBuff = ms.ToArray();
}
var output = Encoding.UTF8.GetString(xBuff);
return output;
}
After couple of minutes of searching I've found simple decryption function in PHP using mcrypt:
function strippadding($string)
{
$slast = ord(substr($string, -1));
$slastc = chr($slast);
$pcheck = substr($string, -$slast);
if(preg_match("/$slastc{".$slast."}/", $string)){
$string = substr($string, 0, strlen($string)-$slast);
return $string;
} else {
return false;
}
}
function decrypt($string, $key)
{
$string = base64_decode($string);
$iv = substr($string, -32);
$string = str_replace($iv, "", $string);
return strippadding(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $string, MCRYPT_MODE_CBC, $iv));
}
This works well, but as I read on multiple sites, mcrypt is no longer recommended and sooner or later will be removed.
I'm trying to recreate same function using openssl, but without any luck.
I've tried replacing mcrypt_decrypt with:
openssl_decrypt($string, 'aes-256-cbc', $encryption_key, 0, $iv);
but as I found out MCRYPT_RIJNDAEL_256 doesn't mean AES-256.
I've been trying with different key size and block size, but without luck.
How can I recreate PHP decrypting function using openssl?
EDIT1 :
I've changed RijndaelManaged with AesCryptoServiceProvider in my C# code:
var aes = new AesCryptoServiceProvider()
{
KeySize = 256,
BlockSize = 128,
Padding = PaddingMode.PKCS7,
Mode = CipherMode.CBC,
Key = Encoding.UTF8.GetBytes(key)
};
and inside PHP to:
define('AES_128_CBC', 'aes-128-cbc');
function decrypt_openssl($string, $pkey)
{
$key = $pkey;
$string = base64_decode($string);
$iv = substr($string, -32);
$string = str_replace($iv, "", $string);
$decrypted = openssl_decrypt($string, AES_128_CBC, base64_encode($key), 0, base64_encode($iv));
return $decrypted;
}
but still I can't get encoded string to be decoded in PHP.
I need a way to decrypt output of my C# function or change both to get that two way communication working.
EDIT2:
I'm providing full source of my C# class:
public static string EncryptRijndael(string input, string key)
{
var aes = new RijndaelManaged
{
KeySize = 256,
BlockSize = 256,
Padding = PaddingMode.PKCS7,
Mode = CipherMode.CBC,
Key = Encoding.UTF8.GetBytes(key)
};
aes.GenerateIV();
var encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] buffer;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
byte[] bytes = Encoding.UTF8.GetBytes(input);
cs.Write(bytes, 0, bytes.Length);
}
buffer = ms.ToArray();
}
buffer = buffer.Concat(aes.IV).ToArray();
aes.Dispose();
return Convert.ToBase64String(buffer);
}
public static string DecryptRijndael(string input, string key)
{
var aes = new RijndaelManaged
{
KeySize = 256,
BlockSize = 256,
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7,
Key = Encoding.UTF8.GetBytes(key)
};
byte[] xXml = Convert.FromBase64String(input);
var buffer = xXml.Take(xXml.Length - aes.IV.Length).ToArray();
var iv = xXml.Skip(xXml.Length - aes.IV.Length).ToArray();
aes.IV = iv;
var decrypt = aes.CreateDecryptor();
byte[] xBuff;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
{
cs.Write(buffer, 0, buffer.Length);
}
xBuff = ms.ToArray();
}
aes.Dispose();
String output = Encoding.UTF8.GetString(xBuff);
return output;
}
public static string EncryptAes(string input, string key)
{
var aes = new AesCryptoServiceProvider()
{
KeySize = 256,
BlockSize = 128,
Padding = PaddingMode.PKCS7,
Mode = CipherMode.CBC,
Key = Encoding.UTF8.GetBytes(key)
};
aes.GenerateIV();
var encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] buffer;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
byte[] bytes = Encoding.UTF8.GetBytes(input);
cs.Write(bytes, 0, bytes.Length);
}
buffer = ms.ToArray();
}
buffer = buffer.Concat(aes.IV).ToArray();
aes.Dispose();
return Convert.ToBase64String(buffer);
}
public static String DecryptAes(string input, string key)
{
var aes = new AesCryptoServiceProvider()
{
KeySize = 256,
BlockSize = 128,
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7,
Key = Encoding.UTF8.GetBytes(key)
};
byte[] xXml = Convert.FromBase64String(input);
var buffer = xXml.Take(xXml.Length - aes.IV.Length).ToArray();
var iv = xXml.Skip(xXml.Length - aes.IV.Length).ToArray();
aes.IV = iv;
var decrypt = aes.CreateDecryptor();
byte[] xBuff;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
{
cs.Write(buffer, 0, buffer.Length);
}
xBuff = ms.ToArray();
}
aes.Dispose();
String output = Encoding.UTF8.GetString(xBuff);
return output;
}
My test key is: zjPUcCp9Jn7k8RtEzxTRePjn984LqwyN
My test data as plain text: zażółć geślą jaźń
My test data as base64: emHFvMOzxYLEhyBnZcWbbMSFIGphxbrFhA==
And sample output for both encryption functions:
Rijndael: 4gD/tt3I3hqYToLnwxI/HJ37EHfXrd1uxchIOjuxSuZl0Kyvxb+S6h4gG3cWKJTbj0wDSH1zvbeSvHd9Wu1VaA==
AES: B0dKdL4k9J6CeqlAekaXM+eh/zDqd5B4sKK2p6DFsgYNbV56Xdy01XvYPZX8ZXBc
IV is added at the end of byte array just before creating base64 output. When decrypting I'm reading IV from end of input string and using it to decrypt.
I need to ensure I can encrypt/decrypt utf-8 strings.
This is not an answer but added as an answer because of necessary formatting and length:
Provided by the OP:
Encryption input:
test key is: zjPUcCp9Jn7k8RtEzxTRePjn984LqwyN
test data as plain text: zażółć geślą jaźń (not used, see below)
test data as base64: emHFvMOzxYLEhyBnZcWbbMSFIGphxbrFhA== (used)
Sample output for both encryption functions:
Rijndael: 4gD/tt3I3hqYToLnwxI/HJ37EHfXrd1uxchIOjuxSuZl0Kyvxb+S6h4gG3cWKJTbj0wDSH1zvbeSvHd9Wu1VaA==
AES: B0dKdL4k9J6CeqlAekaXM+eh/zDqd5B4sKK2p6DFsgYNbV56Xdy01XvYPZX8ZXBc
Provided data displayed as hex for consistency, spaces added for legibility:
RijndaelExpected: e200ffb6 ddc8de1a 984e82e7 c3123f1c 9dfb1077 d7addd6e c5c8483a 3bb14ae6 65d0acaf c5bf92ea 1e201b77 162894db 8f4c0348 7d73bdb7 92bc777d 5aed5568
AESExpected: 07474a74 be24f49e 827aa940 7a469733 e7a1ff30 ea779078 b0a2b6a7 a0c5b206 0d6d5e7a 5ddcb4d5 7bd83d95 fc65705c
testData: 7a61c5bc c3b3c582 c4872067 65c59b6c c485206a 61c5bac5 84
testKey: 7a6a5055 63437039 4a6e376b 38527445 7a785452 65506a6e 3938344c 7177794e
testIV: 8f4c0348 7d73bdb7 92bc777d 5aed5568 (from RijndaelExpected trailing bytes).
The above is what one would hope for in a question.
Assumptions: PKCS#7 padding, CBC mode.
Based on the data 7-bytes of padding is expected so the encrypted data should be 32-bytes.
The RijndaelExpected output is 64-bytes, minus 16-bytes for the appended IV is 48-bytes which is incorrect.
The AESExpected output is 48-bytes. If the IV is appended it does not match RijndaelExpected, it the IV is not appended it is the wrong length.
My calculated AES output without an appended IV is (Note an IV generally prefixes the encrypted data):
CryptData: 1a6ec05d 00a6e61b 8196e7f2 879e2f59 25d3b7e2 c103f7e6 41c8c93f 70b32de5
Which does not agree with either expected output.
Also see this online AES calculator Note that PKCS#7 padding has been manually added.
For completness only, my test code:
NSData *testData = [[NSData alloc] initWithBase64EncodedString:#"emHFvMOzxYLEhyBnZcWbbMSFIGphxbrFhA==" options:0];
NSData *testKey = [#"zjPUcCp9Jn7k8RtEzxTRePjn984LqwyN" dataUsingEncoding:NSUTF8StringEncoding];
NSData *testIV = [[NSData alloc] initWithBase64EncodedString:#"j0wDSH1zvbeSvHd9Wu1VaA==" options:0];
size_t movedBytes = 0;
NSMutableData *cryptData = [NSMutableData dataWithLength: testData.length + kCCBlockSizeAES128];
CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
kCCOptionPKCS7Padding, // CBC mode is the default
testKey.bytes, kCCKeySizeAES256,
testIV.bytes,
testData.bytes, testData.length,
cryptData.mutableBytes, cryptData.length,
&movedBytes);
cryptData.length = movedBytes;
Display(#"CryptData: %#", cryptData);

C# triple DES wrapper problems: TransformFinalBlock throws 'Bad data'

I have a triple DES wrapper in C# that consists of two static functions, Encrypt and Decrypt. Occasionally, Decrypt fails with TransformFinalBlock(..., ...) throwing the error 'Bad data'.
Why is this happening?
What's the solution?
Thanks in advance.
public static string Encrypt(string toencrypt, string key, bool usehashing = true)
{
byte[] keyArray;
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toencrypt);
byte[] resultArray;
//If hashing use get hashcode regards to your key
if (usehashing)
{
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
//Always release the resources and flush data
// of the Cryptographic service provide. Best Practice
hashmd5.Clear();
}
else
keyArray = UTF8Encoding.UTF8.GetBytes(key);
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
//set the secret key for the tripleDES algorithm
tdes.Key = keyArray;
//mode of operation. there are other 4 modes.
//We choose ECB(Electronic code Book)
tdes.Mode = CipherMode.ECB;
//padding mode(if any extra byte added)
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tdes.CreateEncryptor();
try
{
//transform the specified region of bytes array to resultArray
resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
}
catch (System.Exception ex)
{
//Release resources held by TripleDes Encryptor
tdes.Clear();
return "";
}
//Release resources held by TripleDes Encryptor
tdes.Clear();
//Return the encrypted data into unreadable string format
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
public static string Decrypt(string todecrypt, string key, bool usehashing = true)
{
byte[] keyArray;
byte[] toEncryptArray;
byte[] resultArray;
//get the byte code of the string
try
{
toEncryptArray = Convert.FromBase64String(todecrypt.Replace(" ", "+"));//The replace happens only when spaces exist in the string (hence not a Base64 string in the first place).
}
catch (System.Exception ex)
{
return "";
}
if (usehashing)
{
//if hashing was used get the hash code with regards to your key
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
//release any resource held by the MD5CryptoServiceProvider
hashmd5.Clear();
}
else
{
//if hashing was not implemented get the byte code of the key
keyArray = UTF8Encoding.UTF8.GetBytes(key);
}
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
//set the secret key for the tripleDES algorithm
tdes.Key = keyArray;
//mode of operation. there are other 4 modes.
//We choose ECB(Electronic code Book)
tdes.Mode = CipherMode.ECB;
//padding mode(if any extra byte added)
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tdes.CreateDecryptor();
try
{
resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
}
catch (System.Exception ex)
{
//Release resources held by TripleDes Encryptor
tdes.Clear();
return "";
}
//Release resources held by TripleDes Encryptor
tdes.Clear();
//return the Clear decrypted TEXT
return UTF8Encoding.UTF8.GetString(resultArray);
}
An example string that once encrypted causes Decrypt to fail would be:
AgAAAA*AQAAAA*aAAAAA*jfgGTw*nY+sHZ2PrBmdj6wVnY+sEZ2PrA2dj6wFk4GhCJOHoQqdj6x9nY+seQ*trIBAA*AAMAAA**+L7PHiJ76M8OTV4BjXCkuDgDG2u7AcW87p1KU7KTSCKI3fYTnYAcGk1gyS62AvZO4g1FrsVbzoAnsX9Y0Ju+V9YjaYr9+Xr+pen4SEas0NjRvntv0gqU0QZOj9bjKXx1Izc9Dw1HCUqjUGBcwakQo6kBlvb2v2/pV9dM4B3RM6m7rmaW79CSc7CC3DQjnqA5HMHC5k65pOK0KT76MzTawYQotNOk0BabTO3HpVcI8BNNjSsIP7TvtxXBmbc6TfXahw1zLTvC4iTSPnsgz0jhxvHhHD+N0cblfQhAK/nt2IZQuWGL3jW0oPpPJnjhGMWQPDLXbNwp23WUv8GXIPKevXbushYKjutmsdqJT7C1mcB45XhbYCVUVbLIja1AV831YeHqqke2msSaisg37UM+urL9EFIueUHZgZryhQUSjAhZDiHXqosoQou92RqbTK5YTqYY+zyBBzRt2r7KS3v5u9smtWMNk8Xcn42a6pFFxd6g4u0/s/SVm7NFb2UbREvp75lBVxEQv5IIznPSHfDnLtuX8pLfrZ/AVQ+gM9AGvzBjHGNYDQJ6VhgkHOZMeuLISJXjfGX0ZPFYKd+CPObpbFlukOSlIB5epRDnuggTLnthpN06Kle+iDqz1Q96ty4mfzwuhRwxvQ7EMzTykHXxC8p9bLKMr86K/vart2D9w1g9RtyS+pekgW8lkutWWGdu1eZml/5abNmlW5VgSJiuA9Yyrd2UNjUl6/a0oMKHPk6b2gZkpmENpO7auC9HA2gO
However most strings do not cause it to fail. This must be something to do with special characters I'm guessing.
First, please provide the initial unencrypted key and string which generates that encrypted block that fails. Then we may have a better chance of figuring out why there's an issue. However, that being requested, I see a few potential pitfalls in your code, mostly related to not disposing of types which implement IDisposable. Here's a small refactoring of the code which takes that into account (amongst a few other small adjustments):
public static string Encrypt(string toencrypt, string key, bool usehashing = true)
{
byte[] keyArray;
// If hashing use get hash code regards to your key
if (usehashing)
{
using (var hashmd5 = new MD5CryptoServiceProvider())
{
keyArray = hashmd5.ComputeHash(Encoding.UTF8.GetBytes(key));
}
}
else
{
keyArray = Encoding.UTF8.GetBytes(key);
}
// set the secret key for the tripleDES algorithm
// mode of operation. there are other 4 modes.
// We choose ECB(Electronic code Book)
// padding mode(if any extra byte added)
using (var tdes = new TripleDESCryptoServiceProvider
{
Key = keyArray,
Mode = CipherMode.ECB,
Padding = PaddingMode.PKCS7
})
using (var transform = tdes.CreateEncryptor())
{
try
{
var toEncryptArray = Encoding.UTF8.GetBytes(toencrypt);
// transform the specified region of bytes array to resultArray
var resultArray = transform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
// Return the encrypted data into unreadable string format
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
catch (Exception)
{
return string.Empty;
}
}
}
public static string Decrypt(string todecrypt, string key, bool usehashing = true)
{
byte[] toEncryptArray;
// get the byte code of the string
try
{
toEncryptArray = Convert.FromBase64String(todecrypt.Replace(" ", "+")); // The replace happens only when spaces exist in the string (hence not a Base64 string in the first place).
}
catch (Exception)
{
return string.Empty;
}
byte[] keyArray;
if (usehashing)
{
// if hashing was used get the hash code with regards to your key
using (var hashmd5 = new MD5CryptoServiceProvider())
{
keyArray = hashmd5.ComputeHash(Encoding.UTF8.GetBytes(key));
}
}
else
{
// if hashing was not implemented get the byte code of the key
keyArray = Encoding.UTF8.GetBytes(key);
}
// set the secret key for the tripleDES algorithm
// mode of operation. there are other 4 modes.
// We choose ECB(Electronic code Book)
// padding mode(if any extra byte added)
using (var tdes = new TripleDESCryptoServiceProvider
{
Key = keyArray,
Mode = CipherMode.ECB,
Padding = PaddingMode.PKCS7
})
using (var transform = tdes.CreateDecryptor())
{
try
{
var resultArray = transform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
// return the Clear decrypted TEXT
return Encoding.UTF8.GetString(resultArray);
}
catch (Exception)
{
return string.Empty;
}
}
}

Categories

Resources