So I'm struggling a bit with that. I am trying to create my own AES 128 library for use with one of my programs. The library checks and works in C ++ (well, for the encryption function .. I have not implemented others yet). The encrypt function looks like this:
NEW CODE
void Aes128Class::EncryptBlock(BYTE* outBlock, const BYTE* inBlock, const BYTE* cipherBlock) { BYTE temp[16] = {0x00}; Galois::XorBlock(temp, inBlock); Galois::XorBlock(temp, cipherBlock); BYTE expandedKey[176] = {0x00}; memcpy(expandedKey, Key, 16); Galois::expand_key(expandedKey); Galois::XorBlock(temp, expandedKey); for(int i=16; i<160; i+=16) { Galois::DoRound(temp, &expandedKey[i]); } Galois::SubBytes(temp); Galois::ShiftRows(temp); Galois::XorBlock(temp, &expandedKey[160]); memcpy(outBlock, temp, 16); } void Aes128Class::EncryptData(BYTE* outBlock, size_t& outlen, const BYTE* inBlock, size_t length) { float blockSize = (float)(length/16); blockSize = ceilf(blockSize); int newLength = (int)(blockSize*16); BYTE* temp = (BYTE*)malloc(newLength); BYTE* padd = (BYTE*)malloc(newLength); memset(temp, 0, newLength); memcpy(padd, inBlock, length); EncryptBlock(temp, padd, IV); for (int i=1; i<blockSize; i++) { EncryptBlock(&temp[i*16], &padd[i*16], &temp[(i-1)*16]); } outlen = newLength; memcpy(outBlock, temp, newLength); }
The idea is that if plainText not in a 16-byte block increment, I force it to be. Thus, it makes an array of bytes with a variable size. It works in my C++ test, but when I call it in C# , I get a few different errors ... It takes a minute to describe.
[DllImport("CppAes128.dll", CallingConvention = CallingConvention.ThisCall, EntryPoint = " ?EncryptData@Aes128Class @@ QAEXPAEAAIPBEI@Z ")] static extern void EncryptData(IntPtr pClass, ref IntPtr outblock, [Out]int OutLength, byte[] inBlock, int length);
When I call this, I get valid pointers to both array and outlength. The way it looks right now causes an access violation, but I can get this structure to work if I change [Out]int OutLength to ref IntPtr . Interestingly, if I do ref int or ref uint , it still "works." So if I do this, I will try to read intptr and then I will get an access violation. I am compiling this as an x86 project in .NET 4.0 (since I read somewhere that 3.5 had some access errors ...)
Here is what I tried in C# . This got a little distorted as I played with him for hours (sorry):
public byte[] EncryptData(byte[] plainText, int length) { byte[] enc = null; int len = 0; IntPtr pArray = IntPtr.Zero; EncryptData(theClass, ref pArray, len, plainText, length); Console.WriteLine(len); //enc = new byte[len]; //Marshal.Copy(pArray, enc, 0, len); //Marshal.Release(pArray); //try //{ // int elementSize = Marshal.SizeOf(typeof(IntPtr)); // //IntPtr unmanagedArray = Marshal.AllocHGlobal(10 * elementSize); // Console.WriteLine("Reading unmanaged memory:"); // // Print the 10 elements of the C-style unmanagedArray // for (int i = 0; i < 10; i++) // { // Console.WriteLine("{0:X2}:", Marshal.ReadByte(pArray, i)); // } // Marshal.FreeHGlobal(pArray); //} //catch (Exception ex) //{ // Console.WriteLine("{0}\n{1}", ex.Source, ex.Message); // Console.WriteLine("Win32({0})", Marshal.GetLastWin32Error()); //} //Marshal.Release(pArray); return enc; }
The only time this worked was when I simply created an array of static size and did not use a ref or marshal copy or anything else. I think my signature was something like this
static extern void EncryptData(IntPtr pClass, byte[] outBlock, byte[] inBlock, int length);
It almost worked, but the problem was that when I did the foreach on this array , it was always the size I set. Uncomfortable to say.
So what am I doing wrong? how can i make this work? I am so upset about this. thank you
Oh and FYI, I can no longer depend on cryptlib . I am trying to recompile another project that uses cryptlib as a static library and does not share it, which causes some problems with my compiled parameters and too big a problem for the change.
EDITED show more code
These are the tests that I use. I found a webpage that showed a bunch of tests, so I am implementing this.
void VerifyEncrypt16(const BYTE* expected, const BYTE* key, const BYTE* iv, const BYTE* plainText) { BYTE actual[16] = {0x00}; Aes128Class aes; aes.SetKey(key, 16); aes.SetIV(iv, 16); size_t len = 0; aes.EncryptData(actual, len, plainText, 16); _ASSERT(CompareTwoArrays(expected, actual)); } void VerifyEncrypt16String(const char* expected, const char* key, const char* iv, const char* plainText) { BYTE e[16]; BYTE k[16]; BYTE i[16]; BYTE p[16]; ByteUtil::StringToHex(expected, e); ByteUtil::StringToHex(key, k); ByteUtil::StringToHex(iv, i); ByteUtil::StringToHex(plainText, p); VerifyEncrypt16(e, k, i, p); } void CheckEncrypt16(void) { _RPT0(_CRT_WARN, "Checking Encryption of a 16 byte number IV set to 0\n"); //AESVS GFSbox test data for CBC VerifyEncrypt16String("0336763e966d92595a567cc9ce537f5e","00000000000000000000000000000000","00000000000000000000000000000000","f34481ec3cc627bacd5dc3fb08f273e6"); VerifyEncrypt16String("a9a1631bf4996954ebc093957b234589","00000000000000000000000000000000","00000000000000000000000000000000","9798c4640bad75c7c3227db910174e72"); VerifyEncrypt16String("ff4f8391a6a40ca5b25d23bedd44a597","00000000000000000000000000000000","00000000000000000000000000000000","96ab5c2ff612d9dfaae8c31f30c42168"); VerifyEncrypt16String("dc43be40be0e53712f7e2bf5ca707209","00000000000000000000000000000000","00000000000000000000000000000000","6a118a874519e64e9963798a503f1d35"); VerifyEncrypt16String("92beedab1895a94faa69b632e5cc47ce","00000000000000000000000000000000","00000000000000000000000000000000","cb9fceec81286ca3e989bd979b0cb284"); VerifyEncrypt16String("459264f4798f6a78bacb89c15ed3d601","00000000000000000000000000000000","00000000000000000000000000000000","b26aeb1874e47ca8358ff22378f09144"); VerifyEncrypt16String("08a4e2efec8a8e3312ca7460b9040bbf","00000000000000000000000000000000","00000000000000000000000000000000","58c8e00b2631686d54eab84b91f0aca1"); //AESVS KeySbox test data for CBC VerifyEncrypt16String("6d251e6944b051e04eaa6fb4dbf78465","10a58869d74be5a374cf867cfb473859","00000000000000000000000000000000","00000000000000000000000000000000"); //A TON OF MORE TESTS! etc etc etc VerifyEncrypt16String("5c005e72c1418c44f569f2ea33ba54f3","00000000000000000000000000000000","00000000000000000000000000000000","fffffffffffffffffffffffffffffffe"); VerifyEncrypt16String("3f5b8cc9ea855a0afa7347d23e8d664e","00000000000000000000000000000000","00000000000000000000000000000000","ffffffffffffffffffffffffffffffff"); }