openssl之aes加密(源码分析 AES_encrypt 与 AES_cbc_encrypt ,加密模式)

转自http://blog.csdn.net/chary8088/article/details/21124495

首先要了解AES加密是什么,以及几种加密模式的区别。之后才是编程。具体的编程案例,在下面的链接。

openssl之aes加密(AES_cbc_encrypt 与 AES_encrypt 的编程案例)

下面这个链接有详细图解。
http://www.cnblogs.com/adylee/archive/2007/09/14/893438.html
<p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"><span class="pln" style="color: rgb(0, 0, 0);">AES</span><span class="pun" style="color: rgb(102, 102, 0);">加密<a target=_blank href="http://lib.csdn.net/base/datastructure" class="replace_word" title="算法与数据结构知识库" target="_blank" style="text-decoration: none; color: rgb(223, 52, 52); font-weight: bold;">算法</a></span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">-</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">加密模式</span></p>
ECB模式 
  优点: 
  1.简单; 
  2.有利于并行计算; 
  3.误差不会被传送; 
  缺点: 
  1.不能隐藏明文的模式; 
  2.可能对明文进行主动攻击; 
CBC模式: 
  优点: 
  1.不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。 
  缺点: 
  1.不利于并行计算; 
  2.误差传递; 
  3. 需要初始化向量IV 
CFB模式: 
  优点: 
  1.隐藏了明文模式; 
  2.分组密码转化为流模式; 
  3.可以及时加密传送小于分组的数据; 
  缺点: 
  1.不利于并行计算; 
  2.误差传送:一个明文单元损坏影响多个单元; 
  3.唯一的IV; 
ofb模式: 
  优点: 
  1.隐藏了明文模式; 
  2.分组密码转化为流模式; 
  3.可以及时加密传送小于分组的数据; 
  缺点: 
  1.不利于并行计算; 
  2.对明文的主动攻击是可能的; 
  3.误差传送:一个明文单元损坏影响多个单元; 


了解这些加密模式之后,再看openssl提供的接口就好理解了。
<p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"><span class="pln" style="color: rgb(0, 0, 0);">openssl</span><span class="pun" style="color: rgb(102, 102, 0);">提供的</span><span class="pln" style="color: rgb(0, 0, 0);">aes</span><span class="pun" style="color: rgb(102, 102, 0);">加密接口</span></p>
以下接口来自“crypto/aes/aes.h”,有openssl源码。
//设置加密和解密器
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);

//默认的加密解密方式,参数好理解
void AES_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void AES_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);

//下面这些也是常用的加密方式,但是参数很多,而源码对于参数使用介绍不多,只能摸索
void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key, const int enc);
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc); //参数相对复杂
void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num);
void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char ivec[AES_BLOCK_SIZE],
unsigned char ecount_buf[AES_BLOCK_SIZE],
unsigned int *num);

