AES CBC和CTR加解密实例
来源:互联网 发布:xboxone好的软件 编辑:程序博客网 时间:2024/06/05 04:59
AES(Advanced Encryption Standard,高级加密标准)又叫Rijndael加密法,用来替代DES算法。常见AES加密模式有ECB、CBC、CFB、OFB和CTR等五种, CFB、OFB都带反馈,做流加密用的多,CBC和CTR、ECB多用于独立block加密,由于ECB算法有点小缺点,所以CBC和CTR这两种加解密方式用的较多,也是很多标准规范要求的实现算法,下面看一下这两种算法原理。
AES跟Rijndael相比有点小区别,就是使用固定块(block size)为128bits(16字节)(原Rijndael块大小更灵活),密钥长度支持128、192或256位。
一、AES CBC加解密原理
CBC加解密原理如下图所示(图片来源维基百科,参考文末地址):
CBC加密原理:明文跟向量异或,再用KEY进行加密,结果作为下个BLOCK的初始化向量。解密原理:使用密钥先对密文解密,解密后再同初始向量异或得到明文。
CBC需要对明文块大小进行Padding(补位),由于前后加密的相关性,只能实施串行化动作,无法并行运算。另外,CBC需要参量:密钥和初始化向量。
二、AES CTR加解密原理
CTR加密原理:用密钥对输入的计数器加密,然后同明文异或得到密文。解密原理:用密钥对输入计数器加密,然后同密文异或得到明文。
CTR不需要Padding,而且采用了流密钥方式加解密,适合于并行运算,CTR涉及参量:Nounce随机数、Counter计数器和密钥。Nounce随机数和Counter计数器整体可看作计数器,因为只要算法约定好,就可以回避掉串行化运算。
三、AES CBC和CTR加解密实例
下文实例使用了第三方开源源码,官方网址:http://www.gladman.me.uk/, 本文测试源码来源:http://gladman.plushost.co.uk/oldsite/AES/index.php,测试时,如下源码文件需加入工程:aes_modes.c、aescrypt.c、aeskey.c、aestab.c。
测试源码如下:
001
#include <iostream>
002
#include <string>
003
#include <time.h>
004
005
#include "aes/aes.h"
006
007
typedef
unsigned
char
uint8;
008
typedef
char
int8;
009
typedef
unsigned
short
uint16;
010
typedef
short
int16;
011
typedef
unsigned
int
uint32;
012
typedef
int
int32;
013
014
typedef
unsigned
__int64
uint64;
015
typedef
__int64
int64;
016
/******************************
017
For _LINUX
018
typedef long long int64;
019
typedef unsigned long long uint64;
020
******************************/
021
022
using
namespace
std;
023
024
//same as function rfc3686_inc
025
void
ctr_inc(unsigned
char
ctr_buf[16])
026
{
027
if
(!(++(ctr_buf[15])))
028
if
(!(++(ctr_buf[14])))
029
if
(!(++(ctr_buf[13])))
030
++(ctr_buf[12]);
031
}
032
033
//same as function rfc3686_init
034
//4Bytes nounce+8Bytes iv+4Bytes counter
035
void
ctr_init( unsigned
char
nonce[4], unsigned
char
iv[8], unsigned
char
ctr_buf[16])
036
{
037
memcpy
(ctr_buf, nonce, 4);
038
memcpy
(ctr_buf + 4, iv, 8);
039
memset
(ctr_buf + 12, 0, 4);
040
ctr_inc(ctr_buf);
041
}
042
043
void
print_hex(uint8* buf, uint64 len) {
044
//Print results:
045
for
(
int
i=0;i<len;i++) {
046
printf
(
"%02X"
,buf[i]);
047
if
(15 == i%16)
048
printf
(
"\n"
);
049
}
050
printf
(
"\n"
);
051
}
052
053
void
main() {
054
055
uint8 key[] = {0x10,0xa5,0x88,0x69,0xd7,0x4b,0xe5,0xa3,0x74,0xcf, 0x86,0x7c,0xfb,0x47,0x38,0x59};
//AES::DEFAULT_KEYLENGTH
056
uint8 buf[16];
//tmp buffer
057
058
uint8 msg[] =
"HelloWorld!23456"
;
059
uint64 fsize=
strlen
((
char
*)msg);
//message size
060
uint8* DataBuf=
new
uint8[1024];
//Data Buffer
061
062
063
//AES with CBC
064
printf
(
"AES with CBC\n"
);
065
066
//Copy data
067
memset
(DataBuf,0,1024);
068
strcpy
((
char
*)DataBuf,(
char
*)msg);
069
uint8* pDataBuf = DataBuf;
//tmp pointer
070
uint8 iv1[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00};
071
072
uint64 iEncryptTimes = fsize/16+1;
073
uint8 iPaddings = 16-fsize%16;
//Padding size
074
uint64 newlen = fsize+iPaddings;
//New length
075
076
//memcpy(DataBuf,iv,16);//Save iv
077
memset
(pDataBuf+fsize, iPaddings,iPaddings);
//Padding
078
printf
(
"input =\n"
);
079
print_hex(DataBuf,newlen);
080
aes_encrypt_ctx en_ctx[1];
//Init encrypt
081
082
//Encrypt
083
for
(uint64 i=0;i<iEncryptTimes;i++) {
084
aes_encrypt_key128(key,en_ctx);
085
aes_cbc_encrypt(pDataBuf,buf,16,iv1,en_ctx);
//iv has been changed, ctx has been changed!!!
086
memcpy
(pDataBuf,buf,16);
087
pDataBuf += 16;
088
}
089
090
printf
(
"encrypt =\n"
);
091
print_hex(DataBuf,newlen);
092
093
//Decrypt
094
pDataBuf = DataBuf;
095
uint8 iv2[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00};
096
uint8 buf3[256]={
'\0'
};
097
aes_decrypt_ctx de_ctx[1];
098
aes_decrypt_key128(key,de_ctx);
099
aes_cbc_decrypt(pDataBuf,buf3,newlen,iv2,de_ctx);
100
101
printf
(
"decrypt =\n"
);
102
print_hex(buf3,newlen);
103
104
//================================
105
106
printf
(
"AES with CTR\n"
);
107
//Copy data
108
memset
(DataBuf,0,1024);
109
strcpy
((
char
*)DataBuf,(
char
*)msg);
110
pDataBuf = DataBuf;
//tmp pointer
111
uint8 iv3[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00};
112
113
iEncryptTimes = fsize/16;
114
uint8 iRemain = fsize%16;
115
uint8 ctr_buf[AES_BLOCK_SIZE];
116
117
//Save iv(as ctrl buffer)
118
//memcpy(DataBuf,iv,16);
119
printf
(
"input =\n"
);
120
print_hex(DataBuf,fsize);
121
122
//Init encrypt
123
//aes_encrypt_ctx en_ctx[1];
124
125
//Encrypt
126
for
(i=0;i<iEncryptTimes;i++) {
127
aes_encrypt_key128(key,en_ctx);
128
ctr_init(iv3,iv3+4,ctr_buf);
//we set iv as the nouce
129
aes_ctr_encrypt(pDataBuf,buf,16,ctr_buf,ctr_inc,en_ctx);
//iv has been changed, ctx has been changed!!!
130
memcpy
(pDataBuf,buf,16);
131
pDataBuf += 16;
132
}
133
134
if
(iRemain!=0) {
//last times
135
pDataBuf += i*16;
136
aes_encrypt_key128(key,en_ctx);
137
ctr_init(iv3,iv3+4,ctr_buf);
//we set iv as the nouce
138
aes_ctr_encrypt(pDataBuf,buf,iRemain,ctr_buf,ctr_inc,en_ctx);
//iv has been changed, ctx has been changed!!!
139
memcpy
(pDataBuf,buf,iRemain);
140
}
141
142
printf
(
"encrypt =\n"
);
143
print_hex(DataBuf,fsize);
144
145
//Decrypt
146
pDataBuf = DataBuf;
147
uint8 iv4[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00};
148
//uint8 buf3[256]={'\0'};
149
//aes_decrypt_ctx de_ctx[1];
150
//aes_decrypt_key128(key,de_ctx);
151
aes_encrypt_key128(key,en_ctx);
152
ctr_init(iv4,iv4+4,ctr_buf);
//we set iv as the nouce
153
aes_ctr_decrypt(pDataBuf,buf3,16,ctr_buf,ctr_inc,en_ctx);
154
printf
(
"decrypt =\n"
);
155
print_hex(buf3,fsize);
156
157
printf
(
"\n"
);
158
}
输出如下(CBC未去掉Padding):
- AES with CBC
- input =
- 48656C6C6F576F726C64213233343536
- 10101010101010101010101010101010
- encrypt =
- F928E09884AA2BA8CC4B73C09304250C
- C9A0EEFF2295B5D83BEA0410001BD7C6
- decrypt =
- 48656C6C6F576F726C64213233343536
- 10101010101010101010101010101010
- AES with CTR
- input =
- 48656C6C6F576F726C64213233343536
- encrypt =
- 1CA0978FE499969C769B6346D46B66F9
- decrypt =
- 48656C6C6F576F726C64213233343536
参考资料:
http://zh.wikipedia.org/wiki/高级加密标准
http://zh.wikipedia.org/zh/块密码的工作模式
- AES CBC和CTR加解密实例
- AES CBC和CTR加解密实例
- AES/CBC/PKCS5Padding加解密
- C++ 和 java 使用 AES CBC 128 加解密
- c++ AES实现CBC,CTR模式解密函数
- C# AES-256-CBC 加解密
- AES/CBC/PKCS5Padding 对称算法加解密
- CBC和CTR解密模式——C++实现
- Android 使用AES/CBC/PKCS7Padding 加解密字符串
- Java 使用AES/CBC/PKCS7Padding 加解密字符串
- Openssl中AES加解密——CBC模式
- C#, Java, PHP, Python和Javascript几种语言的AES加密解密实现【多种语言AES/CBC/PKCS5Padding通用加解密数据】
- AES CBC模式加密/解密
- java aes解密cbc模式
- nodejs中aes-128-cbc加密和解密
- js版aes加解密实例
- compare of the CBC and CTR mode in PyCrypto AES
- AES 五种加密方式ECB、CBC、CTR、CFB、OFB
- Java开发中有时候用十六进制定义常量有什么好处?什么时候考虑使用十六进制?
- php中抽象类和接口的概念和区别
- VC中如何在对话框上显示位图
- CUDA开发矩阵乘法测试你的GPU效率
- 文件描述符 (file descriptor)
- AES CBC和CTR加解密实例
- php中抽象类和接口的概念和区别
- mfc 基本
- 仿百度文库/仿豆丁文库开源版MTCEO文库系统 v2.4
- 【SQL Server数据迁移】把csv文件中的数据导入SQL Server的方法
- BUG: soft lockup - CPU#0 stuck for 61s!
- C# 运用Jquery和Div实现Loading加载提示效果
- 编程名言名句
- 2010-01-25 11:52 php 接口类,抽象类 的实际作用和区别