1) I get the following Exception when I try to decrypt data using TripleDES. -
"An unhandled exception of type 'System.Security.Cryptography.CryptographicException' occurred in mscorlib.dll
Additional information: Specified initialization vector (IV) does not match the block size for this algorithm."
How do I make things right
The code is as follows -
/* Provides TripleDES encryption and decryption using classes in the .net Framework 1.1 */
public class TripleDES_Cryptography
{
public static string Encrypt(string plaintext, string key, string IV)
{
TripleDES des3 = new TripleDESCryptoServiceProvider();
des3.Mode = CipherMode.CBC;
byte[] by_plaintext = Encoding.ASCII.GetBytes(plaintext); // Convert.FromBase64String(plaintext);
byte[] by_key = Encoding.ASCII.GetBytes(key); // Convert.FromBase64String(key);
byte[] by_IV = Encoding.ASCII.GetBytes(IV); // Convert.FromBase64String(IV);
des3.Key = by_key;
des3.IV = by_IV;
ICryptoTransform Encryptor = des3.CreateEncryptor(des3.Key,des3.IV);
MemoryStream ms = new MemoryStream();
ms.Write(by_plaintext,0,by_plaintext.Length);
CryptoStream cs = new CryptoStream(ms,Encryptor,CryptoStreamMode.Write);
byte[] by_ciphertext = ms.ToArray();
string ciphertext = Convert.ToBase64String( by_ciphertext ); //Encoding.ASCII.GetString(by_ciphertext);
cs.Close();
return ciphertext;
}
public static string Decrypt(string ciphertext, string key, string IV)
{
DES des3 = new DESCryptoServiceProvider();
des3.Mode = CipherMode.CBC;
byte[] by_ciphertext = Convert.FromBase64String(ciphertext);//Encoding.ASCII.GetBytes(ciphertext);
byte[] by_key = Encoding.ASCII.GetBytes(key); // Convert.FromBase64String(key);
byte[] by_IV = Encoding.ASCII.GetBytes(IV); // Convert.FromBase64String(IV);
des3.Key = by_key;
des3.IV = by_IV;
ICryptoTransform Decryptor = des3.CreateDecryptor(des3.Key,des3.IV);
MemoryStream ms = new MemoryStream();
ms.Write(by_ciphertext,0,by_ciphertext.Length);
CryptoStream cs = new CryptoStream(ms,Decryptor,CryptoStreamMode.Write);
byte[] by_plaintext = ms.ToArray();
string plaintext = Encoding.ASCII.GetString(by_plaintext);// Convert.ToBase64String( by_plaintext );
cs.Close();
return plaintext;
}
}
Question No. 2) How can I perform RC2 encryption and decryption in the above fashion
The key size always appears wrong. It seems RC2 works with variable key sizes but how do I exploit the feature

