Simple string encryption (solution)

  • Thread starter Thread starter Alan Samet
  • Start date Start date
A

Alan Samet

This message includes a solution for encrypting and encoding a string
into a "safe" character string that you can read or pass in ASP.NET
querystrings, and then decode and decrypt it back to its original form.
If you find it useful, please let me know.

I had an issue with a web site that I was working on where I needed to
pass around a moniker in my querystring. While the database itself
performed relevant security checks, I didn't want to expose this to my
users. The problem I had is that I just wanted to encrypt/decrypt a
string without having to know or understand anything about the
cryptography namespace. I also wanted to be able to pass this value
around in my QueryString. This code takes the unmodified symmetric
encryption example code that Lion Shi posted a while back on Usenet,
converts the resultant bytes to hex and then performs a simple
substitution for aesthetics.

If you plan to use this for your own purposes, and since I've posted
this publicly, I recommend you change the values of the two variables
having the value of "password" (they don't have to match, but if I
remember what I've read on DES, I believe they need to be a multiple of
8 characters in length).

The code that Lion Shi originally posted is located here:

http://groups-beta.google.com/group...t.languages.csharp/msg/eb7712e9e5cc1045?hl=en

This is the modified version that encodes the resultant byte arrays
into strings. It seems to work on the three strings that I've tested it
with, but I make no guarantees on its security or reliability.

Usage Example:

string s = "Raw Text String";
Response.Write(s);
s = Encryption.Encode(s);
Response.Write(s);
s = Encryption.Decode(s);
Response.Write(s);

Source:

using System;
using System.Collections;
using System.IO;
using System.Security;
using System.Security.Cryptography;
using System.Text;

public class Encryption
{
private Encryption(){}

static byte[] m_bDESKey = ASCIIEncoding.ASCII.GetBytes("password");
static byte[] m_bDESIV = ASCIIEncoding.ASCII.GetBytes("password");

static char[] hex = "0123456789ABCDEF".ToCharArray();
static char[] munge = "ZXCVASDFQWERPOIU".ToCharArray();

public static string Encode(string text)
{
byte[] data = DesEncrypt(ASCIIEncoding.ASCII.GetBytes(text));
char[] chars = BitConverter.ToString(data).ToCharArray();


ArrayList al = new ArrayList();
for (int i = 0; i < chars.Length; i++)
{
if ((i + 1) % 3 == 0) continue; //BitConverter.ToString(...) returns
data in the format XX-XX-XX -- this skips the dashes.
al.Add(munge[Array.IndexOf(hex, chars)]);
}
return new string((char[])al.ToArray(typeof(char)));
}

public static string Decode(string text)
{
char[] chars = text.ToCharArray();

ArrayList al = new ArrayList();
for (int i = 0; i < chars.Length; i += 2)
{
al.Add((byte)(Array.IndexOf(munge, chars) * 16 +
Array.IndexOf(munge, chars[i + 1])));
}

byte[] decrypted = DesDecrypt((byte[])al.ToArray(typeof(byte)));
return ASCIIEncoding.ASCII.GetString(decrypted,0,decrypted.Length);
}

static byte[] DesEncrypt(byte[] data)
{
MemoryStream ms = new MemoryStream(4096);


DES des = new DESCryptoServiceProvider() ;


CryptoStream encStream = new CryptoStream(ms,
des.CreateEncryptor(m_bDESKey, m_bDESIV),
CryptoStreamMode.Write);


encStream.Write(data,0,data.Length);
encStream.FlushFinalBlock();


//calculate the length of the encrypted data
byte[] bResult = new byte[ms.Position];
ms.Position = 0;
ms.Read(bResult, 0, bResult.Length) ;


encStream.Close();
return bResult;
}


static byte[] DesDecrypt ( byte[] data )
{
MemoryStream ms = new MemoryStream(data.Length);


DES des = new DESCryptoServiceProvider() ;


CryptoStream encStream = new CryptoStream(ms,
des.CreateDecryptor(m_bDESKey, m_bDESIV),
CryptoStreamMode.Read);


ms.Write(data,0,data.Length);
ms.Position = 0;


string strResult = new StreamReader(encStream).ReadToEnd();


encStream.Close();


return ASCIIEncoding.ASCII.GetBytes(strResult);
}
}

// --

// Alan Samet
// http://www.alansamet.com/
// http://www.htmlwindows.net/
// http://www.usfbs.com/
// http://www.marshwoodwinds.com/
 
This is the modified version that encodes the resultant byte arrays
into strings. It seems to work on the three strings that I've tested it
with, but I make no guarantees on its security or reliability.

The first problem is that it assumes all the characters to be encoded
are in ASCII - using UTF-8 would be a better idea.

Secondly, it converts an arbitrary byte array into text in a slightly
obscure (and inefficient) way - I'd suggest using
Convert.ToBase64String instead.

(Using MemoryStream.ToArray would be a better way of converting the
stream to a byte array too, but that was a problem with the MSDN
version as well...)
 
Those are all excellent (if not crucial) suggestions. I was unaware of
Convert.ToBase64String -- the complement I assume is
Convert.FromBase64String; I'm sure I'll be using those quite a bit. It
was a hurried solution whose goal was to get the results of that sample
code into character data.

To anyone following this thread: the easily remedied caveats with using
Base64 directly in a querystring is the addition of the padding "=" and
possibly the front-slash.

-Alan
 
Back
Top