📄 aeslib.c
字号:
/* ------------------------------------------------------------------------- Copyright (c) 2002, Markus Lagler <markus.lagler@trivadis.com> Copyright (c) 2002, Tim Tassonis <timtas@dplanet.ch> All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. DISCLAIMER This software is provided 'as is' with no explcit or implied warranties in respect of any properties, including, but not limited to, correctness and fitness for purpose. -------------------------------------------------------------------------*/#include <stdio.h>#include <stdlib.h>#include <memory.h>#include "aes.h"#include "aeslib.h"#ifdef HAVE_DEV_URANDOMvoid fillrand(char *buf, const int len){ FILE * frand; frand = fopen("/dev/urandom","r"); fread(buf,1,len,frand); fclose(frand); return;}#endif#ifdef WINDOWS/* A Pseudo Random Number Generator (PRNG) used for the Initialisation Vector. The PRNG is George Marsaglia's Multiply-With-Carry (MWC) PRNG that concatenates two 16-bit MWC generators: x(n)=36969 * x(n-1) + carry mod 2^16 y(n)=18000 * y(n-1) + carry mod 2^16 to produce a combined PRNG with a period of about 2^60. The Pentium cycle counter is used to initialise it. This is crude but the IV does not really need to be secret.*/void cycles(unsigned long *rtn){ __asm /* read the Pentium Time Stamp Counter */ { _emit 0x0f /* complete pending operations */ _emit 0xa2 _emit 0x0f /* read time stamp counter */ _emit 0x31 mov ebx,rtn mov [ebx],eax mov [ebx+4],edx _emit 0x0f /* complete pending operations */ _emit 0xa2 }}#define RAND(a,b) (((a = 36969 * (a & 65535) + (a >> 16)) << 16) + \ (b = 18000 * (b & 65535) + (b >> 16)) )void fillrand(char *buf, const int len){ static unsigned long a[2], mt = 1, count = 4; static char r[4]; int i; if(mt) { mt = 0; cycles(a); } for(i = 0; i < len; ++i) { if(count == 4) { *(unsigned long*)r = RAND(a[0], a[1]); count = 0; } buf[i] = r[count++]; }}#endifint encbuf(char* in, int in_len, char* out, aes_ctx *ctx, int* out_len){ char buf[BLOCK_LEN], dbuf[2 * BLOCK_LEN]; unsigned long i, l, rlen; char *pos_out, *pos_in; fillrand(dbuf, BLOCK_LEN); // set a random IV rlen = in_len; pos_out = out; pos_in = in; if(rlen < BLOCK_LEN) // file length of less than one block { memcpy(dbuf + BLOCK_LEN, in, rlen); l = rlen; for(i = 0; i < l; ++i) // xor file bytes with IV bytes dbuf[i + BLOCK_LEN] ^= dbuf[i]; aes_enc_blk(dbuf, dbuf, ctx); // encrypt lower half of buffer // encrypt bytes from position l to position l + BLOCK_LEN - the // file bytes plus a second encryption of some of the IV bytes aes_enc_blk(dbuf + l, dbuf + l, ctx); l += BLOCK_LEN; // write the encrypted bytes memcpy(out, dbuf, l); *out_len = l; } else { aes_enc_blk(dbuf, buf, ctx); // encrypt and write IV block memcpy(pos_out, buf, BLOCK_LEN); pos_out += BLOCK_LEN; *out_len = BLOCK_LEN; while(rlen) { // read a block and reduce remaining memcpy(buf, pos_in, BLOCK_LEN); pos_in += BLOCK_LEN; l = BLOCK_LEN; rlen -= l; for(i = 0; i < BLOCK_LEN; ++i) // do CBC chaining prior to buf[i] ^= dbuf[i]; // encryption aes_enc_blk(buf, dbuf, ctx); if(rlen < BLOCK_LEN) // if only a part block remains { memcpy(dbuf+BLOCK_LEN, pos_in, rlen); // encrypt from position rlen to rlen + BLOCK_LEN - the last // file bytes plus a part of the last encrypted block - this // is called 'ciphertext stealing' for(i = 0; i < rlen; ++i) // do CBC chaining prior to dbuf[i + BLOCK_LEN] ^= dbuf[i]; // encryption aes_enc_blk(dbuf + rlen, dbuf + rlen, ctx); l = rlen + BLOCK_LEN; // set final buffer length rlen = 0; } memcpy(pos_out, dbuf, l); pos_out += l; *out_len += l; } } return 0;}int decbuf(char* in, int in_len, char* out, aes_ctx *ctx, int *out_len){ char buf1[BLOCK_LEN], buf2[BLOCK_LEN], dbuf[2 * BLOCK_LEN]; char *b1, *b2, *bt; unsigned long i, l, rlen; char *pos_in, *pos_out; rlen = in_len; pos_in = in; pos_out = out; if(rlen < 2 * BLOCK_LEN) // original length of less than one block { memcpy(dbuf, in, rlen); l = rlen; l -= BLOCK_LEN; // original file length // decrypt from position l to position l + BLOCK_LEN aes_dec_blk(dbuf + l, dbuf + l, ctx); aes_dec_blk(dbuf, dbuf, ctx); // decrypt lower half of buffer for(i = 0; i < l; ++i) // remove IV xor dbuf[i] ^= dbuf[i + BLOCK_LEN]; memcpy(out, dbuf, l); *out_len = l; } else { // we need two input buffers because we have to keep the previous // ciphertext block - the pointers b1 and b2 are swapped once per // loop so that b2 points to new ciphertext block and b1 to the // last ciphertext block rlen -= BLOCK_LEN; b1 = buf1; b2 = buf2; memcpy(b1, pos_in, BLOCK_LEN); pos_in += BLOCK_LEN; *out_len = 0; aes_dec_blk(b1, b1, ctx); // and decrypt it while (rlen) { // read a block and reduce remaining if (rlen < BLOCK_LEN) { memcpy(b2, pos_in, rlen); l = rlen; } else { memcpy(b2, pos_in, BLOCK_LEN); pos_in += BLOCK_LEN; l = BLOCK_LEN; } rlen -= l; if(rlen < BLOCK_LEN) // if only a part block remains { for(i = 0; i < BLOCK_LEN; ++i) // move bytes from last but dbuf[i] = b2[i]; // one block into lower half of dbuf if (rlen) { memcpy(dbuf + BLOCK_LEN, pos_in, rlen); } // decrypt from position rlen to rlen + BLOCK_LEN - that is // the file bytes plus a part of the last but one encrypted // block aes_dec_blk(dbuf + rlen, dbuf + rlen, ctx); for(i = 0; i < rlen; ++i) // unchain the CBC using the dbuf[i + BLOCK_LEN] ^= dbuf[i]; // last ciphertext block // set output buffer and correct final length b2 = dbuf; l = rlen + BLOCK_LEN; rlen = 0; } aes_dec_blk(b2, dbuf, ctx); // decrypt the input buffer for(i = 0; i < BLOCK_LEN; ++i) // unchain the CBC using the dbuf[i] ^= b1[i]; // last ciphertext block memcpy(pos_out, dbuf, l); pos_out += l; *out_len += l; bt = b1, b1 = b2, b2 = bt; // swap the input buffer pointers } } return 0;}char* aes_enc(char *in, int in_len, char *key, int key_len, int* out_len){ aes_ctx ctx[1]; char *out; char local_key[FIX_KEY_LEN]; // always use key of 32 byte length aes_fret ret; out = (char*) malloc(in_len + 2*BLOCK_LEN); // 1 BLOCK IV and BLOCK at the end memset(ctx, 0x0, sizeof(ctx)); // key run up if (key_len < FIX_KEY_LEN) { memset(local_key, 0x12, FIX_KEY_LEN); // if the entred key is shorter as the desired key length memcpy(local_key, key, key_len); // add simple padding (fill up with 0x12) } else { memcpy(local_key, key, FIX_KEY_LEN); } ret = aes_enc_key(local_key, FIX_KEY_LEN, ctx); if (ret != aes_good) return NULL; encbuf(in, in_len, out, ctx, out_len); return out;}char* aes_dec(char *in, int in_len, char *key, int key_len, int* out_len){ aes_ctx ctx[1]; char *out; char local_key[FIX_KEY_LEN]; // always use key of 32 byte length aes_fret ret; out = (char*) malloc(in_len); memset(ctx, 0x0, sizeof(ctx)); // key run up if (key_len < FIX_KEY_LEN) { memset(local_key, 0x12, FIX_KEY_LEN); // if the entred key is shorter as the desired key length memcpy(local_key, key, key_len); // add simple padding (fill up with 0x12) } else { memcpy(local_key, key, FIX_KEY_LEN); } ret = aes_dec_key(local_key, FIX_KEY_LEN, ctx); if (ret != aes_good) return NULL; decbuf(in, in_len, out, ctx, out_len); return out;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -