source: trunk/CrypPlugins/NativeCryptography/NativeCryptography.cpp @ 2028

Last change on this file since 2028 was 2028, checked in by Sven Rech, 11 years ago

added encrypt functionality to NativeCryptography

File size: 9.5 KB
Line 
1// This is the main DLL file.
2
3#include "NativeCryptography.h"
4#include <stdlib.h>
5#include <string.h>
6
7namespace NativeCryptography {
8
9        /* Fast way to xor an AES block */
10        void Crypto::xorBlockAES(int *t1, int *t2)
11        {
12                t1[0] ^= t2[0];
13                t1[1] ^= t2[1];
14                t1[2] ^= t2[2];
15                t1[3] ^= t2[3];
16        }
17
18        /* Fast way to xor an DES block */
19        void Crypto::xorBlockDES(int *t1, int *t2)
20        {
21                t1[0] ^= t2[0];
22                t1[1] ^= t2[1];
23        }
24
25        void Crypto::encrypt(unsigned char* in, unsigned char* out, const cryptMethod method, AES_KEY* aeskey, DES_key_schedule* deskey)
26        {
27                if (method == cryptMethod::methodAES)
28                        AES_encrypt(in, out, aeskey);
29                else
30                        DES_ecb_encrypt((const_DES_cblock*)in, (const_DES_cblock*)out, deskey, DES_ENCRYPT);
31        }
32
33        void Crypto::decrypt(unsigned char* in, unsigned char* out, const cryptMethod method, AES_KEY* aeskey, DES_key_schedule* deskey)
34        {
35                if (method == cryptMethod::methodAES)
36                        AES_decrypt(in, out, aeskey);
37                else
38                        DES_ecb_encrypt((const_DES_cblock*)in, (const_DES_cblock*)out, deskey, DES_DECRYPT);
39        }
40
41
42        void Crypto::xorblock(unsigned char* t1, unsigned char* t2, const cryptMethod method) {
43                if (method == cryptMethod::methodAES)
44                        xorBlockAES((int*)t1, (int*)t2);
45                else
46                        xorBlockDES((int*)t1, (int*)t2); 
47        }
48
49        array<unsigned char>^ Crypto::decryptAESorDES(array<unsigned char>^ Input, array<unsigned char>^ Key, array<unsigned char>^ IV, const int bits, const int length, const int mode, const int blockSize, const cryptMethod method)
50        {
51                int numBlocks = length / blockSize;
52                if (length % blockSize != 0)
53                        numBlocks++;
54
55                bool noIV = false;
56
57                if (IV == nullptr)
58                {
59                        noIV = true;
60                        if (blockSize == 8)
61                                IV = zeroIV8;
62                        else if (blockSize == 16)
63                                IV = zeroIV16;
64                        else
65                                return nullptr;
66                }
67
68                pin_ptr<unsigned char> input = &Input[0];
69                pin_ptr<unsigned char> key = &Key[0];
70                pin_ptr<unsigned char> iv = &IV[0];
71
72                array<unsigned char>^ output = gcnew array<unsigned char>(length);
73                pin_ptr<unsigned char> outp = &output[0];
74
75                AES_KEY aeskey;
76                DES_key_schedule deskey;
77                if (mode == 2)  //CFB
78                {                       
79                        unsigned char block[16];        //16 is enough for AES and DES
80                        unsigned char shiftregister[16];
81                        //works only for little endian architectures:
82                        if (blockSize == 8)
83                        {
84                                *((unsigned int*)shiftregister) = *((unsigned int*)&iv[1]);
85                                *((unsigned int*)&shiftregister[4]) = (*((unsigned int*)&iv[4]) >> 8) | ((unsigned int)(input[0]) << 24);
86                        }
87                        else if (blockSize == 16)
88                        {
89                                *((unsigned int*)shiftregister) = *((unsigned int*)&iv[1]);
90                                *((unsigned int*)&shiftregister[4]) = (*((unsigned int*)&iv[4]) >> 8) | ((unsigned int)iv[8] << 24);
91                                *((unsigned int*)&shiftregister[8]) = (*((unsigned int*)&iv[8]) >> 8) | ((unsigned int)iv[12] << 24);
92                                *((unsigned int*)&shiftregister[12]) = (*((unsigned int*)&iv[12]) >> 8) | ((unsigned int)input[0] << 24);
93                        }
94                        else
95                                return nullptr;
96                       
97                        if (method == cryptMethod::methodAES)
98                                AES_set_encrypt_key(key, bits, &aeskey);
99                        else
100                                DES_set_key_unchecked((const_DES_cblock*)key, &deskey);
101
102                        encrypt(iv, block, method, &aeskey, &deskey);
103                        unsigned char leftmost = block[0];
104                        outp[0] = leftmost ^ input[0];
105
106                        for (int i = 1; i < length; i++)
107                        {
108                                encrypt(shiftregister, block, method, &aeskey, &deskey);
109                                leftmost = block[0];
110                                outp[i] = leftmost ^ input[i];
111                               
112                                //shift input[i] in register:
113                                if (blockSize == 8)
114                                {
115                                        *((unsigned int*)shiftregister) = *((unsigned int*)&shiftregister[1]);
116                                        *((unsigned int*)&shiftregister[4]) = (*((unsigned int*)&shiftregister[4]) >> 8) | ((unsigned int)input[i] << 24);
117                                }
118                                else if (blockSize == 16)
119                                {
120                                        *((unsigned int*)shiftregister) = *((unsigned int*)&shiftregister[1]);
121                                        *((unsigned int*)&shiftregister[4]) = (*((unsigned int*)&shiftregister[4]) >> 8) | ((unsigned int)shiftregister[8] << 24);
122                                        *((unsigned int*)&shiftregister[8]) = (*((unsigned int*)&shiftregister[8]) >> 8) | ((unsigned int)shiftregister[12] << 24);
123                                        *((unsigned int*)&shiftregister[12]) = (*((unsigned int*)&shiftregister[12]) >> 8) | ((unsigned int)input[i] << 24);
124                                }
125                        }
126                }
127                else    //CBC or ECB
128                {
129                        if (method == cryptMethod::methodAES)
130                                AES_set_decrypt_key(key, bits, &aeskey);
131                        else
132                                DES_set_key_unchecked((const_DES_cblock*)key, &deskey);
133
134                        decrypt(input, outp, method, &aeskey, &deskey);                         
135                        if (mode == 1 && !noIV)         //CBC
136                                xorblock(outp, iv, method);     
137                        for (int c = 1; c < numBlocks; c++)
138                        {
139                                decrypt(input+c*blockSize, outp+c*blockSize, method, &aeskey, &deskey);
140                                if (mode == 1)          //CBC
141                                        xorblock(outp+c*blockSize, input+(c-1)*blockSize, method);                             
142                        }
143                }
144
145                return output;
146        }
147
148        array<unsigned char>^ Crypto::encryptAESorDES(array<unsigned char>^ Input, array<unsigned char>^ Key, array<unsigned char>^ IV, const int bits, const int length, const int mode, const int blockSize, const cryptMethod method)
149        {
150                int numBlocks = length / blockSize;
151                if (length % blockSize != 0)
152                        numBlocks++;
153
154                bool noIV = false;
155
156                if (IV == nullptr)
157                {
158                        noIV = true;
159                        if (blockSize == 8)
160                                IV = zeroIV8;
161                        else if (blockSize == 16)
162                                IV = zeroIV16;
163                        else
164                                return nullptr;
165                }
166
167                pin_ptr<unsigned char> input = &Input[0];
168                pin_ptr<unsigned char> key = &Key[0];
169                pin_ptr<unsigned char> iv = &IV[0];
170
171                array<unsigned char>^ output = gcnew array<unsigned char>(length);
172                pin_ptr<unsigned char> outp = &output[0];
173
174                AES_KEY aeskey;
175                DES_key_schedule deskey;
176                if (mode == 2)  //CFB
177                {                       
178                        unsigned char block[16];        //16 is enough for AES and DES
179                        unsigned char shiftregister[16];
180                        //works only for little endian architectures:
181                        if (blockSize == 8)
182                        {
183                                *((unsigned int*)shiftregister) = *((unsigned int*)&iv[1]);
184                                *((unsigned int*)&shiftregister[4]) = (*((unsigned int*)&iv[4]) >> 8) | ((unsigned int)(input[0]) << 24);
185                        }
186                        else if (blockSize == 16)
187                        {
188                                *((unsigned int*)shiftregister) = *((unsigned int*)&iv[1]);
189                                *((unsigned int*)&shiftregister[4]) = (*((unsigned int*)&iv[4]) >> 8) | ((unsigned int)iv[8] << 24);
190                                *((unsigned int*)&shiftregister[8]) = (*((unsigned int*)&iv[8]) >> 8) | ((unsigned int)iv[12] << 24);
191                                *((unsigned int*)&shiftregister[12]) = (*((unsigned int*)&iv[12]) >> 8) | ((unsigned int)input[0] << 24);
192                        }
193                        else
194                                return nullptr;
195                       
196                        if (method == cryptMethod::methodAES)
197                                AES_set_encrypt_key(key, bits, &aeskey);
198                        else
199                                DES_set_key_unchecked((const_DES_cblock*)key, &deskey);
200
201                        encrypt(iv, block, method, &aeskey, &deskey);
202                        unsigned char leftmost = block[0];
203                        outp[0] = leftmost ^ input[0];
204
205                        for (int i = 1; i < length; i++)
206                        {
207                                encrypt(shiftregister, block, method, &aeskey, &deskey);
208                                leftmost = block[0];
209                                outp[i] = leftmost ^ input[i];
210                               
211                                //shift input[i] in register:
212                                if (blockSize == 8)
213                                {
214                                        *((unsigned int*)shiftregister) = *((unsigned int*)&shiftregister[1]);
215                                        *((unsigned int*)&shiftregister[4]) = (*((unsigned int*)&shiftregister[4]) >> 8) | ((unsigned int)input[i] << 24);
216                                }
217                                else if (blockSize == 16)
218                                {
219                                        *((unsigned int*)shiftregister) = *((unsigned int*)&shiftregister[1]);
220                                        *((unsigned int*)&shiftregister[4]) = (*((unsigned int*)&shiftregister[4]) >> 8) | ((unsigned int)shiftregister[8] << 24);
221                                        *((unsigned int*)&shiftregister[8]) = (*((unsigned int*)&shiftregister[8]) >> 8) | ((unsigned int)shiftregister[12] << 24);
222                                        *((unsigned int*)&shiftregister[12]) = (*((unsigned int*)&shiftregister[12]) >> 8) | ((unsigned int)input[i] << 24);
223                                }
224                        }
225                }
226                else    //CBC or ECB
227                {
228                        if (method == cryptMethod::methodAES)
229                                AES_set_encrypt_key(key, bits, &aeskey);
230                        else
231                                DES_set_key_unchecked((const_DES_cblock*)key, &deskey);
232
233                        encrypt(input, outp, method, &aeskey, &deskey);                         
234                        if (mode == 1 && !noIV)         //CBC
235                                xorblock(outp, iv, method);     
236                        for (int c = 1; c < numBlocks; c++)
237                        {
238                                encrypt(input+c*blockSize, outp+c*blockSize, method, &aeskey, &deskey);
239                                if (mode == 1)          //CBC
240                                        xorblock(outp+c*blockSize, input+(c-1)*blockSize, method);                             
241                        }
242                }
243
244                return output;
245        }
246
247        double *xlogx = 0;
248
249        void prepareEntropy(int size)
250    {
251                if (xlogx != 0)
252                        free(xlogx);
253        xlogx = (double*)malloc((size + 1)*sizeof(double));
254        //precomputations for fast entropy calculation 
255        xlogx[0] = 0.0;
256        for (int i = 1; i <= size; i++)
257                        xlogx[i] = -1.0 * i * Math::Log(i / (double)size) / Math::Log(2.0);
258    }
259
260
261        double Crypto::calculateEntropy(array<unsigned char>^ text, int bytesToUse)
262        {
263        if (bytesToUse > text->Length)
264            bytesToUse = text->Length;
265                static int lastUsedSize = -1;
266
267        if (lastUsedSize != bytesToUse)
268        {
269            try
270            {
271                prepareMutex->WaitOne();
272                if (lastUsedSize != bytesToUse)
273                {
274                    prepareEntropy(bytesToUse);
275                    lastUsedSize = bytesToUse;
276                }
277            }
278            finally
279            {
280                prepareMutex->ReleaseMutex();
281            }
282        }
283
284                pin_ptr<unsigned char> t = &text[0];
285
286        int n[256];
287                memset(n,0,sizeof(n));
288        //count all ASCII symbols
289        for (int counter = 0; counter < bytesToUse; counter++)
290        {
291            n[t[counter]]++;
292        }
293
294        double entropy = 0;
295        //calculate probabilities and sum entropy
296        for (short i = 0; i < 256; i++)                 
297            entropy += xlogx[n[i]];
298
299        return entropy / (double)bytesToUse;
300        }
301
302}
Note: See TracBrowser for help on using the repository browser.