从下面这个文件可以看出, AES_encrypt 就是ecb加密的方式。而AES_set_encrypt_key和 AES_encrypt,它们的实现在"crypto/aes/aes_x86core.c"和 "crypto/aes/aes_core.c",也就是有两个版本,根据平台选择。看源码。
<p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"></p><div><span class="str" style="color: rgb(0, 136, 0);">"</span><span style="font-family: "Hiragino Sans GB W3", "Hiragino Sans GB", Arial, Helvetica, simsun, 宋体; white-space: normal;"><span class="str" style="color: rgb(0, 136, 0);">crypto/aes/</span></span><span style="font-family: "Hiragino Sans GB W3", "Hiragino Sans GB", Arial, Helvetica, simsun, 宋体;"><span class="str" style="color: rgb(0, 136, 0);">aes_ecb.c"</span></span></div><div><span class="kwd" style="color: rgb(0, 0, 136);">void</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(255, 0, 0);"><span class="pln" style="color: rgb(0, 0, 0);">AES_ecb_encrypt</span></span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="kwd" style="color: rgb(0, 0, 136);">const</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">unsigned</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">char</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">*</span><span class="kwd" style="color: rgb(0, 0, 136);">in</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">unsigned</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">char</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">*</span><span class="kwd" style="color: rgb(0, 0, 136);">out</span><span class="pun" style="color: rgb(102, 102, 0);">,</span></div><div><span class="pln" style="color: rgb(0, 0, 0);">		</span><span class="pln" style="color: rgb(0, 0, 0);">     </span><span class="kwd" style="color: rgb(0, 0, 136);">const</span><span class="pln" style="color: rgb(0, 0, 0);"> AES_KEY </span><span class="pun" style="color: rgb(102, 102, 0);">*</span><span class="pln" style="color: rgb(0, 0, 0);">key</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">const</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">int</span><span class="pln" style="color: rgb(0, 0, 0);"> enc</span><span class="pun" style="color: rgb(102, 102, 0);">)</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">{</span></div><div><span class="pln" style="color: rgb(0, 0, 0);">        </span><span class="kwd" style="color: rgb(0, 0, 136);">assert</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="kwd" style="color: rgb(0, 0, 136);">in</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">&&</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">out</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">&&</span><span class="pln" style="color: rgb(0, 0, 0);"> key</span><span class="pun" style="color: rgb(102, 102, 0);">);</span></div><div><span class="pln" style="color: rgb(0, 0, 0);">	</span><span class="kwd" style="color: rgb(0, 0, 136);">assert</span><span class="pun" style="color: rgb(102, 102, 0);">((</span><span class="pln" style="color: rgb(0, 0, 0);">AES_ENCRYPT </span><span class="pun" style="color: rgb(102, 102, 0);">==</span><span class="pln" style="color: rgb(0, 0, 0);"> enc</span><span class="pun" style="color: rgb(102, 102, 0);">)||(</span><span class="pln" style="color: rgb(0, 0, 0);">AES_DECRYPT </span><span class="pun" style="color: rgb(102, 102, 0);">==</span><span class="pln" style="color: rgb(0, 0, 0);"> enc</span><span class="pun" style="color: rgb(102, 102, 0);">));</span></div><div><span class="pln" style="color: rgb(0, 0, 0);">	</span><span class="kwd" style="color: rgb(0, 0, 136);">if</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">AES_ENCRYPT </span><span class="pun" style="color: rgb(102, 102, 0);">==</span><span class="pln" style="color: rgb(0, 0, 0);"> enc</span><span class="pun" style="color: rgb(102, 102, 0);">)</span></div><div><span class="pln" style="color: rgb(0, 0, 0);">		</span><span class="pln" style="color: rgb(0, 0, 0);">AES_encrypt</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="kwd" style="color: rgb(0, 0, 136);">in</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">out</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> key</span><span class="pun" style="color: rgb(102, 102, 0);">);</span></div><div><span class="pln" style="color: rgb(0, 0, 0);">	</span><span class="kwd" style="color: rgb(0, 0, 136);">else</span></div><div><span class="pln" style="color: rgb(0, 0, 0);">		</span><span class="pln" style="color: rgb(0, 0, 0);">AES_decrypt</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="kwd" style="color: rgb(0, 0, 136);">in</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">out</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> key</span><span class="pun" style="color: rgb(102, 102, 0);">);</span></div><div><span class="pun" style="color: rgb(102, 102, 0);">}</span></div><div><strong><span style="color: rgb(255, 0, 0);"><span class="pun" style="color: rgb(102, 102, 0);">从这里可以看出,</span><span class="pln" style="color: rgb(0, 0, 0);">ecb</span><span class="pun" style="color: rgb(102, 102, 0);">方式的加密,是由</span><span class="pln" style="color: rgb(0, 0, 0);">AES_encrypt</span><span class="pun" style="color: rgb(102, 102, 0);">接口实现的。</span></span></strong></div><p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"></p>

