Thursday, November 23, 2006

Real World Enterprise Application!

Pic-1










Pic-2







I have veiled the brand and company name to keep it anonymous to avoid embarrassment :-)

Tuesday, November 21, 2006

C# class for Hex encoding

Here is the C# code I wrote for handling Hexadecimal encoding/decoding for using with OpenSSL tool. Pls see my earlier post for discussion on OpenSSL quirks.

#region HexUtil class
/// <summary>
/// Utility class for doing Hex encoding/decoding
/// </summary>
public sealed class HexUtil {

/// <summary>
/// Holds the hex characters for a fast lookup
/// </summary>
private static readonly char[] HEX_CHARS = "0123456789ABCDEF".ToCharArray();
//Keep the array sorted for faster search
static HexUtil() {
Array.Sort(HEX_CHARS);
}

/// <summary>
/// No explicit client creation needed/allowed
/// </summary>
private HexUtil() {
}


/// <summary>
/// Creates a byte array from the hexadecimal string. Each two characters are combined
/// to create one byte. First two hexadecimal characters become first byte in returned array.
/// If input hex string contains an odd number of bytes, then last character is dropped to
/// make the returned byte array as even bytes. It raises ArgumentException, if a
/// Non-hexadecimal character is encountered while processing the string.
/// </summary>
/// <param name="hexString">String to convert to byte array. It should contain only
/// Hex chars [0-9 a-f A-F] only, else error will be raised. See description above </param>
/// <returns>byte array, in the same left-to-right order as the hexString</returns>
///
public static byte[] GetBytes(string hexString) {

if( ! IsValidHexCharLength(hexString) ) {
throw new ArgumentException("Invalid hexString size");
}

//check for non hex characters
StringBuilder tempString = new StringBuilder(hexString.Length);
foreach (char c in hexString) {
if (IsHexChar(c)) {
tempString.Append(c);
}
else {
throw new ArgumentException("Non Hexadecimal character '"+c+"' in hexString");
}
}

string verifiedHexString = tempString.ToString();
tempString=null;

//check for valid length. If number of characters is odd in the hex string then
//drop the last character
if ((verifiedHexString.Length % 2) != 0) {
verifiedHexString = verifiedHexString.Substring(0, verifiedHexString.Length-1);
}


//Convert each hex character to byte
//Hex byte length is half of actual ascii byte length
int byteArrayLength = verifiedHexString.Length / 2;
byte[] hexbytes = new byte[byteArrayLength];
string tmp_substring = null;
try {
for (int i = 0; i < hexbytes.Length; i++) {
int charIndex = i * 2;
tmp_substring = verifiedHexString.Substring(charIndex, 2);
hexbytes[i] = Convert.ToByte(tmp_substring, 16);
}
}
catch (FormatException ex) {
throw new ArgumentException("hexString must be a valid hexadecimal", ex);
}

return hexbytes;
}



/// <summary>
/// Converts the input bytes array to a String assuming each character as a hexadecimal
/// character. Uses .NET Byte.ToString("X2") implementation to achieve the encoding
/// </summary>
/// <param name="bytes">hex encoded bytes to be converted to the string</param>
/// <returns>A string representation of the input bytes assuming Hex encoding</returns>
public static string ToString(byte[] bytes) {

if( bytes == null || bytes.Length == 0) {
throw new ArgumentNullException("bytes");
}

StringBuilder hexString = new StringBuilder();
foreach (byte byt in bytes) {
hexString.Append( byt.ToString("X2") );
}
return hexString.ToString();
}


/// <summary>
/// Determines if given string is in proper hexadecimal string format
/// </summary>
/// <param name="hexString">string to be tested for valid hexadecimal content</param>
/// <returns>true if hexString contains only hex characters and
/// atleast two characters long else false.</returns>
public static bool IsHexString(string hexString) {

bool hexFormat = IsValidHexCharLength(hexString);
if(hexFormat) {
foreach (char ch in hexString) {
if (!IsHexChar(ch)) {
hexFormat = false;
break;
}
}
}
return hexFormat;
}

/// <summary>
/// Checks to see if the input string is not null and atleast two
/// characters long
/// </summary>
/// <param name="hexString">string to be tested</param>
/// <returns>true if hexString is not null and atleast two
/// characters long</returns>
private static bool IsValidHexCharLength(string hexString) {
return ((hexString != null) && (hexString.Length >= 2));
}

/// <summary>
/// Returns true if c is a hexadecimal character [A-F, a-f, 0-9]
/// </summary>
/// <param name="c">Character to test</param>
/// <returns>true if c is a hex char, false if not</returns>
public static bool IsHexChar(Char c) {
c = Char.ToUpper(c);
//look-up the char in HEX_CHARS Array
bool isHexChar = (Array.BinarySearch(HEX_CHARS,c) >= 0);
return isHexChar;
}


/// <summary>
/// This is a utility method to convert any input byte[] to the requiredSize. If the input
/// byte[] is smaller than requiredSize, then a new byte array is created where all lower order
/// places are filled with input byte[] and balance places are filled with 0 (zeros). inputBytes
/// array is truncated if it is larger than requiredSize.
/// </summary>
/// <param name="inputBytes">input byte aray</param>
/// <param name="requiredSize">the size of the byte array to be created</param>
/// <returns>a byte array of requiredSize</returns>
public static byte[] CreateLegalByteArray(byte[] inputBytes, int requiredSize) {

byte[] newBytes = null;
int inputLength = inputBytes.Length;

if(inputLength == requiredSize) {
//nothing to do
newBytes = inputBytes;
}
else {
//create a new Byte array of reuired lenght and fill the content with
//given byte[] starting from 0 index in the new byte[]
newBytes = new byte[requiredSize];
int len= newBytes.Length;
if (len > inputLength) {
len= inputLength;
}
Array.Copy(inputBytes,newBytes,len); //note: balance is filled with 0 (zero)
}
return newBytes;
}
}

