|
This class is written using 100% managed code that is dependant upon the functionality of the Microsoft .NET Framework and CLR in order to compile and execute.
While you could certainly write a C++ version that would compile in MS VC 6.0, this would require that you make direct use of the Win32 API and not the .NET Framework.
Unfortunatly, I do not have an example of how to do this. Perhaps you can find one elsewhere online.
Tony
|
|
|
|
|
Tony,
I wish my project is required on C#, your example is in such elegant way - nice and clear, nnfortunately, I canot use your code this time.
Thanks for all you done.
|
|
|
|
|
Hi Mindy,
Have a look at the crypto++ library, it should do what you want for C++ Check out http://www.cryptopp.com/[^] for more info
Ciao,
M.
|
|
|
|
|
using System;<br />
using System.IO;<br />
using System.Text;<br />
using System.Security.Cryptography;<br />
<br />
namespace Utilities.Crypto<br />
{<br />
class cTripleDES<br />
{<br />
private TripleDESCryptoServiceProvider m_des = new TripleDESCryptoServiceProvider();<br />
<br />
private UTF8Encoding m_utf8 = new UTF8Encoding();<br />
<br />
private byte[] m_key;<br />
private byte[] m_iv;<br />
<br />
public cTripleDES(byte[] key, byte[] iv)<br />
{<br />
this.m_key = key;<br />
this.m_iv = iv;<br />
}<br />
<br />
public byte[] Encrypt(byte[] input)<br />
{<br />
return Transform(input, m_des.CreateEncryptor(m_key, m_iv));<br />
}<br />
<br />
public byte[] Decrypt(byte[] input)<br />
{<br />
return Transform(input, m_des.CreateDecryptor(m_key, m_iv));<br />
}<br />
<br />
public string Encrypt(string text)<br />
{<br />
byte[] input = m_utf8.GetBytes(text);<br />
byte[] output = Transform(input, m_des.CreateEncryptor(m_key, m_iv));<br />
return Convert.ToBase64String(output);<br />
}<br />
<br />
public string Decrypt(string text)<br />
{<br />
byte[] input = Convert.FromBase64String(text);<br />
byte[] output = Transform(input, m_des.CreateDecryptor(m_key, m_iv));<br />
return m_utf8.GetString(output);<br />
}<br />
<br />
private byte[] Transform(byte[] input, ICryptoTransform CryptoTransform)<br />
{<br />
MemoryStream memStream = new MemoryStream();<br />
CryptoStream cryptStream = new CryptoStream(memStream, CryptoTransform, CryptoStreamMode.Write);<br />
cryptStream.Write(input, 0, input.Length);<br />
cryptStream.FlushFinalBlock();<br />
memStream.Position = 0;<br />
byte[] result = memStream.ToArray();<br />
memStream.Close();<br />
cryptStream.Close();<br />
return result;<br />
}<br />
}<br />
}
|
|
|
|
|
I have submitted an article update that includes the C# and VB.NET versions together within the article, but I don't know how long that will take to be updated, so here is your "advance copy." Enjoy!
|
|
|
|
|
OK,
your code looks much cleaner then mine. I take yours.
Thanks !
|
|
|
|
|
Hi,
I've got a exception (something like: The length of the datas are not correct) when I execute cryptStream.FlushFinalBlock() in the Transform Method.
I've translated the code to C#. Maybe this will cause the problem:
Do you have any ideas?
private byte[] Transform(byte[] input, ICryptoTransform CryptoTransform)
{
byte[] result = null;
try
{
MemoryStream memStream = new MemoryStream();
CryptoStream cryptStream = new CryptoStream(memStream, CryptoTransform, CryptoStreamMode.Write);
cryptStream.Write(input, 0, input.Length);
cryptStream.FlushFinalBlock() // Crash !!!!!!!!
memStream.Position = 0;
result = memStream.ToArray();
memStream.Close();
cryptStream.Close();
}
catch (Exception e)
{
MessageBox.Show(e.Message));
}
return result;
}
Andreas
|
|
|
|
|
I haven't seen or heard of such a problem, and you aren't the first person to port this to C#. What you are doing looks fine, but if you would post the entire C# class content along with an example of the offending call, I may have time to paste it into Visual Studio and see what happens.
Also, make sure you include the version of VS you are using. This was originally written for Fx 1.1. I have no reason to believe that it wouldn't run in VS2k5, but I haven't had occasion to try it yet.
|
|
|
|
|
One more question. Are you encrypting or decrypting when you get the error?
|
|
|
|
|
Hi Tony,
do you got my email with my code?
|
|
|
|
|
I never saw anything. What did you send, where did you send it and when?
|
|
|
|
|
Hmmm,
very curious.
I sent the email at, I think, 24. Feb 06. And I used the normal email Button below your comment.
I try to post my 2 classes this very day in the normal blog.
Chiao
Andreas
|
|
|
|
|
OK,
I've done a little examle project.
here are the two classes:
using System;
using System.Text;
namespace CryptoTest
{
public class UserMgr
{
private readonly byte[] key = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 };
private readonly byte[] IV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
private Crypto crypto = null;
public UserMgr()
{
crypto = new Crypto(key, IV);
crypto.Decrypt("1234"); // It musst be 4 characters (or 8,12,16)
}
}
}
using System;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Security.Cryptography;
namespace CryptoTest
{
class Crypto
{
private TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
private UTF8Encoding utf8 = new UTF8Encoding();
private byte[] Key;
private byte[] IV;
public Crypto(byte[] key, byte[] iv)
{
Key = key;
IV = iv;
}
public string Encrypt(string text)
{
byte[] input = utf8.GetBytes(text);
byte[] output = Transform(input, des.CreateDecryptor(Key, IV));
return utf8.GetString(output);
}
public string Decrypt(string text)
{
byte[] input = Convert.FromBase64String(text);
byte[] output = Transform(input, des.CreateDecryptor(Key, IV));
return utf8.GetString(output);
}
private byte[] Transform(byte[] input, ICryptoTransform CryptoTransform)
{
byte[] result = null;
try
{
MemoryStream memStream = new MemoryStream();
CryptoStream cryptStream = new CryptoStream(memStream, CryptoTransform, CryptoStreamMode.Write);
cryptStream.Write(input, 0, input.Length);
cryptStream.FlushFinalBlock(); // Crash
memStream.Position = 0;
result = memStream.ToArray();
memStream.Close();
cryptStream.Close();
}
catch (Exception e)
{
MessageBox.Show("Error: " + e.Message);
}
return result;
}
}
}
|
|
|
|
|
Okay, you have two problems that I see right of the bat ...
First, it's not a valid test to just randomly decrypt something. You should alter your test function to do something like mine, where you first encrypt a string and then decrypt it and finally compare the values to see if they match.
Second, you neglected to include the base 64 encoding function into your encrypt function, so this isn't ever going to work. Your example sends a non-base 64 string to the function, tries to decode the base 64 and then decrypt that.
Take another run through the conversion you did, make sure you haven't missed anything else, change your test to be a full-cycle with comparison of input and output and see where that gets you.
Tony
|
|
|
|
|
Ok,
changed my code at following points:
- First encrypt a string called "Password".
- Change my Encrypt(string text) Method and do UTF8 Encoding
Result: Crashes at the same line, when using FlushFinalBlock();
Code:
using System;
using System.Text;
namespace CryptoTest
{
public class UserMgr
{
private readonly byte[] key = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 };
private readonly byte[] IV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
private Crypto crypto = null;
public UserMgr()
{
crypto = new Crypto(key, IV);
string userName = "Passwort";
string s = crypto.Encrypt(userName);
string t = crypto.Decrypt(s);
}
}
}
using System;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Security.Cryptography;
namespace CryptoTest
{
class Crypto
{
private TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
private UTF8Encoding utf8 = new UTF8Encoding();
private byte[] Key;
private byte[] IV;
public Crypto(byte[] key, byte[] iv)
{
Key = key;
IV = iv;
}
public string Encrypt(string text)
{
Encoding utf8Encoding = Encoding.UTF8;
byte[] byteArray = new byte[utf8Encoding.GetByteCount(text)];
byteArray = utf8Encoding.GetBytes(text);
byte[] output = Transform(byteArray, des.CreateDecryptor(Key, IV));
return utf8.GetString(output);
}
public string Decrypt(string text)
{
byte[] input = Convert.FromBase64String(text);
byte[] output = Transform(input, des.CreateDecryptor(Key, IV));
return utf8.GetString(output);
}
private byte[] Transform(byte[] input, ICryptoTransform CryptoTransform)
{
byte[] result = null;
try
{
MemoryStream memStream = new MemoryStream();
CryptoStream cryptStream = new CryptoStream(memStream, CryptoTransform, CryptoStreamMode.Write);
cryptStream.Write(input, 0, input.Length);
cryptStream.FlushFinalBlock(); // Crash
memStream.Position = 0;
result = memStream.ToArray();
memStream.Close();
cryptStream.Close();
}
catch (Exception e)
{
MessageBox.Show("Error: " + e.Message);
}
return result;
}
}
}
|
|
|
|
|
Again, I must point you back to your conversion. Please take a few minutes to re-read the code and compare it, line by line, with your implementation and be sure to understand what's happening.
Your current problem is that you are using the TripleDESCryptoServiceProvider.CreateDecryptor() function inside of the Crypto.Encrypt() function.
As a result, you are taking "Password", mistakenly trying to decrypt it in Crypto.Encrypt() , then taking that result and trying to decrypt it again in Crypto.Decrypt() .
|
|
|
|
|
Juhuuu, got'em !!!!
Correct; it was a overside with the CreateDecryptor()
I also have to convert the encrypted string byte by byte into the result string. "utf8Encoding.GetString()" doesn't work well.
Thanks very much to you Tony
Here the code, if somebody wants to use it:
using System;
using System.Text;
namespace CryptoTest
{
public class UserMgr
{
private readonly byte[] key = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 };
private readonly byte[] IV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
private Crypto crypto = null;
public UserMgr()
{
crypto = new Crypto(key, IV);
string userName = "Password";
string s = crypto.Encrypt(userName);
string t = crypto.Decrypt(s);
}
}
}
using System;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Security.Cryptography;
namespace CryptoTest
{
class Crypto
{
private TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
private UTF8Encoding utf8 = new UTF8Encoding();
private byte[] Key;
private byte[] IV;
public Crypto(byte[] key, byte[] iv)
{
Key = key;
IV = iv;
}
public string Encrypt(string text)
{
Encoding utf8Encoding = Encoding.UTF8;
byte[] byteArray = new byte[utf8Encoding.GetByteCount(text)];
byteArray = utf8Encoding.GetBytes(text);
byte[] output1 = Transform(byteArray, des.CreateEncryptor(Key, IV));
string outputString = "";
foreach (byte b in output1)
{
outputString += Convert.ToChar(b);
}
return outputString;
}
public string Decrypt(string text)
{
byte[] byteArray = new byte[text.Length];
char c;
for (int i = 0; i < text.Length; i++)
{
c = Convert.ToChar(text.Substring(i, 1));
byteArray[i] = Convert.ToByte(c);
}
byte[] output = Transform(byteArray, des.CreateDecryptor(Key, IV));
return utf8.GetString(output);
}
private byte[] Transform(byte[] input, ICryptoTransform CryptoTransform)
{
byte[] result = null;
try
{
MemoryStream memStream = new MemoryStream();
CryptoStream cryptStream = new CryptoStream(memStream, CryptoTransform, CryptoStreamMode.Write);
cryptStream.Write(input, 0, input.Length);
cryptStream.FlushFinalBlock();
memStream.Position = 0;
result = memStream.ToArray();
memStream.Close();
cryptStream.Close();
}
catch (Exception e)
{
MessageBox.Show("Error: " + e.Message);
}
return result;
}
}
}
|
|
|
|
|
I posted a C# version for you that doesn't do all the looping and stuff.
|
|
|
|
|
i have the crash in decript...
|
|
|
|
|
Hello: I resolved the trouble in my soft . I tell you: I use to get the byte array to decrypt from a textbox after convert it, and things gona bad always, even with different providers. Then, I change the textbox where i saved the encrypted memorystream to recover, convert and decrypt back for an array, it is, I copy the initial array (data to encrypt) to another array, and I sent to decrypt the later, it works fine. The problem seems to be the algorithm was developed to save the data in a byte field and recover from that kind of store, I use a textbox to test it and it seems that does not run if we set in the middle a textbox or something like that.
My question is did you resolve in some other way. could you pass it please. Thank you. Bye.
|
|
|
|
|
I have to confess, I didn't follow what you were saying at all.
Without knowing better if/what the problem may be, all I can say is that botht he byte array and string overrides have worked as-is for a lot of people. If you are having a problem, I suggest the following:
(A) If you are using .NET 2.0 or later and C#, use the updated, generics-based version of this code, which you can find here: Symmetric Algorithm Helper[^].
(B) If you need VB.NET or you are limited to .NET 1.1, make sure that you are using the latest code above; this article has been revised since 2006, when this thread was started.
If neither of the above work for you, please post a more specific description or better yet an example of what you are doing and I will see what I can do to help.
|
|
|
|
|
Thank you Tony Selke for this code example you definitely saved a lot of time for me. Now, I have some questions if you don’t mind to answer! I am tiring to understand the “key” and “iv” concept. How do they work and which one should I change to make the data unique? I spouse that should be the key, but when I change the combination of “iv” it works as well. If it is the key that I should change than I noticed that if I change any of the digits by adding or subtracting one it will still decrypt the encrypted data; Is this normal? I’ll be glad to here from you!
|
|
|
|
|
Glad you liked the code! That's a good question and I don't know the answer off the top of my head. I always change both the key and vector to something unique. I would take a walk down "Google Lane" and see what you find.
|
|
|
|
|
Thank you for making this simple and easy to understand. I'm new to VB .NET and cryptography. So I've been struggling trying to use TripleDES with my application. You've just made my life a lot more easier. Thanks again. I'm looking forward to reading more useful articles from you.
-Long Nguyen
|
|
|
|
|
Hi, some string Encrypted have problem when Desencrypt.
cryptStream.FlushFinalBlock
String similar = "FDG$#D#=$==
Problem is -> "
I not can understand.
when Code get line : cryptStream.FlushFinalBlock
Stop.
Any idea ?
|
|
|
|
|