而cbc的加密方式在另外的地方实现了,下面给出目录以及源代码。
<span style="font-family: "Hiragino Sans GB W3", "Hiragino Sans GB", Arial, Helvetica, simsun, 宋体;"><span class="str" style="color: rgb(0, 136, 0);">"</span></span><span style="font-family: "Hiragino Sans GB W3", "Hiragino Sans GB", Arial, Helvetica, simsun, 宋体; white-space: normal;"><span class="str" style="color: rgb(0, 136, 0);">crypto/aes/</span></span><span style="font-family: "Hiragino Sans GB W3", "Hiragino Sans GB", Arial, Helvetica, simsun, 宋体;"><span class="str" style="color: rgb(0, 136, 0);">aes_cbc.c"</span></span>
<p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"><span class="kwd" style="color: rgb(0, 0, 136);">void</span><span class="pln" style="color: rgb(0, 0, 0);"> AES_cbc_encrypt</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="kwd" style="color: rgb(0, 0, 136);">const</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">unsigned</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">char</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">*</span><span class="kwd" style="color: rgb(0, 0, 136);">in</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">unsigned</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">char</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">*</span><span class="kwd" style="color: rgb(0, 0, 136);">out</span><span class="pun" style="color: rgb(102, 102, 0);">,</span>
<span class="pln" style="color: rgb(0, 0, 0);">		     </span><span class="typ" style="color: rgb(102, 0, 102);">size_t</span><span class="pln" style="color: rgb(0, 0, 0);"> len</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">const</span><span class="pln" style="color: rgb(0, 0, 0);"> AES_KEY </span><span class="pun" style="color: rgb(102, 102, 0);">*</span><span class="pln" style="color: rgb(0, 0, 0);">key</span><span class="pun" style="color: rgb(102, 102, 0);">,</span>
<span class="pln" style="color: rgb(0, 0, 0);">		     </span><span class="kwd" style="color: rgb(0, 0, 136);">unsigned</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">char</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">*</span><span class="pln" style="color: rgb(0, 0, 0);">ivec</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">const</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">int</span><span class="pln" style="color: rgb(0, 0, 0);"> enc</span><span class="pun" style="color: rgb(102, 102, 0);">)</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">{</span>