#endregion

Friday, November 17, 2006

Sight...

Saw a dumbbell formed lady just emerging out of a local gym sporting a T-Shirt proclaiming... "Misson Impossible" !

Tuesday, November 14, 2006

Recipe for inter-operating a C# Symmetric Encryption code with OpenSSL

Interoperability is not a difficult thing to achieve. Yet, it is not an easy thing to get either- predominantly because the relevant information are widely fragmented and even Google fails to compact all of them together- leaving you rummaging through a pile of web pages to fish out really useful information from them. I am posting this for my own help- may be in future I will need to come back here to look at this again to see what I did!

Problem # 1: Quirks of Hex key in OpenSSL

I needed to write some C# code which will take in a plain text file and run some Symmetric Encryption routine over them using a given Initialization Vector (IV) and a Secret Key (SK). The output will be some encrypted binary data which should be decoded by the OpenSSL tool. Basically, I wanted following OpenSSL command line to work for me always:

$openssl enc [-aes-128-cbc] -in <CipherData.bin> -out <ClearData.txt> -d -K <SomeSecretKey> -iv <SomeIV>

Here <CipherData.bin> is the encrypted file generated by C#/.NET crypto routine. My aim is to support these algorithms: AES, 3DES, RC2 and DES and at least support following chaining modes: CBC, ECB and CFB.

With -–K (and -iv) option, OpenSSL expects only Hexadecimal secret key (and IV) string whose valid size differ for different algorithms employed. The input hex string is converted into a byte array and used as SK (and IV). The interesting part is that OpenSSL and .NET crypto behave differently if you do not supply a valid length hex stream against these data. While, OpenSSL intelligently (and silently) pads the byte array with trailing 0s to make up for the shortfall in “legal” size or truncate it if the same goes beyond the adequate size, the C#/.NET crypto code dies with an exception, leaving you puzzled- what went wrong? Sometimes, to baffle us more, a secret key which had worked in C#/.Net seems to give you "“bad crypto"” in OpenSSL and vice versa.

The crux is how you encode (and decode) a Hex string into byte[] for SK and IV. Basically the point to remember is that a simple Hex text like "“CAFEBABE"” is 8 ASCII character (8 bytes array) but, becomes 4 bytes array when converted to Hex encoding. I have a sample HexUtil C# class which illustrates these things... wait for next post.

Problem # 2: Line breaks in base64 encoding

By default (-a or -base64 switch) OpenSSL inserts/expects a line break (new line character) after every 64th character printed in the encoded/decoded stream. But C#/.NET Libraries v1.1 does not insert a line break automatically in the generated base64 encoded string. Hence, there is some incompatibility between OpenSSL and C# Base64 converter. I have read that in .NET v2.0, Microsoft has added an additional API to insert line breaks in the generated Base64 strings [add link ?]. Meanwhile, I figured out that there is a command line switch in OpenSSL to disable the default line break behavior in the tool. I used following OpenSSL command to successfully decode the Base64 texts generated by C# code:

$openssl enc -a -A -d -in <B64EncryptedData.txt> -out <B64EncryptedData.txt.out>

Note the extra -A switch in the command line!