Help with TripleDES and RC2 cryptography.
Grant Fritchey
You are getting error In decryption using the same length of Key because you did something wrong I know it would be a typing mistake that's suckking you up
:
public static string Decrypt(string ciphertext, string key, string IV)
{
DES des3 = new DESCryptoServiceProvider(); // Wrong Algorithm...
TripleDES des3 = new TripleDESCryptoServiceProvider();
The second problem in your code is that you are accepting IV from User which is again a problem IV must be of exact length what this Algorithm Supports that is 8 bytes you can have many solutions hot to use Fixed sized IVs you can also Trim your key to 8 bytes and use it as IV.
I hope your problem is solved now.
Cheers ;-)
Caleb T
Hi again,
I did what you asked me to, but it didn't work. It causes the following Format Exception-
"An unhandled exception of type 'System.FormatException' occurred in Cryptography.exe
Additional information: Invalid length for a Base-64 char array."
But the code I posted works perfectly for DES, Rijndael and RC2(I've solved the problem). I'm using the following procedure for all the above -
ENCRYPTION
----------
1. Use ASCII encoding to get the byte[] from the strings - plaintext, key and IV ( Encoding.ASCII.GetBytes() ).
2. I encrypt the byte[] and
3. Display the ciphertext using Convert.ToBase64String().
DECRYPTION
----------
1. Convert.FromBase64String(ciphertext) to get the byte[] from ciphertext.
2. Decrypt the byte[].
3. Display the plaintext using Encoding.ASCII.GetString().
Please note that I am not storing the key and IV anywhere. The user is asked to enter the key in the textbox tbKey. I use the key string to get the byte[] and initialize the IV as the key itself;
So the user does not explicitly enter the IV -
// The prototype is --- public static string Encrypt(string plaintext, string key, string IV)
tbCiphertext.Text = DES_Cryptography.Encrypt(tbplaintext.Text,tbKey.Text,tbKey.Text); // The Call
// the tbKey.Text is passed as both the Key and IV strings
The ciphertext is displayed in the textbox tbCiphertext. Now the assumption is that the user may save this encrypted text somewhere. He should be able to decrypt the ciphertext at a later time by entering the ciphertext and key (assume he has to remember the key) in the concerned textboxes.
I hope my intent is clear now.
*************************************************************************************************
Also, sometimes I get exceptions relating to invalid block sizes or key lengths or IV length not matching block sizes. How do I eliminate the above embarassing situations in a manner that is transparent to the user (The user is not required to know the correct block sizes. He may only be asked to enter key of correct length.The user must be able to encrypt and decrypt text of any size)
Nagaraj K
True! Thats Good ;)
jphoekstra
Thanks for your reply and for taking the trouble to help me. I truly appreciate it.
However, I'd be happier if yu could please fix the code I posted by telling me what's wrong with it.
Again, I'm not trying to encrypt files as such. Also, I derive the key and IV from string values entered by the user.
Could you try modifying my code
mEt
Hi Rizwan,
I corrected the instantiation error. The IV problem is solved by making the algorithm generate the IV by itself. But now I have found yet another vulnerability in the program. Any user can get the original plaintext from the ciphertext by simply supplying ANY key of the correct length. The key (password) need not necessarily be the one originally supplied to generate the ciphertext. Any password of a valid key size will accomplish the same.
For example, consider the following scenario –
ENCRYPTION
PLAINTEXT (tbplaintext.Text)
KEY (PASSWORD) (tbKey.Text)
CIPHERTEXT (tbCiphertext.Text)
Hello World
password
SGVsbG8gV29ybGQ=
DECRYPTION
CIPHERTEXT
(tbCiphertext.Text)
KEY (PASSWORD) (tbKey.Text)
PLAINTEXT
(tbplaintext.Text)
SGVsbG8gV29ybGQ=
password
Hello World
SGVsbG8gV29ybGQ=
anything
Hello World
SGVsbG8gV29ybGQ=
Yet anything
Hello World
SGVsbG8gV29ybGQ=
Anything at all
Hello World
SGVsbG8gV29ybGQ=
Hello World
The way I want it, the original plaintext should be reproduced only if the correct key (password) is provided. Some random (incorrect) plaintext may be produced if the wrong key is supplied.
I’m posting my entire class here. What is the problem with the code I think it’s some problem with the encoding. I’m not at all familiar with how to use these encoding schemes (ASCII, Base 64).
Could you please help me
Regards and respect,
Sreerag
/* Provides TripleDES encryption and decryption using classes in the .net Framework 1.1 */
public class TripleDES_Cryptography
{
public static byte[] createRandomSalt(int Length)
{
// Create a buffer
byte[] randBytes;
if (Length >= 1)
{
randBytes = new byte[Length];
}
else
{
randBytes = new byte[1];
}
// Create a new RNGCryptoServiceProvider.
RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
// Fill the buffer with random bytes.
rand.GetBytes(randBytes);
// return the bytes.
return randBytes;
}
public static void clearBytes(byte[] Buffer)
{
// Check arguments.
if (Buffer == null)
{
throw new ArgumentException("Buffer");
}
// Set each byte in the buffer to 0.
for (int x = 0; x <= Buffer.Length - 1; x++)
{
Buffer[x] = 0;
}
}
public static string Encrypt(string plaintext, string key, string IV)
{
TripleDES des3 = new TripleDESCryptoServiceProvider();
des3.Mode = CipherMode.CBC;
byte[] salt = createRandomSalt(7);
byte[] by_plaintext = Encoding.ASCII.GetBytes(plaintext);
byte[] by_IV =Encoding.ASCII.GetBytes(IV);
string strPassWd = key;
PasswordDeriveBytes pdb = new PasswordDeriveBytes(strPassWd,salt);
// des3.IV = by_IV;
des3.Key = pdb.CryptDeriveKey("TripleDES","SHA1",192,des3.IV);
ICryptoTransform Encryptor = des3.CreateEncryptor(des3.Key,des3.IV);
MemoryStream ms = new MemoryStream();
ms.Write(by_plaintext,0,by_plaintext.Length);
CryptoStream cs = new CryptoStream(ms,Encryptor,CryptoStreamMode.Write);
byte[] by_ciphertext = ms.ToArray();
string ciphertext = Convert.ToBase64String( by_ciphertext );
cs.Close();
clearBytes(salt);
des3.Clear();
return ciphertext;
}
public static string Decrypt(string ciphertext, string key, string IV)
{
TripleDES des3 = new TripleDESCryptoServiceProvider();
des3.Mode = CipherMode.CBC;
byte[] salt = createRandomSalt(7);
byte[] by_ciphertext = Convert.FromBase64String(ciphertext);
byte[] by_IV = Encoding.ASCII.GetBytes(IV);
string strPw = key;
PasswordDeriveBytes pdb = new PasswordDeriveBytes(strPw,salt);
// des3.IV = by_IV;
des3.Key = pdb.CryptDeriveKey("TripleDES","SHA1",192,des3.IV);
ICryptoTransform Decryptor = des3.CreateDecryptor(des3.Key,des3.IV);
MemoryStream ms = new MemoryStream();
ms.Write(by_ciphertext,0,by_ciphertext.Length);
CryptoStream cs = new CryptoStream(ms,Decryptor,CryptoStreamMode.Write);
byte[] by_plaintext = ms.ToArray();
string plaintext = Encoding.ASCII.GetString(by_plaintext);
cs.Close();
clearBytes(salt);
des3.Clear();
return plaintext;
}
}
andypai
Hi Again!
The problem is obvious in your code, First of all do this in both Encryption and Decryption Methods:
byte[] by_key = Encoding.ASCII.GetBytes(key); // Convert.FromBase64String(key);
byte[] by_IV = Encoding.ASCII.GetBytes(IV); // Convert.FromBase64String(IV);
byte[] by_key = Convert.FromBase64String(key);
byte[] by_IV = Convert.FromBase64String(IV);
and make sure where you are saving these keys always use Convert.ToBase64String() no ASCII.
It'll work surely ;-) if not then please also post the code where you are saying these keys
Second Question:
I have never used RC2 Encryption, RijndaelManaged is the best class to use in .Net's Symetric encryption so I always use Rijndael (AES Encryption). If you need help in RC2 Iw'll check it what's the problem you can post me the code. But its recommended to use Rijndael with 256 bit key size, 256 block size etc.
What I do is Create a New IV for each message Encryption, so If you encrypt the same string for 1000000 times you'll get different Cipher Text.
Anyhow, that's another matter,
Best Regards,
Ehsan_AIUB
Hi Peca55,
I went through your code and am now convinced that I should use PasswordDeriveBytes to derive the key from a password the user enters. However, I found that the first argument ‘pwd’ in
PasswordDeriveBytes pdb = new PasswordDeriveBytes(pwd, salt);
is a string and not a byte[] array.
Using your suggested method, I could perform the encryption successfully, but I am getting the following when I try to decrypt –
An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll
Additional information: Specified key is not a valid size for this algorithm.
My questions are –
1) Why do I get the exception when decrypting but not when encrypting After all, I use the same 192 bits key in both.
2) Is the key guaranteed to be the same during separate executions Assume the user saves the ciphertext somewhere and ends the program. Later when he performs, does he get the same key
Other vice he would not get the same plaintext, would he This is dependent on
createRandomSalt(7) giving the same value. Does that happen
Remember, the function calls are as follows –
// Encryption
tbCiphertext.Text = TripleDES_Cryptography.Encrypt(tbplaintext.Text,tbKey.Text,tbKey.Text);
// Decryption
tbplaintext.Text = TripleDES_Cryptography.Decrypt(tbCiphertext.Text,tbKey.Text,tbKey.Text);
where tbKey, tbCiphertext and tbplaintext are textboxes for entering the password, ciphertext and the plaintext, respectively.Also, I’m passing the tbKey.text for both the key and IV.
I’m posing my entire class here. I’d be very grateful if you could help me fix the errors. Thanks again for your help so far.
Respect,
Sreerag
**********************************************************************************************************************************
/* Provides TripleDES encryption and decryption using classes in the .net Framework 1.1 */
public class TripleDES_Cryptography
{
public static byte[] createRandomSalt(int Length)
{
// Create a buffer
byte[] randBytes;
if (Length >= 1)
{
randBytes = new byte[Length];
}
else
{
randBytes = new byte[1];
}
// Create a new RNGCryptoServiceProvider.
RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
// Fill the buffer with random bytes.
rand.GetBytes(randBytes);
// return the bytes.
return randBytes;
}
public static void clearBytes(byte[] Buffer)
{
// Check arguments.
if (Buffer == null)
{
throw new ArgumentException("Buffer");
}
// Set each byte in the buffer to 0.
for (int x = 0; x <= Buffer.Length - 1; x++)
{
Buffer[x] = 0;
}
}
public static string Encrypt(string plaintext, string key, string IV)
{
TripleDES des3 = new TripleDESCryptoServiceProvider();
des3.Mode = CipherMode.CBC;
byte[] salt = createRandomSalt(7);
byte[] by_plaintext = Encoding.ASCII.GetBytes(plaintext); byte[] by_IV = Encoding.ASCII.GetBytes(IV);
string strPassWd = key;
PasswordDeriveBytes pdb = new PasswordDeriveBytes(strPassWd,salt);
des3.IV = by_IV;
des3.Key = pdb.CryptDeriveKey("TripleDES","SHA1",192,des3.IV);
ICryptoTransform Encryptor = des3.CreateEncryptor(des3.Key,des3.IV);
MemoryStream ms = new MemoryStream();
ms.Write(by_plaintext,0,by_plaintext.Length);
CryptoStream cs = new CryptoStream(ms,Encryptor,CryptoStreamMode.Write);
byte[] by_ciphertext = ms.ToArray();
string ciphertext = Convert.ToBase64String( by_ciphertext );
cs.Close();
clearBytes(salt);
des3.Clear();
return ciphertext;
}
public static string Decrypt(string ciphertext, string key, string IV)
{
DES des3 = new DESCryptoServiceProvider();
des3.Mode = CipherMode.CBC;
byte[] salt = createRandomSalt(7);
byte[] by_ciphertext = Convert.FromBase64String(ciphertext);
byte[] by_IV = Encoding.ASCII.GetBytes(IV);
string strPw = key;
PasswordDeriveBytes pdb = new PasswordDeriveBytes(strPw,salt);
des3.IV = by_IV;
des3.Key = pdb.CryptDeriveKey("TripleDES","SHA1",192,des3.IV);
ICryptoTransform Decryptor = des3.CreateDecryptor(des3.Key,des3.IV);
MemoryStream ms = new MemoryStream();
ms.Write(by_ciphertext,0,by_ciphertext.Length);
CryptoStream cs = new CryptoStream(ms,Decryptor,CryptoStreamMode.Write);
byte[] by_plaintext = ms.ToArray();
string plaintext = Encoding.ASCII.GetString(by_plaintext);
cs.Close();
clearBytes(salt);
des3.Clear();
return plaintext;
}
}
Pikachu881
Wicket
HiRizwan,
Thanks for poinint it out.
I feel like an idiot troubling you all this while.
I'll correct the mistake and let you know.
Respect,
Sreerag,
Alexey Rokhin
public class TripleDES_Cryptography
{
public static string Encrypt(string plaintext, string key, string IV)
{
TripleDES des3 = new TripleDESCryptoServiceProvider();
des3.Mode = CipherMode.CBC;
byte[] by_plaintext = Encoding.ASCII.GetBytes(plaintext); // Convert.FromBase64String(plaintext);
byte[] by_key = Encoding.ASCII.GetBytes(key); // Convert.FromBase64String(key);
byte[] by_IV = Encoding.ASCII.GetBytes(IV); // Convert.FromBase64String(IV);
byte[] by_key = Convert.FromBase64String(key);
byte[] by_IV = Convert.FromBase64String(IV);
des3.Key = by_key;
des3.IV = by_IV;
ICryptoTransform Encryptor = des3.CreateEncryptor(des3.Key,des3.IV);
MemoryStream ms = new MemoryStream();
ms.Write(by_plaintext,0,by_plaintext.Length);
CryptoStream cs = new CryptoStream(ms,Encryptor,CryptoStreamMode.Write);
byte[] by_ciphertext = ms.ToArray();
string ciphertext = Convert.ToBase64String( by_ciphertext ); //Encoding.ASCII.GetString(by_ciphertext);
cs.Close();
return ciphertext;
}
public static string Decrypt(string ciphertext, string key, string IV)
{
DES des3 = new DESCryptoServiceProvider();
des3.Mode = CipherMode.CBC;
byte[] by_ciphertext = Convert.FromBase64String(ciphertext);//Encoding.ASCII.GetBytes(ciphertext);
byte[] by_key = Encoding.ASCII.GetBytes(key); // Convert.FromBase64String(key);
byte[] by_IV = Encoding.ASCII.GetBytes(IV); // Convert.FromBase64String(IV);
byte[] by_key = Convert.FromBase64String(key);
byte[] by_IV = Convert.FromBase64String(IV);
des3.Key = by_key;
des3.IV = by_IV;
ICryptoTransform Decryptor = des3.CreateDecryptor(des3.Key,des3.IV);
MemoryStream ms = new MemoryStream();
ms.Write(by_ciphertext,0,by_ciphertext.Length);
CryptoStream cs = new CryptoStream(ms,Decryptor,CryptoStreamMode.Write);
byte[] by_plaintext = ms.ToArray();
string plaintext = Encoding.ASCII.GetString(by_plaintext);// Convert.ToBase64String( by_plaintext );
cs.Close();
return plaintext;
}
}
I hope this will work fine.
I'm a bit busy so I'm writing in some Quick.... So please done mind. I'll get back to you again.
Best Regards,
karande23
Doing some detective work, I made simple TripleDES console app from various samples. Here is my code:
using
System;using
System.Security.Cryptography;using
System.Text;using
System.IO;namespace
tdes{
class
Program{
//******************************************************** //* Helper methods: //* createRandomSalt: Generates a random salt value of the //* specified length. //* //* clearBytes: Clear the bytes in a buffer so they can't //* later be read from memory. //******************************************************** public static