<span class="pln" style="color: rgb(0, 0, 0);">	</span><span class="kwd" style="color: rgb(0, 0, 136);">if</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">enc</span><span class="pun" style="color: rgb(102, 102, 0);">)</span>
<span class="pln" style="color: rgb(0, 0, 0);">		</span><span style="color: rgb(255, 0, 0);"><span class="pln" style="color: rgb(0, 0, 0);">CRYPTO_cbc128_encrypt</span></span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="kwd" style="color: rgb(0, 0, 136);">in</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="kwd" style="color: rgb(0, 0, 136);">out</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);">len</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);">key</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);">ivec</span><span class="pun" style="color: rgb(102, 102, 0);">,(</span><span class="pln" style="color: rgb(0, 0, 0);">block128_f</span><span class="pun" style="color: rgb(102, 102, 0);">)</span><span class="pln" style="color: rgb(0, 0, 0);">AES_encrypt</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);">	</span><span class="kwd" style="color: rgb(0, 0, 136);">else</span>
<span class="pln" style="color: rgb(0, 0, 0);">		CRYPTO_cbc128_decrypt</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="kwd" style="color: rgb(0, 0, 136);">in</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="kwd" style="color: rgb(0, 0, 136);">out</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);">len</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);">key</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);">ivec</span><span class="pun" style="color: rgb(102, 102, 0);">,(</span><span class="pln" style="color: rgb(0, 0, 0);">block128_f</span><span class="pun" style="color: rgb(102, 102, 0);">)</span><span class="pln" style="color: rgb(0, 0, 0);">AES_decrypt</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pun" style="color: rgb(102, 102, 0);">}</span></p><p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"><span style="font-weight: bold;"><span style="color: rgb(255, 0, 0);"><span class="pun" style="color: rgb(102, 102, 0);">从这里看出,</span><span style="font-family: "Hiragino Sans GB W3", "Hiragino Sans GB", Arial, Helvetica, simsun, 宋体;"><span class="pln" style="color: rgb(0, 0, 0);">cbc</span><span class="pun" style="color: rgb(102, 102, 0);">加密方式,调用接口</span></span><span style="font-family: "Hiragino Sans GB W3", "Hiragino Sans GB", Arial, Helvetica, simsun, 宋体;"><span class="pln" style="color: rgb(0, 0, 0);">CRYPTO_cbc128_decrypt</span></span><span style="font-family: "Hiragino Sans GB W3", "Hiragino Sans GB", Arial, Helvetica, simsun, 宋体;"><span class="pun" style="color: rgb(102, 102, 0);">,而它又将</span></span></span></span><span style="font-family: "Hiragino Sans GB W3", "Hiragino Sans GB", Arial, Helvetica, simsun, 宋体;"><strong><span style="color: rgb(255, 0, 0);"><span class="pln" style="color: rgb(0, 0, 0);">AES_encrypt</span><span class="pun" style="color: rgb(102, 102, 0);">作为参数传入</span></span></strong><span class="pun" style="color: rgb(102, 102, 0);">。</span></span></p>
<p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"></p><div><span style="font-family: "Hiragino Sans GB W3", "Hiragino Sans GB", Arial, Helvetica, simsun, 宋体; white-space: normal;"><span class="str" style="color: rgb(0, 136, 0);">"crypto/modes/</span></span><span style="font-family: "Hiragino Sans GB W3", "Hiragino Sans GB", Arial, Helvetica, simsun, 宋体;"><span style="white-space: normal;"><span class="str" style="color: rgb(0, 136, 0);">cbc128.c"</span></span></span></div><div><span class="kwd" style="color: rgb(0, 0, 136);">void</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(255, 0, 0);"><span class="pln" style="color: rgb(0, 0, 0);">CRYPTO_cbc128_encrypt</span></span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="kwd" style="color: rgb(0, 0, 136);">const</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">unsigned</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">char</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">*</span><span class="kwd" style="color: rgb(0, 0, 136);">in</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">unsigned</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">char</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">*</span><span class="kwd" style="color: rgb(0, 0, 136);">out</span><span class="pun" style="color: rgb(102, 102, 0);">,</span></div><div><span class="pln" style="color: rgb(0, 0, 0);">			</span><span class="typ" style="color: rgb(102, 0, 102);">size_t</span><span class="pln" style="color: rgb(0, 0, 0);"> len</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">const</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">void</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">*</span><span class="pln" style="color: rgb(0, 0, 0);">key</span><span class="pun" style="color: rgb(102, 102, 0);">,</span></div><div><span class="pln" style="color: rgb(0, 0, 0);">			</span><span class="kwd" style="color: rgb(0, 0, 136);">unsigned</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">char</span><span class="pln" style="color: rgb(0, 0, 0);"> ivec</span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="lit" style="color: rgb(0, 102, 102);">16</span><span class="pun" style="color: rgb(102, 102, 0);">],</span><span class="pln" style="color: rgb(0, 0, 0);"> block128_f block</span><span class="pun" style="color: rgb(102, 102, 0);">)</span></div><div><span class="pun" style="color: rgb(102, 102, 0);">{</span><span style="color: rgb(255, 0, 0);"><span class="com" style="color: rgb(136, 0, 0);">//这里的block就是</span><span style="font-family: "Hiragino Sans GB W3", "Hiragino Sans GB", Arial, Helvetica, simsun, 宋体;"><span class="com" style="color: rgb(136, 0, 0);">AES_encrypt</span></span></span></div><div><span class="com" style="color: rgb(136, 0, 0);">	</span><span class="com" style="color: rgb(136, 0, 0);">size_t n;</span></div><div><span class="com" style="color: rgb(136, 0, 0);">	</span><span class="com" style="color: rgb(136, 0, 0);">const unsigned char *iv = ivec;</span></div><div><span class="com" style="color: rgb(136, 0, 0);">	</span><span class="com" style="color: rgb(136, 0, 0);">assert(in && out && key && ivec);</span></div><div><span class="com" style="color: rgb(136, 0, 0);">#if !defined(OPENSSL_SMALL_FOOTPRINT)</span></div><div><span class="com" style="color: rgb(136, 0, 0);">	</span><span class="com" style="color: rgb(136, 0, 0);">if (STRICT_ALIGNMENT &&</span></div><div><span class="com" style="color: rgb(136, 0, 0);">	</span><span class="com" style="color: rgb(136, 0, 0);">    ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(size_t) != 0) {</span></div><div><span class="com" style="color: rgb(136, 0, 0);">		</span><span class="com" style="color: rgb(136, 0, 0);">while (len>=16) {</span></div><div><span class="com" style="color: rgb(136, 0, 0);">			</span><span class="com" style="color: rgb(136, 0, 0);">for(n=0; n<16; ++n)</span></div><div><span class="com" style="color: rgb(136, 0, 0);">				</span><span class="com" style="color: rgb(136, 0, 0);">out[n] = in[n] ^ iv[n];</span><span style="color: rgb(255, 0, 0);"><span class="com" style="color: rgb(136, 0, 0);">//输入与初始化向量进行异或,保存在out</span></span></div><div><span class="com" style="color: rgb(136, 0, 0);">			</span><span class="com" style="color: rgb(136, 0, 0);">(*block)(out, out, key);</span><span style="color: rgb(255, 0, 0);"><span class="com" style="color: rgb(136, 0, 0);">//调用</span><span style="font-family: "Hiragino Sans GB W3", "Hiragino Sans GB", Arial, Helvetica, simsun, 宋体;"><span class="com" style="color: rgb(136, 0, 0);">AES_encrypt进行加密,异或结果out作为加密输入</span></span></span></div><div><span style="color: rgb(255, 0, 0);"><span style="font-family: "Hiragino Sans GB W3", "Hiragino Sans GB", Arial, Helvetica, simsun, 宋体;"><span class="com" style="color: rgb(136, 0, 0);">                                                //加密输出结果也保存在out里面,</span></span></span></div><div><span class="com" style="color: rgb(136, 0, 0);">			</span><span class="com" style="color: rgb(136, 0, 0);">iv = out;</span><span style="color: rgb(255, 0, 0);"><span class="com" style="color: rgb(136, 0, 0);">//将前一次密文,作为后一次的初始化向量,从而完成加密</span></span></div><div><span class="com" style="color: rgb(136, 0, 0);">			</span><span class="com" style="color: rgb(136, 0, 0);">len -= 16;</span></div><div><span class="com" style="color: rgb(136, 0, 0);">			</span><span class="com" style="color: rgb(136, 0, 0);">in  += 16;</span></div><div><span class="com" style="color: rgb(136, 0, 0);">			</span><span class="com" style="color: rgb(136, 0, 0);">out += 16;</span></div><div><span class="com" style="color: rgb(136, 0, 0);">		</span><span class="com" style="color: rgb(136, 0, 0);">}</span></div><div><span class="com" style="color: rgb(136, 0, 0);">	</span><span class="com" style="color: rgb(136, 0, 0);">} else {</span></div><div><span class="com" style="color: rgb(136, 0, 0);">		</span><span class="com" style="color: rgb(136, 0, 0);">while (len>=16) {</span></div><div><span class="com" style="color: rgb(136, 0, 0);">			</span><span class="com" style="color: rgb(136, 0, 0);">for(n=0; n<16; n+=sizeof(size_t))</span></div><div><span class="com" style="color: rgb(136, 0, 0);">				</span><span class="com" style="color: rgb(136, 0, 0);">*(size_t*)(out+n) =</span></div><div><span class="com" style="color: rgb(136, 0, 0);">				</span><span class="com" style="color: rgb(136, 0, 0);">*(size_t*)(in+n) ^ *(size_t*)(iv+n);</span></div><div><span class="com" style="color: rgb(136, 0, 0);">			</span><span class="com" style="color: rgb(136, 0, 0);">(*block)(out, out, key);</span></div><div><span class="com" style="color: rgb(136, 0, 0);">			</span><span class="com" style="color: rgb(136, 0, 0);">iv = out;</span></div><div><span class="com" style="color: rgb(136, 0, 0);">			</span><span class="com" style="color: rgb(136, 0, 0);">len -= 16;</span></div><div><span class="com" style="color: rgb(136, 0, 0);">			</span><span class="com" style="color: rgb(136, 0, 0);">in  += 16;</span></div><div><span class="com" style="color: rgb(136, 0, 0);">			</span><span class="com" style="color: rgb(136, 0, 0);">out += 16;</span></div><div><span class="com" style="color: rgb(136, 0, 0);">		</span><span class="com" style="color: rgb(136, 0, 0);">}</span></div><div><span class="com" style="color: rgb(136, 0, 0);">	</span><span class="com" style="color: rgb(136, 0, 0);">}</span></div><div><span class="com" style="color: rgb(136, 0, 0);">#endif</span></div><div><span class="com" style="color: rgb(136, 0, 0);">	</span><span class="com" style="color: rgb(136, 0, 0);">while (len) {</span></div><div><span class="com" style="color: rgb(136, 0, 0);">		</span><span class="com" style="color: rgb(136, 0, 0);">for(n=0; n<16 && n<len; ++n)</span></div><div><span class="com" style="color: rgb(136, 0, 0);">			</span><span class="com" style="color: rgb(136, 0, 0);">out[n] = in[n] ^ iv[n];</span><span style="color: rgb(255, 0, 0);"><span class="com" style="color: rgb(136, 0, 0);">//in和iv异或</span></span></div><div><span class="com" style="color: rgb(136, 0, 0);">		</span><span class="com" style="color: rgb(136, 0, 0);">for(; n<16; ++n)</span><span style="color: rgb(255, 0, 0);"><span class="com" style="color: rgb(136, 0, 0);">//</span><span style="font-family: "Hiragino Sans GB W3", "Hiragino Sans GB", Arial, Helvetica, simsun, 宋体;"><span class="com" style="color: rgb(136, 0, 0);">如果in长度不是16的整数倍</span></span></span></div><div><span class="com" style="color: rgb(136, 0, 0);">			</span><span class="com" style="color: rgb(136, 0, 0);">out[n] = iv[n];</span><span style="color: rgb(255, 0, 0);"><span class="com" style="color: rgb(136, 0, 0);">//最后的out直接用iv初始化,其实也就相当于out与0进行异或</span></span></div><div><span class="com" style="color: rgb(136, 0, 0);">		</span><span class="com" style="color: rgb(136, 0, 0);">(*block)(out, out, key);</span></div><div><span class="com" style="color: rgb(136, 0, 0);">		</span><span class="com" style="color: rgb(136, 0, 0);">iv = out;</span></div><div><span class="com" style="color: rgb(136, 0, 0);">		</span><span class="com" style="color: rgb(136, 0, 0);">if (len<=16) break;</span><span style="color: rgb(255, 0, 0);"><span class="com" style="color: rgb(136, 0, 0);">//加密结束</span></span></div><div><span class="com" style="color: rgb(136, 0, 0);">		</span><span class="com" style="color: rgb(136, 0, 0);">len -= 16;</span></div><div><span class="com" style="color: rgb(136, 0, 0);">		</span><span class="com" style="color: rgb(136, 0, 0);">in  += 16;</span></div><div><span class="com" style="color: rgb(136, 0, 0);">		</span><span class="com" style="color: rgb(136, 0, 0);">out += 16;</span></div><div><span class="com" style="color: rgb(136, 0, 0);">	</span><span class="com" style="color: rgb(136, 0, 0);">}</span></div><div><span class="com" style="color: rgb(136, 0, 0);">	</span><span class="com" style="color: rgb(136, 0, 0);">memcpy(ivec,iv,16);</span></div><div><span class="com" style="color: rgb(136, 0, 0);">}</span></div><div><span style="font-family: "Hiragino Sans GB W3", "Hiragino Sans GB", Arial, Helvetica, simsun, 宋体; white-space: normal;"><span class="com" style="color: rgb(136, 0, 0);">//从上面的源码可以看出,cbc本质上和ecb差别不大,唯一区别是将前一次加密结果,与要加密的内容异或。因此,cbc的并行性较差,因为每次都要等待前一次的结果,而ecb则不用,速度较快。其主要区别仍然看文章开头,原理图看参考链接。</span></span></div><p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"></p>

调用实例:
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. int aes_encrypt(char* in, char* key, char* out)//, int olen)  
  2. {  
  3.     if(!in || !key || !out) return 0;  
  4.     AES_KEY aes;  
  5.     if(AES_set_encrypt_key((unsigned char*)key, 128, &aes) < 0)  
  6.     {  
  7.         return 0;  
  8.     }  
  9.     int len=strlen(in)/<span style="font-family: 'Hiragino Sans GB W3', 'Hiragino Sans GB', Arial, Helvetica, simsun, u5b8bu4f53;">AES_BLOCK_SIZE*</span><span style="font-family: 'Hiragino Sans GB W3', 'Hiragino Sans GB', Arial, Helvetica, simsun, u5b8bu4f53;">AES_BLOCK_SIZE</span><span style="font-family: 'Hiragino Sans GB W3', 'Hiragino Sans GB', Arial, Helvetica, simsun, u5b8bu4f53;">, en_len=0;</span><span style="font-family: 'Hiragino Sans GB W3', 'Hiragino Sans GB', Arial, Helvetica, simsun, u5b8bu4f53;">  
  10. </span>    while(en_len<len)//输入输出字符串够长,并且是AES_BLOCK_SIZE的整数倍,需要严格限制  
  11.     {  
  12.         AES_encrypt((unsigned char*)in, (unsigned char*)out, &aes);  
  13.         in+=AES_BLOCK_SIZE;  
  14.         out+=AES_BLOCK_SIZE;  
  15.         en_len+=AES_BLOCK_SIZE;  
  16.     }  
  17.     return 1;  
  18. }  
  19. int aes_decrypt(char* in, char* key, char* out)  
  20. {  
  21.     if(!in || !key || !out) return 0;  
  22.     AES_KEY aes;  
  23.     if(AES_set_decrypt_key((unsigned char*)key, 128, &aes) < 0)  
  24.     {  
  25.         return 0;  
  26.     }  
  27.     int len=strlen(in), en_len=0;  
  28.     while(en_len<len)  
  29.     {  
  30.         AES_decrypt((unsigned char*)in, (unsigned char*)out, &aes);  
  31.         in+=AES_BLOCK_SIZE;  
  32.         out+=AES_BLOCK_SIZE;  
  33.         en_len+=AES_BLOCK_SIZE;  
  34.     }  
  35.     return 1;  
  36. }  
最近遇到一个坑,
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. AES_encrypt <pre code_snippet_id="232583" snippet_file_name="blog_20140312_1_226454" name="code" class="cpp" style="color: rgb(55, 42, 24); font-size: 16px; line-height: 28px;">AES_decrypt  
 
   就是这两个函数让我折腾了四五天,心力憔悴,几近崩溃,也许是走火入魔了,因为遇到了挑战,非要干掉它,而不是绕过! 
  
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. int aes_encrypt(char* in, char* key, char* out)//, int olen)  
  2. {  
  3.     if(!in || !key || !out) return 0;  
  4.     AES_KEY aes;  
  5.     if(AES_set_encrypt_key((unsigned char*)key, 128, &aes) < 0)  
  6.     {  
  7.         return 0;  
  8.     }  
  9.     <pre code_snippet_id="232583" snippet_file_name="blog_20140312_1_226454" name="code" class="cpp" style="color: rgb(55, 42, 24); font-size: 16px; line-height: 28px;">    int len=strlen(in)/<span style="font-family: 'Hiragino Sans GB W3', 'Hiragino Sans GB', Arial, Helvetica, simsun, u5b8bu4f53;">AES_BLOCK_SIZE*</span><span style="font-family: 'Hiragino Sans GB W3', 'Hiragino Sans GB', Arial, Helvetica, simsun, u5b8bu4f53;">AES_BLOCK_SIZE</span><span style="font-family: 'Hiragino Sans GB W3', 'Hiragino Sans GB', Arial, Helvetica, simsun, u5b8bu4f53;">, en_len=0;</span>  
 
   
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. char *lptmp = new char[len+1];  
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.  memset(lptmp, '\0', len+1);  
  2. while(en_len<len)//输入输出字符串够长,并且是AES_BLOCK_SIZE的整数倍,需要严格限制  
  3. {  
  4.     AES_encrypt((unsigned char*)in, (unsigned char*)lptmp, &aes);  
  5.     in+=AES_BLOCK_SIZE;  
  6.     <span style="font-family: 'Hiragino Sans GB W3', 'Hiragino Sans GB', Arial, Helvetica, simsun, u5b8bu4f53;">lptmp</span><span style="font-family: 'Hiragino Sans GB W3', 'Hiragino Sans GB', Arial, Helvetica, simsun, u5b8bu4f53;">+=AES_BLOCK_SIZE;</span>  
  7.     en_len+=AES_BLOCK_SIZE;  
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <span style="color:#372a18;">        //hex(lptmp)  </span><strong><span style="color:#ff0000;">那么就发现第一个数据块加密的结果是对的,后面就错误了,加密后的数据很多是0,查了openssl的</span></strong>  
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <strong><span style="color:#ff0000;">        //源代码这个aes这块的加解密是线程安全的,有谁知道原因?</span></strong>  
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. }  
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. if(lptmp)  
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. {  
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. delete []lptmp;  
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. lptmp = NULL;  
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.     }  
  2.     return 1;  
  3. }  


最后给出一个链接,利用openssl的AES接口进行编程。
参考资料:

分组对称加密模式:ECB/CBC/CFB/OFB缺CTR

http://fossies.org/dox/openssl-1.0.1f/index.html  (详细源码)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值