I am using the Dynamic C programming language on a Rabbit microprocessor. I believe Dynamic C is based on ANSI-C89 with some very slight changes. They have an AES encryption library which I am trying to use to encrypt data before I send it to my server (with very little success).
Here's the documentation for the C-based AES functions that I'm using:
AESinitStream
SYNTAX: void AESinitStream(AESstreamState *state, const char *key, const char *init_vector);
DESCRIPTION: Sets up a stream state structure to begin encrypting or decrypting a stream. A particular stream state can only be used for one direction.
PARAMETER1: state - An AESstreamState structure to be initialized
PARAMETER2: key - the 16-byte cipher key, using a NULL pointer will prevent an existing key from being recalculated.
PARAMETER3: init_vector - a 16-byte array representing the initial state of the feedback registers. Both ends of the stream must begin with the same initialization vector and key.
AESencryptStream
SYNTAX: void AESencryptStream(AESstreamState *state, char *data, int count);
DESCRIPTION: Encrypts an array of bytes
PARAMETER1: state - The AESstreamState structure
PARAMETER2: data - an array of bytes that will be encrypted in place.
PARAMETER3: count - size of data array
Here's my C code:
const char key[] = {'\x41', '\x41', '\x37', '\x44',
'\x44', '\x34', '\x30', '\x33',
'\x30', '\x35', '\x39', '\x4e',
'\x36', '\x37', '\x30', '\x38'};
AESstreamState encrypt_state; //built in Dynamic C type
char init_vector[16];
int i;
int bufLength;
sprintf(Buf, "%s", "testabc");
bufLength = strlen(Buf);
for (i = 0; i < 16; i++)
init_vector[i] = rand() % 255;
printf("Key: ");
for (i = 0; i < sizeof(key); i++)
printf("%d ", key[i]);
printf("\n");
AESinitStream(&encrypt_state, key, init_vector); //built in Dynamic C function
AESencryptStream(&encrypt_state, Buf, bufLength); //built in Dynamic C function
printf("Data: ");
for (i = 0; i < strlen(Buf); i++)
printf("%d ", Buf[i]);
printf("\n");
//set first byte to something that lets the server know it's encrypted
//set 2nd through 16th byte to the IV (initialization vector) so every message will be different even if they have the same contents
for (i = bufLength-1; i >= 0; i--)
Buf[i+17] = Buf[i];
Buf[0] = 237; //φ
printf("IV: ");
for (i = 1; i < 17; i++)
{
printf("%d ", init_vector[i-1]);
Buf[i] = init_vector[i-1];
}
printf("\n");
Output:
Key: 65 65 55 68 68 52 48 51 48 53 57 78 54 55 48 56
Data: 249 78 60 83 130 167 37
IV: 74 121 108 165 83 120 36 27 161 192 84 76 105 239 34 214
Here's my C# code:
private string DecryptAES(byte[] cipherText, byte[] IV)
{
byte[] key = {
0x41, 0x41, 0x37, 0x44,
0x44, 0x34, 0x30, 0x33,
0x30, 0x35, 0x39, 0x4e,
0x36, 0x37, 0x30, 0x38
};
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
{
throw new ArgumentNullException("cipherText");
}
else if (IV == null || IV.Length <= 0 || IV.Length != 16)
{
throw new ArgumentNullException("IV");
}
Console.Write("Key: ");
for (int i = 0; i < key.Length; i++)
Console.Write("{0} ", key[i]);
Console.WriteLine();
Console.Write("Data: ");
for (int i = 0; i < cipherText.Length; i++)
Console.Write("{0} ", cipherText[i]);
Console.WriteLine();
Console.Write("IV: ");
for (int i = 0; i < IV.Length; i++)
Console.Write("{0} ", IV[i]);
Console.WriteLine();
// Create an RijndaelManaged object
// with the specified key and IV.
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Mode = CipherMode.CFB;
rijAlg.FeedbackSize = 8;
rijAlg.BlockSize = 128;
rijAlg.Padding = PaddingMode.None;
rijAlg.Key = key;
rijAlg.IV = IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for decryption.
using (System.IO.MemoryStream msDecrypt = new System.IO.MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (System.IO.StreamReader srDecrypt = new System.IO.StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
string plaintext = null;
plaintext = srDecrypt.ReadToEnd();
Console.WriteLine("Decrypted: " + plaintext);
return plaintext;
}
}
}
}
}
Output:
Key: 65 65 55 68 68 52 48 51 48 53 57 78 54 55 48 56
Data: 249 78 60 83 130 167 37
IV: 74 121 108 165 83 120 36 27 161 192 84 76 105 239 34 214
Decrypted: t{^^?d2
As you can see, I'm getting some strange output in my decrypted text. Can anybody point me in the right direction?
I have tried decrypting this using Dynamic C successfully, but if you think the built in Dynamic C AES library is the culprit, what would you recommend?
EDIT: So I decided to encrypt this using C#'s AES libraries and got a different cipher:
private byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
{
throw new ArgumentNullException("plainText");
}
if (Key == null || Key.Length <= 0)
{
throw new ArgumentNullException("Key");
}
if (IV == null || IV.Length <= 0)
{
throw new ArgumentNullException("IV");
}
byte[] encrypted = null;
// Create an RijndaelManaged object
// with the specified key and IV.
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Mode = CipherMode.CFB;
rijAlg.FeedbackSize = 8;
rijAlg.BlockSize = 128;
rijAlg.Padding = PaddingMode.None;
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for encryption.
using (System.IO.MemoryStream msEncrypt = new System.IO.MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (System.IO.StreamWriter swEncrypt = new System.IO.StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
Calling the above function with the same string, key, & IV that I originally used results in the following cipher:
249 (which is correct), 43, 74, 118, 241, 179, 235
I changed the FeedbackSize to 16 and the first two bytes were correct, but it also gave me an error (Length of the data to encrypt is invalid.) and reduced the array size to 6 bytes. I'm clueless.
Here is a snippet of some sample code from Rabbit that uses AESencryptStream (they chose to set the IV to the same value as the key). It appears that I am using this function correctly but please tell me if I am wrong:
const char key[16] = {
'\x06', '\xa9', '\x21', '\x40', '\x36', '\xb8', '\xa1', '\x5b',
'\x51', '\x2e', '\x03', '\xd5', '\x34', '\x12', '\x00', '\x06'
};
char bblock[8192];
AESstreamState ass;
memset(bblock, 'A', sizeof(bblock));
AESinitStream(&ass, key, key);
AESencryptStream(&ass, bblock, sizeof(bblock));
AESinitStream(&ass, key, key);
AESdecryptStream(&ass, bblock, sizeof(bblock));