Ciphers and Cryptographic Hashes

The System.Security.Cryptography namespace supports a variety of cryptographic services to encrypt and decrypt data, create one-way hashes, authenticate messages and generate random numbers.

One way hashes, which can take variable length data and convert it into fixed length binary sequences, are useful for verifying passwords and generating digital signatures. I like to use a standard 512 bit hashing algorithm called SHA-512 to convert a password or pass phrase into a sequence to use for generating ciphers. For example, a string could be converted into a hashed byte array as follows:

using System.Security.Cryptography;
…..

string passPhrase = “A secret phrase”;

// convert the passPhrase string into a byte array
ASCIIEncoding AE = new ASCIIEncoding();
byte[] passBuff = AE.GetBytes(passPhrase);

SHA512Managed hashVal = new SHA512Managed();
byte[] passHash = hashVal.ComputeHash(passBuff);

Here is an example of using a an array of bytes (for example produced by running SHA-512 on on a plain text string converted into a byte array), to perform an XOR based cipher. .

// XcryptBuf() – xor based poly-alphabetic substitution cipher layer
private void XcryptBuf(byte[] targetBuf, byte[] keyBuf)
{
int i, j = 0;
int newChar;
int kLen = keyBuf.Length;
int targetLen = targetBuf.Length;

    for (i = 0; i < targetLen; i++)
{
if (j == kLen) j = 0;
newChar = (targetBuf[i] ^ keyBuf[j]);
targetBuf[i] = (byte)newChar;
j++;
}
}

After this method is called targetBuf will be encrypted with a reversible polyalphabetic XOR cipher. Running the same method with the same arguments again would unencrypt it.

Other examples

This example is a simple transposition cipher which uses the same format (target array and key array arguments) to scramble the characters in a  buffer:

// ScrambleBuf()
void ScrambleBuf(byte[] targetBuf, byte[] keyBuf)
{
int i, j = 0, targetLen = targetBuf.Length;
int oldChar, newPos;
int kLen = keyBuf.Length;

    for (i = 0; i < targetLen; i++)
{
// swap char with position determined by position and keyBuf char
oldChar = targetBuf[i];
if (j == kLen) j = 0;
if (i % 2 == 0) newPos = (keyBuf[j] + i) % targetLen;
else newPos = Math.Abs(keyBuf[j] – i) % targetLen;
targetBuf[i] = targetBuf[newPos];
targetBuf[newPos] = (byte)oldChar;
j++;
}
}

A corresponding unscramble method to decipher a scrambled byte array could look like this:

// UnscrambleBuf() – reverse of scrambleBuf()
void UnscrambleBuf(byte[] targetBuf, byte[] keyBuf)
{
int i, j, targetLen = targetBuf.Length;
int oldChar, newPos;
int kLen = keyBuf.Length;

    if (kLen > targetLen) j = targetLen – 1;
else j = (targetLen – 1) % kLen;

    for (i = targetLen – 1; i >= 0; i–)
{
// unswap char with position determined by position and keyBuf char
oldChar = targetBuf[i];
if (i % 2 == 0) newPos = (keyBuf[j] + i) % targetLen;
else newPos = Math.Abs(keyBuf[j] – i) % targetLen;
targetBuf[i] = targetBuf[newPos];
targetBuf[newPos] = (byte)oldChar;
if (j == 0) j = kLen – 1;
else j–;
if (i == 0) break;
}
}

Cipher Block Chaining

Here are a set of polyalphabetic cipher methods which use a simple form of cipher block chaining (CBC) to add and subtract characters in a key from a target buffer, and use a hash of the previous block to encrypt the next block:

private void CipherBuf(byte[] targetBuf, byte[] keyBuf)
{
int i = 0, j = 0, kLen = keyBuf.Length;
int newChar, oldChar;
byte[] blockKey = keyBuf;
byte[] newKeyBuf = new byte[keyBuf.Length];

    for (i = 0; i < targetBuf.Length; i++)
{
if (j == kLen)
{
j = 0;
blockKey = GetSHA512(newKeyBuf);
}
oldChar = targetBuf[i];
newKeyBuf[j] = targetBuf[i];
if (i % 2 == 0) newChar = oldChar + blockKey[j];
else newChar = oldChar – blockKey[j];
targetBuf[i] = (byte)newChar;
j++;
}
}

private void DecipherBuf(byte[] targetBuf, byte[] keyBuf)
{
int i = 0, j = 0, kLen = keyBuf.Length;
int newChar, oldChar;
byte[] blockKey = keyBuf;
byte[] newKeyBuf = new byte[keyBuf.Length];

    for (i = 0; i < targetBuf.Length; i++)
{
if (j == kLen)
{
j = 0;
blockKey = GetSHA512(newKeyBuf);
}
oldChar = targetBuf[i];
if (i % 2 == 0) newChar = oldChar – blockKey[j];
else newChar = oldChar + blockKey[j];
targetBuf[i] = (byte)newChar;
newKeyBuf[j] = targetBuf[i];
j++;
}
}

private byte[] GetSHA512(byte[] plainBuf)
{
SHA512Managed hashVal = new SHA512Managed();
return hashVal.ComputeHash(plainBuf);
}

There are of course more sophisticated, standardized (and hence mathematically verified) cipher algorithms readily available for production use, but it can be fun to write your own ciphering routines, and layer methods like these together to create home made cipher applications.

Advertisements
This entry was posted in Cryptography. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s