AES跟Rijndael相比有點(diǎn)小區別,就是使用固定塊(block size)為128bits(16字節)(原Rijndael塊大小更靈活),密鑰長(cháng)度支持128、192或256位。
CBC加解密原理如下圖所示(圖片來(lái)源維基百科,參考文末地址):

CBC加密原理:明文跟向量異或,再用KEY進(jìn)行加密,結果作為下個(gè)BLOCK的初始化向量。解密原理:使用密鑰先對密文解密,解密后再同初始向量異或得到明文。
CBC需要對明文塊大小進(jìn)行Padding(補位),由于前后加密的相關(guān)性,只能實(shí)施串行化動(dòng)作,無(wú)法并行運算。另外,CBC需要參量:密鑰和初始化向量。

CTR加密原理:用密鑰對輸入的計數器加密,然后同明文異或得到密文。解密原理:用密鑰對輸入計數器加密,然后同密文異或得到明文。
CTR不需要Padding,而且采用了流密鑰方式加解密,適合于并行運算,CTR涉及參量:Nounce隨機數、Counter計數器和密鑰。Nounce隨機數和Counter計數器整體可看作計數器,因為只要算法約定好,就可以回避掉串行化運算。
下文實(shí)例使用了第三方開(kāi)源源碼,官方網(wǎng)址:http://www.gladman.me.uk/, 本文測試源碼來(lái)源:http://gladman.plushost.co.uk/oldsite/AES/index.php,測試時(shí),如下源碼文件需加入工程:aes_modes.c、aescrypt.c、aeskey.c、aestab.c。
測試源碼如下:
#include <iostream>#include <string>#include <time.h>#include "aes/aes.h"typedef unsigned char uint8;typedef char int8;typedef unsigned short uint16;typedef short int16;typedef unsigned int uint32;typedef int int32;typedef unsigned __int64 uint64;typedef __int64 int64;/******************************For _LINUXtypedef long long int64;typedef unsigned long long uint64;******************************/using namespace std;//same as function rfc3686_incvoid ctr_inc(unsigned char ctr_buf[16]){ if(!(++(ctr_buf[15]))) if(!(++(ctr_buf[14]))) if(!(++(ctr_buf[13]))) ++(ctr_buf[12]);}//same as function rfc3686_init//4Bytes nounce+8Bytes iv+4Bytes countervoid ctr_init( unsigned char nonce[4], unsigned char iv[8], unsigned char ctr_buf[16]){ memcpy(ctr_buf, nonce, 4); memcpy(ctr_buf + 4, iv, 8); memset(ctr_buf + 12, 0, 4); ctr_inc(ctr_buf);}void print_hex(uint8* buf, uint64 len) { //Print results: for(int i=0;i<len;i++) { printf("%02X",buf[i]); if(15 == i%16) printf("\n"); } printf("\n");}void main() { uint8 key[] = {0x10,0xa5,0x88,0x69,0xd7,0x4b,0xe5,0xa3,0x74,0xcf, 0x86,0x7c,0xfb,0x47,0x38,0x59};//AES::DEFAULT_KEYLENGTH uint8 buf[16];//tmp buffer uint8 msg[] = "HelloWorld!23456"; uint64 fsize=strlen((char*)msg);//message size uint8* DataBuf=new uint8[1024];//Data Buffer //AES with CBC printf("AES with CBC\n"); //Copy data memset(DataBuf,0,1024); strcpy((char*)DataBuf,(char*)msg); uint8* pDataBuf = DataBuf;//tmp pointer uint8 iv1[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00}; uint64 iEncryptTimes = fsize/16+1; uint8 iPaddings = 16-fsize%16;//Padding size uint64 newlen = fsize+iPaddings;//New length //memcpy(DataBuf,iv,16);//Save iv memset(pDataBuf+fsize, iPaddings,iPaddings);//Padding printf("input =\n"); print_hex(DataBuf,newlen); aes_encrypt_ctx en_ctx[1];//Init encrypt //Encrypt for(uint64 i=0;i<iEncryptTimes;i++) { aes_encrypt_key128(key,en_ctx); aes_cbc_encrypt(pDataBuf,buf,16,iv1,en_ctx);//iv has been changed, ctx has been changed!!! memcpy(pDataBuf,buf,16); pDataBuf += 16; } printf("encrypt =\n"); print_hex(DataBuf,newlen); //Decrypt pDataBuf = DataBuf; uint8 iv2[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00}; uint8 buf3[256]={'\0'}; aes_decrypt_ctx de_ctx[1]; aes_decrypt_key128(key,de_ctx); aes_cbc_decrypt(pDataBuf,buf3,newlen,iv2,de_ctx); printf("decrypt =\n"); print_hex(buf3,newlen); //================================ printf("AES with CTR\n"); //Copy data memset(DataBuf,0,1024); strcpy((char*)DataBuf,(char*)msg); pDataBuf = DataBuf;//tmp pointer uint8 iv3[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00}; iEncryptTimes = fsize/16; uint8 iRemain = fsize%16; uint8 ctr_buf[AES_BLOCK_SIZE]; //Save iv(as ctrl buffer) //memcpy(DataBuf,iv,16); printf("input =\n"); print_hex(DataBuf,fsize); //Init encrypt //aes_encrypt_ctx en_ctx[1]; //Encrypt for(i=0;i<iEncryptTimes;i++) { aes_encrypt_key128(key,en_ctx); ctr_init(iv3,iv3+4,ctr_buf);//we set iv as the nouce aes_ctr_encrypt(pDataBuf,buf,16,ctr_buf,ctr_inc,en_ctx);//iv has been changed, ctx has been changed!!! memcpy(pDataBuf,buf,16); pDataBuf += 16; } if(iRemain!=0) {//last times pDataBuf += i*16; aes_encrypt_key128(key,en_ctx); ctr_init(iv3,iv3+4,ctr_buf);//we set iv as the nouce aes_ctr_encrypt(pDataBuf,buf,iRemain,ctr_buf,ctr_inc,en_ctx);//iv has been changed, ctx has been changed!!! memcpy(pDataBuf,buf,iRemain); } printf("encrypt =\n"); print_hex(DataBuf,fsize); //Decrypt pDataBuf = DataBuf; uint8 iv4[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00}; //uint8 buf3[256]={'\0'}; //aes_decrypt_ctx de_ctx[1]; //aes_decrypt_key128(key,de_ctx); aes_encrypt_key128(key,en_ctx); ctr_init(iv4,iv4+4,ctr_buf);//we set iv as the nouce aes_ctr_decrypt(pDataBuf,buf3,16,ctr_buf,ctr_inc,en_ctx); printf("decrypt =\n"); print_hex(buf3,fsize); printf("\n");}輸出如下(CBC未去掉Padding):
參考資料:
http://zh.wikipedia.org/wiki/高級加密標準
http://zh.wikipedia.org/zh/塊密碼的工作模式
如您對AES/DEX加密解密有興趣,建議閱讀:Java DES加密和解密,Java AES加密和解密兩篇文章。
聯(lián)系客服