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.
jfb628
Puntor
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,
Ning
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
OmegaMan
Hi RizwanSharp
If you look my working example code, then you should notice, that I used the PasswordDeriveBytes method to overcome oversized keys the user has to remember and as an side effect it eliminated conversion problems.
Regards
Peca
spottedmahn22
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 ;-)
indigo-alien
Hello Sreerag,
I hope you are fine, The Key length and IV legth are essential for the encrption, decryption. Like if you have a 256 bit key it mean you must provide exact 32 bytes as a key.
If user types the wrong key in the text box or your bytes are lost in otherways then you'll get this length error. The better way to get Key and Password is to use from Encryption Algorithm itself.
There is also a class I think PasswordDerviedBytes and RNGCryptoServiceProvide in MSDN, It'll help you how to create a Key from a user Password, Remeber User doesnot know that he has to complete 32 bytes to encrypt or decrypt data so you have to create a strong random Key from his Password.
Please see MSDN for more help on this so you'lll better understand it.
I hope this will help you,
Best Regards,
Mark_Davies
Hello Dear,
I'm sorry I'm extremely busy in my projects and cant get time to test your code but I can recomend one thing, There are very good articles on www.codeproject .com which use PasswordDervieBytes to genevrate password so please go and see how they are working and take help from them. If your are stuck somewhere then please feel free to write again!
Best of Luck,
Dietz
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,
Joseph Stalin
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 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;
}
}
private static void DecryptData( String inName, String outName, byte[] Key, byte[] IV ){
//Create the file streams to handle the input and output files. FileStream fin = new FileStream( inName, FileMode.Open, FileAccess.Read ); FileStream fout = new FileStream( outName, FileMode.OpenOrCreate, FileAccess.Write );fout.SetLength( 0 );
//Create variables to help with read and write. byte[] bin = new byte[100]; //This is intermediate storage for the encryption. long rdlen = 0; //This is the total number of bytes written. long totlen = fin.Length; //This is the total length of the input file. int len; //This is the number of bytes to be written at a time. ICryptoTransform Decryptor = new TripleDESCryptoServiceProvider().CreateDecryptor( Key, IV ); CryptoStream encStream = new CryptoStream( fout, Decryptor , CryptoStreamMode.Write ); Console.WriteLine( "Decrypting..." ); //Read from the input file, then encrypt and write to the output file. while ( rdlen < totlen ){
len = fin.Read( bin, 0, 100 );
encStream.Write( bin, 0, len );
rdlen = rdlen + len;
Console.WriteLine( "{0} bytes processed", rdlen );}
encStream.Close();
fout.Close();
fin.Close();
}
private static void EncryptData( String inName, String outName, byte[] Key, byte[] IV ){
//Create the file streams to handle the input and output files. FileStream fin = new FileStream( inName, FileMode.Open, FileAccess.Read ); FileStream fout = new FileStream( outName, FileMode.OpenOrCreate, FileAccess.Write );fout.SetLength( 0 );
//Create variables to help with read and write. byte[] bin = new byte[100]; //This is intermediate storage for the encryption. long rdlen = 0; //This is the total number of bytes written. long totlen = fin.Length; //This is the total length of the input file. int len; //This is the number of bytes to be written at a time.
ICryptoTransform Encryptor = new TripleDESCryptoServiceProvider().CreateEncryptor( Key, IV ); CryptoStream encStream = new CryptoStream( fout, Encryptor, CryptoStreamMode.Write ); Console.WriteLine( "Encrypting..." ); //Read from the input file, then encrypt and write to the output file. while ( rdlen < totlen ){
len = fin.Read( bin, 0, 100 );
encStream.Write( bin, 0, len );
rdlen = rdlen + len;
Console.WriteLine( "{0} bytes processed", rdlen );}
encStream.Close();
fout.Close();
fin.Close();
}
static void Main(string[] args){
// Get a password from the user. Console.WriteLine( "Enter a password to produce a key:" ); //******************************************************** //* Security Note: Never hard-code a password within your //* source code. Hard-coded passwords can be retrieved //* from a compiled assembly. //******************************************************** byte[] pwd = Encoding.Unicode.GetBytes(Console.ReadLine()); byte[] salt = createRandomSalt(7); // Create a provider object. TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider(); try{
Console.WriteLine("Creating a key with PasswordDeriveBytes..."); // Create a PasswordDeriveBytes object and then create // a TripleDES key from the password and salt. PasswordDeriveBytes pdb = new PasswordDeriveBytes(pwd, salt); // Create the key and add it to the Key property.tdes.Key = pdb.CryptDeriveKey(
"TripleDES", "SHA1", 192, tdes.IV);
string ans = ""; // Get a action from the user. while ( ( ans != "e" ) && ( ans != "d" ) ){
Console.WriteLine( "Do you want to encrypt or decrypt file (E/D):" );ans =
Console.ReadLine();}
string inFile = ""; while ( inFile == "" ){
Console.WriteLine( "Enter the name of input file:" );inFile =
Console.ReadLine();}
string outFile = ""; while ( outFile == "" ){
Console.WriteLine( "Enter the name of output file:" );outFile =
Console.ReadLine();}
if ( string.Compare( ans, "e" ) == 0 ){
EncryptData( inFile, outFile, tdes.Key, tdes.IV );
}
if ( string.Compare( ans, "d" ) == 0 ){
DecryptData( inFile, outFile, tdes.Key, tdes.IV );
}
Console.WriteLine("Operation complete.");}
catch (Exception e){
Console.WriteLine(e.Message);}
finally{
// Clear the buffersclearBytes(pwd);
clearBytes(salt);
// Clear the key.tdes.Clear();
}
}
}
}
Main point here is that your cryptor accept only specific KEY / IV formats. In this program simply make Key by
tdes.Key = pdb.CryptDeriveKey("TripleDES", "SHA1", 192, tdes.IV);
so, it is guaranteed to be correct format (no blocksize exceptions etc.)
Hope that this working example solves your Question #1. Maybe I do some work for your Question #2, if I will have more spare time ): In the mean time, for general info about RC2, the best place is start reading from RSA Security - 3.6.2 What is RC2 site.
Ayooya
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;
}
}
Floaf
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 TripleDESCry