|
|
|
From the Logic Layer , What should you pass as the Source string and as the Key?
Happy Programming!
Regards,
ctrlnick !
|
|
|
|
|
OK, so heres the thing.
I discovered some instances where what I put in doesn't equal what I get back. To test this I did the following code against a version of the above code (perhaps an older version).
Just for clarity the code that tests this is below.
Anyway if 0.5% of cases the decrypted result does *not* equal what I put in. So watch out !
public static int Run()
{
CreditSights.Helper.Encryptor oEncryptor = new FangHome_Crypto.SymmCrypto(FangHome_Crypto.SymmCrypto.SymmProvEnum.Rijndael);
int countGood =0;
int countBad =0;
for (int i=0; i<1000000;i++)
{
//"ij1g5j"; example of bad pass for this key
// the following line calls GeneratePassword() which randomly
// generates a password consisting of 6 letters or numbers
string decryptedPassword1 = GeneratePassword();
string encryptedPassword = oEncryptor.Encrypting(decryptedPassword1, Key);
string decryptedPassword2 = oEncryptor.Decrypting(encryptedPassword, Key);
if (!decryptedPassword2.Equals(decryptedPassword1))
{
countBad++;
}
else
{
countGood++;
}
}
// outputs numbers like "0.00601870536419309" or "0.00521232321222"
System.Console.WriteLine("countBad/total = " + ((double) countBad)/((double)(countGood+countBad)));
}
|
|
|
|
|
Hello all,
Thought ya'll might want to know what I did to fix the problem I described above.
This is all very much thank you to the comments of Indra Gunawan in particular.
Note that, even though Frank has updated his code, I still had to update even that code with the suggestions of Indra G, in order to get my tests to work.
With the following changes, in my particular case, I get no errors.
Thanks again to Frank who posted the code in the first place.
//------
// in GetLegalKey()..
//------------
// safer to use default encoding so changed this..
//return ASCIIEncoding.ASCII.GetBytes(sTemp);
// to this..
return System.Text.Encoding.Default.GetBytes(sTemp);
//------------
// in Encrypting()..
//------------
// changed this..
// byte[] bytOut = ms.GetBuffer();
// int i = 0;
// for (i = 0; i < bytOut.Length; i++)
// if (bytOut[i] == 0)
// break;
//
// // convert into Base64 so that the
// // result can be used in xml
// return System.Convert.ToBase64String(bytOut, 0, i);
// to this..
byte[] bytOut = ms.ToArray();
return System.Convert.ToBase64String(bytOut);
//------------
|
|
|
|
|
Even with your fixes, it will still fail because you are using System.Text.Encoding.Default.GetBytes(sTemp); On most US/European system, it will most likely work. But it will not work in Japanese/Chinese systems, because the Default would be Shift-JIS/Big5/GB2312, the byte-array will definitely contains invalid data. To resolve this problem, a proper hack is to use System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(sTemp);
|
|
|
|
|
// Here's a version that I got working VERY fast and that
// supports all 4 synch crypt types. I've enhanced several
// of the basic operations to include some basic checks,
// standardization of the calls instead of byte-by-byte
// operations, and a few enhanced functions such as
// DecryptToHash and DecrtypeToHashBase64.
// Enjoy !
//
// 12-10-2002
// Corrected code resubmitted.
// Enhanced support for IV
// Made Rijndael (AES) the default
//
using System;
using System.Security.Cryptography;
using System.IO;
using System.Text;
namespace FangHome_Crypto
{
/// <summary>
/// SymmCrypto is a wrapper of System.Security.Cryptography.SymmetricAlgorithm classes
/// and simplifies the interface. It supports customized SymmetricAlgorithm as well.
/// </summary>
public class SymmCrypto
{
/// <remarks>
/// Supported .Net intrinsic SymmetricAlgorithm classes.
/// </remarks>
public enum SymmProvEnum : int
{
Rijndael, RC2, TripleDES, DES
}
private SymmetricAlgorithm mobjCryptoService;
public String Key;
public String Vector;
/// <remarks>
/// Default Constructor (uses Rijndael by default)
/// </remarks>
public SymmCrypto()
{
mobjCryptoService = new RijndaelManaged();
}
public SymmCrypto(string TheKey, string TheVector)
{
mobjCryptoService = new RijndaelManaged();
Key = TheKey;
Vector = TheVector;
}
/// <remarks>
/// Constructor for using an intrinsic .Net SymmetricAlgorithm class.
/// </remarks>
public SymmCrypto(SymmProvEnum NetSelected)
{
switch (NetSelected)
{
case SymmProvEnum.DES:
mobjCryptoService = new DESCryptoServiceProvider();
break;
case SymmProvEnum.RC2:
mobjCryptoService = new RC2CryptoServiceProvider();
break;
case SymmProvEnum.Rijndael:
mobjCryptoService = new RijndaelManaged();
break;
case SymmProvEnum.TripleDES:
mobjCryptoService = new TripleDESCryptoServiceProvider();
break;
}
}
public SymmCrypto(SymmProvEnum NetSelected, String TheKey, String TheVector)
{
switch (NetSelected)
{
case SymmProvEnum.DES:
mobjCryptoService = new DESCryptoServiceProvider();
break;
case SymmProvEnum.RC2:
mobjCryptoService = new RC2CryptoServiceProvider();
break;
case SymmProvEnum.Rijndael:
mobjCryptoService = new RijndaelManaged();
break;
case SymmProvEnum.TripleDES:
mobjCryptoService = new TripleDESCryptoServiceProvider();
break;
}
Key = TheKey;
Vector = TheVector;
}
/// <remarks>
/// Constructor for using a customized SymmetricAlgorithm class.
/// </remarks>
public SymmCrypto(SymmetricAlgorithm ServiceProvider)
{
mobjCryptoService = ServiceProvider;
}
/// <remarks>
/// Depending on the legal key size limitations of a specific CryptoService provider
/// and length of the private key provided, padding the secret key with space character
/// to meet the legal size of the algorithm.
/// </remarks>
private byte[] GetLegalKey(string Key)
{
if (mobjCryptoService.LegalKeySizes.Length > 0)
{
int lessSize = 0, moreSize = mobjCryptoService.LegalKeySizes[0].MinSize;
// key sizes are in bits
while (Key.Length * 8 > moreSize && mobjCryptoService.LegalKeySizes[0].SkipSize > 0 && moreSize < mobjCryptoService.LegalKeySizes[0].MaxSize)
{
lessSize = moreSize;
moreSize += mobjCryptoService.LegalKeySizes[0].SkipSize;
}
if(Key.Length > (moreSize / 8))
return ASCIIEncoding.ASCII.GetBytes(Key.Substring(0, (moreSize / 8)));
else
return ASCIIEncoding.ASCII.GetBytes(Key.PadRight(moreSize / 8, ' '));
}
else
return ASCIIEncoding.ASCII.GetBytes(Key);
}
private byte[] GetLegalIV(String Vector, int ivLength)
{
return ASCIIEncoding.ASCII.GetBytes(Vector.Substring(0, ivLength));
}
public string Encrypt(string Source)
{
if(Source==null || Key==null || Source.Length==0 || Key.Length == 0)
return "";
byte[] bytIn = System.Text.ASCIIEncoding.ASCII.GetBytes(Source);
// create a MemoryStream so that the process can be done without I/O files
System.IO.MemoryStream ms = new System.IO.MemoryStream();
// set the private key
mobjCryptoService.Key = GetLegalKey(Key);
mobjCryptoService.IV = GetLegalIV(Vector, mobjCryptoService.IV.Length);
// create Crypto Stream that transforms a stream using the encryption
CryptoStream cs = new CryptoStream(ms, mobjCryptoService.CreateEncryptor(), CryptoStreamMode.Write);
// write out encrypted content into MemoryStream
cs.Write(bytIn, 0, bytIn.Length);
cs.FlushFinalBlock();
// convert into Base64 so that the result can be used in xml
return System.Convert.ToBase64String(ms.GetBuffer(), 0, (int) ms.Length);
}
public string DecryptToHashBase64(string Source)
{
MD5CryptoServiceProvider H = new MD5CryptoServiceProvider();
return System.Convert.ToBase64String(
H.ComputeHash(
System.Text.ASCIIEncoding.ASCII.GetBytes(
Decrypt(Source))));
}
public string DecryptToHash(string Source)
{
MD5CryptoServiceProvider H = new MD5CryptoServiceProvider();
return System.Text.ASCIIEncoding.ASCII.GetString(
H.ComputeHash(
System.Text.ASCIIEncoding.ASCII.GetBytes(
Decrypt(Source))));
}
public string Hash(string Source)
{
MD5CryptoServiceProvider H = new MD5CryptoServiceProvider();
return System.Text.ASCIIEncoding.ASCII.GetString(
H.ComputeHash(
System.Text.ASCIIEncoding.ASCII.GetBytes(Source)));
}
public string HashBase64(string Source)
{
MD5CryptoServiceProvider H = new MD5CryptoServiceProvider();
return System.Convert.ToBase64String(
H.ComputeHash(
System.Text.ASCIIEncoding.ASCII.GetBytes(Source)));
}
public string Decrypt(string Source)
{
if(Source==null || Key==null || Source.Length==0 || Key.Length == 0)
return "";
// convert from Base64 to binary
byte[] bytIn = System.Convert.FromBase64String(Source);
// create a MemoryStream with the input
System.IO.MemoryStream ms = new System.IO.MemoryStream(bytIn, 0, bytIn.Length);
// set the private key
mobjCryptoService.Key = GetLegalKey(Key);
mobjCryptoService.IV = GetLegalIV(Vector, mobjCryptoService.IV.Length);
// create Crypto Stream that transforms a stream using the decryption
CryptoStream cs = new CryptoStream(ms, mobjCryptoService.CreateDecryptor(), CryptoStreamMode.Read);
// read out the result from the Crypto Stream
System.IO.StreamReader sr = new System.IO.StreamReader( cs );
return sr.ReadToEnd();
}
}
}
Sincerely,
William M. Rawls
Brainbench MVP for Visual Basic
http://www.brainbench.com
4017 Block Dr #2159
Irving, TX 75038
wrawls@firmsolutions.com
Cell: 972-365-2981
Home: 972-607-2550
Work: 972-507-3756
MSN:willrawls@hotmail.com
Welcome to the Evolution
==================
http://www.sliceanddice.com
|
|
|
|
|
I should note that this version experiences no "bad data" or other errors. I've tested all 4 algorythms several thousand times without error.
Sincerely,
William M. Rawls
Brainbench MVP for Visual Basic
http://www.brainbench.com
4017 Block Dr #2159
Irving, TX 75038
wrawls@firmsolutions.com
Cell: 972-365-2981
Home: 972-607-2550
Work: 972-507-3756
MSN:willrawls@hotmail.com
Welcome to the Evolution
==================
http://www.sliceanddice.com
|
|
|
|
|
I got the following exception on your version, when decrypting a string:
---------------------------------------------
An unhandled exception of type 'System.Security.Cryptography.CryptographicException' occurred in mscorlib.dll
Message: "PKCS7 padding is invalid and cannot be removed."
---------------------------------------------
The exception is thrown on the last line of the Decrypt method:
return sr.ReadToEnd();
Here's my code that's calling it:
string encryptionKey = "Xwhuuebll1jkh88er4jhsWWvlkejf";
SymmCrypto s = new SymmCrypto(SymmCrypto.SymmProvEnum.Rijndael);
string toReturn = s.Decrypt(encryptedString, encryptionKey);
s = null;
return toReturn;
|
|
|
|
|
Sorry, I guess I uploaded the wrong version. Please copy the newly updated version and try again.
Sincerely,
William M. Rawls
Brainbench MVP for Visual Basic
http://www.brainbench.com
2201 Wingren Rd
Irving, TX 75062-4680
wrawls@firmsolutions.com
Cell: 972-365-2981
Home: 972-607-2550
Work: 972-507-3520
Fax:561-325-5977
MSN:willrawls@hotmail.com
Welcome to the Evolution
==================
http://www.sliceanddice.com
|
|
|
|
|
If the Vector Length is less than IV.Length it generates an error.
This fixed the problem:
<br />
private byte[] GetLegalIV(string vector, int ivLength)<br />
{<br />
if (vector.Length > ivLength)<br />
return ASCIIEncoding.ASCII.GetBytes(vector.Substring(0, ivLength));<br />
else<br />
return ASCIIEncoding.ASCII.GetBytes(vector.PadRight(ivLength));<br />
}<br />
Regards,
Aquele Abraço,
Bruno Oliveira
Tecnologia Takenet
+55. 31. 3295.6308
+55. 31. 8803.6267 _gsm
|
|
|
|
|
KB Article is not available.
|
|
|
|
|
OMG you're doing it the hard way
Replace your constructor
public SymmCrypto(SymmProvEnum NetSelected)<br />
{<br />
switch (NetSelected)<br />
{<br />
case SymmProvEnum.DES:<br />
mobjCryptoService = new DESCryptoServiceProvider();<br />
break;<br />
case SymmProvEnum.RC2:<br />
mobjCryptoService = new RC2CryptoServiceProvider();<br />
break;<br />
case SymmProvEnum.Rijndael:<br />
mobjCryptoService = new RijndaelManaged();<br />
break;<br />
}<br />
}
with
<br />
public SymmCrypto(string algo)<br />
{<br />
mobjCryptoService = (SymmetricAlgorithm)CryptoConfig.CreateFromName( algo );<br />
}
This way your class will work with any symmetric algorithm available in the .NET framework without any additional work.
|
|
|
|
|
Here is the VB.NET version
<br />
Imports System<br />
Imports System.Security.Cryptography<br />
Imports System.IO<br />
Imports System.Text<br />
<br />
'SymmCrypto is a wrapper of System.Security.Cryptography.SymmetricAlgorithm classes<br />
'and simplifies the interface. It supports customized SymmetricAlgorithm as well.<br />
'taken from http://www.codeproject.com/dotnet/encryption_decryption.asp#xx222556xx<br />
<br />
Public Class Encryptor<br />
'Supported .Net intrinsic SymmetricAlgorithm classes.<br />
Public Enum Providers<br />
[DES]<br />
[RC2]<br />
[Rijndael]<br />
End Enum<br />
<br />
Private _CryptoService As SymmetricAlgorithm<br />
<br />
'Constructor for using an intrinsic .Net SymmetricAlgorithm class.<br />
Public Sub New(ByVal NetSelected As Providers)<br />
Select Case NetSelected<br />
Case Providers.DES<br />
_CryptoService = New DESCryptoServiceProvider()<br />
Case Providers.RC2<br />
_CryptoService = New RC2CryptoServiceProvider()<br />
Case Providers.Rijndael<br />
_CryptoService = New RijndaelManaged()<br />
End Select<br />
End Sub<br />
<br />
'Constructor for using a customized SymmetricAlgorithm class.<br />
Public Sub New(ByVal ServiceProvider As SymmetricAlgorithm)<br />
_CryptoService = ServiceProvider<br />
End Sub<br />
<br />
'Depending on the legal key size limitations of a specific CryptoService provider<br />
'and length of the private key provided, padding the secret key with space character<br />
'to meet the legal size of the algorithm.<br />
Private Function GetLegalKey(ByVal Key As String) As Byte()<br />
Dim sTemp As String<br />
If (_CryptoService.LegalKeySizes.Length > 0) Then<br />
Dim lessSize As Integer = 0<br />
Dim moreSize As Integer = _CryptoService.LegalKeySizes(0).MinSize<br />
'key sizes are in bits<br />
Do While (Key.Length * 8 > moreSize)<br />
lessSize = moreSize<br />
moreSize += _CryptoService.LegalKeySizes(0).SkipSize<br />
Loop<br />
sTemp = Key.PadRight(moreSize / 8, " ")<br />
Else<br />
sTemp = Key<br />
End If<br />
<br />
'convert the secret key to byte array<br />
Return ASCIIEncoding.ASCII.GetBytes(sTemp)<br />
End Function<br />
<br />
Public Function Encrypt(ByVal Source As String, ByVal Key As String) As String<br />
Dim bytIn As Byte() = System.Text.ASCIIEncoding.ASCII.GetBytes(Source)<br />
'create a MemoryStream so that the process can be done without I/O files<br />
Dim ms As MemoryStream = New MemoryStream()<br />
<br />
Dim bytKey As Byte() = GetLegalKey(Key)<br />
<br />
'set the private key<br />
_CryptoService.Key = bytKey<br />
_CryptoService.IV = bytKey<br />
<br />
'create an Encryptor from the Provider Service instance<br />
Dim encrypto As ICryptoTransform = _CryptoService.CreateEncryptor()<br />
<br />
'create Crypto Stream that transforms a stream using the encryption<br />
Dim cs As CryptoStream = New CryptoStream(ms, encrypto, CryptoStreamMode.Write)<br />
<br />
'write out encrypted content into MemoryStream<br />
cs.Write(bytIn, 0, bytIn.Length)<br />
cs.FlushFinalBlock()<br />
<br />
'get the output and trim the '\0' bytes<br />
Dim bytOut As Byte() = ms.GetBuffer()<br />
Dim i As Integer = 0<br />
For i = 0 To bytOut.Length<br />
If bytOut(i) = 0 Then Exit For<br />
Next<br />
<br />
'convert into Base64 so that the result can be used in xml<br />
Return System.Convert.ToBase64String(bytOut, 0, i)<br />
End Function<br />
<br />
Public Function Decrypt(ByVal Source As String, ByVal Key As String) As String<br />
'convert from Base64 to binary<br />
Dim bytIn As Byte() = System.Convert.FromBase64String(Source)<br />
'create a MemoryStream with the input<br />
Dim ms As MemoryStream = New MemoryStream(bytIn, 0, bytIn.Length)<br />
<br />
Dim bytKey As Byte() = GetLegalKey(Key)<br />
<br />
'set the private key<br />
_CryptoService.Key = bytKey<br />
_CryptoService.IV = bytKey<br />
<br />
'create a Decryptor from the Provider Service instance<br />
Dim encrypto As ICryptoTransform = _CryptoService.CreateDecryptor()<br />
<br />
'create Crypto Stream that transforms a stream using the decryption<br />
Dim cs As CryptoStream = New CryptoStream(ms, encrypto, CryptoStreamMode.Read)<br />
<br />
'read out the result from the Crypto Stream<br />
Dim sr As StreamReader = New StreamReader(cs)<br />
Return sr.ReadToEnd()<br />
End Function<br />
<br />
End Class<br />
|
|
|
|
|
Hi
I am using this as a base for my Rijndael way of encrypting strings
it works fine for most time , but it fails for a lot of time
the sncryption does not do it for the entire string , I really think this has something to do with the Key , should I have to set something before I set the key ?
|
|
|
|
|
I have the same deal using JAVA encryption in JSP. If the string gets to long, the thinig blow up.
I really wish someone knew why this happens ...
|
|
|
|
|
I have updated the source code with modifications regarding possible exceptions of "bad data" when some special characters are used in either the data or the key.
Please search for author articles to locate the new SymmCrypto.cs code.
Frank Fang can be reached at fangfrank@hotmail.com
|
|
|
|
|
I have located 2 places where patches can be done :
1. IV and Key are not same . IV is used to process block of data for the first time , so its size is determined by LegalBlockSizes . Key is used to encrypt and decrypt the whole data . By using this technique , you can also include TripleDES algorithm in your class .
2. For some patterns , the algorithms will fail because sequence of '\0' is intended as part of encrypted data . I suggest the same idea as PhallGuy . By using ToArray() you can change part of your code from ...
byte[] bytOut = ms.GetBuffer();
int i = 0;
for (i = 0; i < bytOut.Length; i++)
if (bytOut[i] == 0)
break;
return System.Convert.ToBase64String(bytOut, 0, i);
to ...
bytOut = ms.ToArray()
Return System.Convert.ToBase64String(bytOut)
Best Regards
IG
|
|
|
|
|
I haven't tested it yet, but I would recommend using Encoding.Default as apposed to ASCIIEncoding.ASCII to perform the convertion to/from strings/bytes. From what I remember when reading all the .NET docs, strings are simply wrappers to the old COM BSTR objects which were by convention allways Unicode strings. The implication then is that all .NET strings are Unicode strings underneath. Using Encoding.ASCII to encrypt/decrypt will progabbly give some weird results because of that. Anyway, this is really just a guest take it for what its worth.
|
|
|
|
|
I've been playing around with Cryptography a bit and I think I may have discovered some solutions to the errors above. First the trimming of the '\0' characters is not technically legal. It is very possible that the encrypted data generates perfectly valid embedded NULL characters. Also the use of GetBuffer() will not allways return the same set of data. Instead use ToArray() to get the stream's bytes. This is guaranteed to return all of the bytes written to the stream. An additional side effect is that it only returns the amount written so there's no need to trim the data later.
- PA
|
|
|
|
|
You are correct on the trimming of the '\0' error....just found that one today when my encryption stuff was throwing an exception....
|
|
|
|
|
I guess a little bit of formatting will greatly improve things.
More work for Paul and Andrew I guess
Nish
My miniputt high is now 29
I do not think I can improve on that
My temperament won't hold
www.busterboy.org
|
|
|
|
|
at least its not one big glob
James
Sonork ID: 100.11138 - Hasaki
"Smile your little smile, take some tea with me awhile.
And every day we'll turn another page.
Behind our glass we'll sit and look at our ever-open book,
One brown mouse sitting in a cage."
"One Brown Mouse" from Heavy Horses, Jethro Tull 1978
|
|
|
|
|
LOL
So you still remember that other one eh?
Nish
My miniputt high is now 29
I do not think I can improve on that
My temperament won't hold
www.busterboy.org
|
|
|
|
|
How could I forget!
James
Sonork ID: 100.11138 - Hasaki
"Smile your little smile, take some tea with me awhile.
And every day we'll turn another page.
Behind our glass we'll sit and look at our ever-open book,
One brown mouse sitting in a cage."
"One Brown Mouse" from Heavy Horses, Jethro Tull 1978
|
|
|
|