Bad Data using TripleDES Encryption

From: Troy Busot (troy@busot.com)
Date: 03/13/03


From: "Troy Busot" <troy@busot.com>
Date: Wed, 12 Mar 2003 16:24:00 -0700


When using TripleDES encryption, I get random, but consistent Bad Data
exceptions.
For example, when looping from 0 to 100, I encrypt and decrypt the values.
The numbers 60 and 96 always throw exceptions when using the key "tbird".

for( int i = 0; i < 100; i++ )
{
  try
  {
    string t = StringUtility.EncryptString( i.ToString() );
    Response.Write( t + " : " );
    Response.Write( StringUtility.DecryptString( t ) + "<br>" );
  }
  catch( Exception )
  {
    Response.Write( i + " bad data.<br>" );
  }
}

There is very little documentation out there for this. Is it my Key? My IV?
It's driving me crazy! Any help would be appreciated.
Troy Busot

Here is my encryption/decryption code:
public class StringUtility
{

    /// <summary>
    /// Encrypts a string using TripleDES encryption.
    /// </summary>
    /// <param name="toEncrypt">String value to encrypt.</param>
    /// <returns></returns>
    public static string EncryptString( string toEncrypt )
    {
        string s;
        if ( toEncrypt != String.Empty && toEncrypt != null )
        {
            SymmCrypto symmCrypto = new SymmCrypto(
SymmCrypto.SymmProvEnum.DES );
            s = symmCrypto.EncString( toEncrypt );
        }
        else
        {
            s = toEncrypt;
        }
        return s;
    }
    /// <summary>
    /// Decrypts a string encrypted using TripleDES encryption.
    /// </summary>
    /// <param name="toDecrypt">String value to decrypt.</param>
    /// <returns></returns>
    public static string DecryptString( string toDecrypt )
    {
        string s;
        if ( toDecrypt != String.Empty && toDecrypt != null )
        {
            SymmCrypto symmCrypto = new SymmCrypto(
SymmCrypto.SymmProvEnum.DES );
            s = symmCrypto.DecString( toDecrypt );
        }
        else
        {
            s = toDecrypt;
        }
        return s;
    }
}

/// <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
{
DES, RC2, Rijndael
}
private SymmetricAlgorithm mobjCryptoService;
/// <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;
}
}
/// <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)
{
string sTemp;
if (mobjCryptoService.LegalKeySizes.Length > 0)
{
int lessSize = 0, moreSize = mobjCryptoService.LegalKeySizes[0].MinSize;
// key sizes are in bits
while (Key.Length * 8 > moreSize)
{
lessSize = moreSize;
moreSize += mobjCryptoService.LegalKeySizes[0].SkipSize;
}
sTemp = Key.PadRight(moreSize / 8, ' ');
}
else
sTemp = Key;
// convert the secret key to byte array
return ASCIIEncoding.ASCII.GetBytes(sTemp);
}
public string EncString( string Source )
{
return EncString( Source, "tbird" );
}
public string EncString(string Source, string Key)
{
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();
byte[] bytKey = GetLegalKey(Key);
// set the private key
mobjCryptoService.Key = bytKey;
mobjCryptoService.IV = bytKey;
// create an Encryptor from the Provider Service instance
ICryptoTransform encrypto = mobjCryptoService.CreateEncryptor();
// create Crypto Stream that transforms a stream using the encryption
CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Write);
// write out encrypted content into MemoryStream
cs.Write(bytIn, 0, bytIn.Length);
cs.FlushFinalBlock();
// get the output and trim the '\0' bytes
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);
}
public string DecString( string Source )
{
return DecString( Source, "tbird" );
}
public string DecString(string Source, string Key)
{
string decrypted;
// 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);
byte[] bytKey = GetLegalKey(Key);
// set the private key
mobjCryptoService.Key = bytKey;
mobjCryptoService.IV = bytKey;
// create a Decryptor from the Provider Service instance
ICryptoTransform encrypto = mobjCryptoService.CreateDecryptor();
// create Crypto Stream that transforms a stream using the decryption
CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Read);
// read out the result from the Crypto Stream
System.IO.StreamReader sr = new System.IO.StreamReader( cs );
decrypted = sr.ReadToEnd();
return decrypted;
// byte[] arrDest = new BinaryReader( cs ).ReadBytes( Convert.ToInt32(
ms.Length ) * 2 );
// return Convert.ToBase64String( arrDest );
}
}



Relevant Pages

  • Re: Security.Crypto.. API question
    ... Thanks for the information however I cant seem to decrypt a string sent to ... CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Read); ... Then you can ignore the IV and decode the Perl output. ...
    (microsoft.public.dotnet.framework.aspnet.security)
  • Re: storing a username and password
    ... decrypt the decrypt the password it throws the following exception: ... public static string Decrypting ... CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Read); ...
    (microsoft.public.dotnet.security)
  • Re: Byte array to string and back - newbie question
    ... // Create a symmetric algorithm. ... This is done to make encryption more ... // Encrypt a string into a string using a password ... // Decrypt a byte array into a byte array using a key and an IV ...
    (microsoft.public.dotnet.framework.aspnet.security)
  • Re: Encrypt and Decrypt a file using .NET 2.0?
    ... public static string GenerateKey() ... DES des = DES.Create; ... // Distribute this key to the user who will decrypt this file. ... // Get the Key for the file to Encrypt. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: a problem with encryption
    ... >> That way I always get the original data I've encrypted. ... I really don't know a way to know how long the string I send to ... > encrypted data in a byte array trough network stream. ... to decrypt in one call, ...
    (microsoft.public.dotnet.general)

Quantcast