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

转载 2015年07月07日 11:00:38

转自: http://yuanshuilee.blog.163.com/blog/static/21769727520140942826137/


现在利用AES的加密接口,进行加密解密编程以及接口封装。关于开发环境见最后

由于前一篇博客已经深入源码了解了cbc加密以及ecb加密,所以下面直接给出cbc加密解密的代码

#include <stdio.h> #include <string.h> #include <stdlib.h> #include <openssl/aes.h> #define AES_BITS 128 #define MSG_LEN 128 int aes_encrypt(char* in, char* key, char* out)//, int olen)可能会设置buf长度 { if(!in || !key || !out) return 0; unsigned char iv[AES_BLOCK_SIZE];//加密的初始化向量 for(int i=0; i<AES_BLOCK_SIZE; ++i)//iv一般设置为全0,可以设置其他,但是加密解密要一样就行 iv[i]=0; AES_KEY aes; if(AES_set_encrypt_key((unsigned char*)key, 128, &aes) < 0) { return 0; } int len=strlen(in);//这里的长度是char*in的长度,但是如果in中间包含'\0'字符的话

//那么就只会加密前面'\0'前面的一段,所以,这个len可以作为参数传进来,记录in的长度

//至于解密也是一个道理,光以'\0'来判断字符串长度,确有不妥,后面都是一个道理。 AES_cbc_encrypt((unsigned char*)in, (unsigned char*)out, len, &aes, iv, AES_ENCRYPT); return 1; } int aes_decrypt(char* in, char* key, char* out) { if(!in || !key || !out) return 0; unsigned char iv[AES_BLOCK_SIZE];//加密的初始化向量 for(int i=0; i<AES_BLOCK_SIZE; ++i)//iv一般设置为全0,可以设置其他,但是加密解密要一样就行 iv[i]=0; AES_KEY aes; if(AES_set_decrypt_key((unsigned char*)key, 128, &aes) < 0) { return 0; } int len=strlen(in); AES_cbc_encrypt((unsigned char*)in, (unsigned char*)out, len, &aes, iv, AES_DECRYPT); return 1; } int main(int argc,char *argv[]) { char sourceStringTemp[MSG_LEN]; char dstStringTemp[MSG_LEN]; memset((char*)sourceStringTemp, 0 ,MSG_LEN); memset((char*)dstStringTemp, 0 ,MSG_LEN); strcpy((char*)sourceStringTemp, "123456789 123456789 123456789 12a"); //strcpy((char*)sourceStringTemp, argv[1]); char key[AES_BLOCK_SIZE]; int i; for(i = 0; i < 16; i++)//可自由设置密钥 { key[i] = 32 + i; } if(!aes_encrypt(sourceStringTemp,key,dstStringTemp)) { printf("encrypt error\n"); return -1; } printf("enc %d:",strlen((char*)dstStringTemp)); for(i= 0;dstStringTemp[i];i+=1){ printf("%x",(unsigned char)dstStringTemp[i]); } memset((char*)sourceStringTemp, 0 ,MSG_LEN); if(!aes_decrypt(dstStringTemp,key,sourceStringTemp)) { printf("decrypt error\n"); return -1; } printf("\n"); printf("dec %d:",strlen((char*)sourceStringTemp)); printf("%s\n",sourceStringTemp); for(i= 0;sourceStringTemp[i];i+=1){ printf("%x",(unsigned char)sourceStringTemp[i]); } printf("\n"); return 0; }

openssl之aes编程(AES_cbc_encrypt 与 AES_encrypt) - yuanshuilee - 勇敢的劳尤条

上图是运行程序的测试结果。可见加密解密已经完成。
这里也能够看出,AES_cbc_encrypt的参数主要用途,其中,len是加密数据长度,由于加密调用了AES_encrypt,而这个函数每次只能加密16个字节,所以,out长度必须是16的整数倍,或者至少大于in长度的最小16倍数,这样才能真正完成加密解密。而如果in长度不足不是16的倍数,那么最后的几个字节,其实相当于填充0。
AES_cbc_encrypt((unsigned char*)in, (unsigned char*)out, len, &aes, iv, AES_ENCRYPT)

PS:我在编写代码的过程中,又一次,加密成功,但是解密一直失败,一直不明白为什么,后来才懂。注意代码中的红色部分,AES_set_encrypt_keyAES_set_decrypt_key是不一样的,同时,加密和解密的参数AES_ENCRYPT和AES_DECRYPT也是不一样的,要特别注意,很可能因为细节忘了,导致出现问题而浪费时间。现在,用aes_encrypt对加密方式进行封装,这样的话,里面可以修改,哪怕用其他的加密方式,比如cfb或者ofb等,都没关系,因为主函数不需要再改了。

下面,还将给出使用AES_encrypt进行加密解密的代码。只是对接口内容进行修改,主函数并不变化,所以就不给出。可以看出,使用AES_encrypt每次只能加密16个字节的东西,如果不够,那么需要填充,所以,这就意味着in和out的长度,都必须是16的倍数。其实,经过测试发现,in并不一定要是16的倍数,但是,加密算法会读16个字节,也就是会继续读in之后的16个字节,读了一段我们不知道的东西,解密也是一样,如果空间不够大,程序只管往out之后的地址填充加密后的内容,所以,这个时候,就需要自己严格把控字符长度,以便加密算法能够每次加密一组16个字节。
所以,我写的接口,增加长度参数,是很有必要的
ps:另外还有一个细节,buf的长度最好设置为16的倍数+1,最后一个字节设置为0,以便通知为结束符。因为如果设置刚好是16的倍数,那么加密后的密文刚好填满buf,打印的时候会因为找不到结束符,多打出很多东西。
int aes_encrypt(char* in, char* key, char* out)//, int olen)
{
    if(!in || !key || !out) return 0;
    AES_KEY aes;
    if(AES_set_encrypt_key((unsigned char*)key, 128, &aes) < 0)
    {
        return 0;
    }
    int len=strlen(in), en_len=0;
    while(en_len<len)//输入输出字符串够长,并且是AES_BLOCK_SIZE的整数倍,需要严格限制
    {
    	AES_encrypt((unsigned char*)in, (unsigned char*)out, &aes);
    	in+=AES_BLOCK_SIZE;
    	out+=AES_BLOCK_SIZE;
    	en_len+=AES_BLOCK_SIZE;
    }
    return 1;
}
int aes_decrypt(char* in, char* key, char* out)
{
    if(!in || !key || !out) return 0;
    AES_KEY aes;
    if(AES_set_decrypt_key((unsigned char*)key, 128, &aes) < 0)
    {
        return 0;
    }
    int len=strlen(in), en_len=0;
    while(en_len<len)
    {
    	AES_decrypt((unsigned char*)in, (unsigned char*)out, &aes);
    	in+=AES_BLOCK_SIZE;
    	out+=AES_BLOCK_SIZE;
    	en_len+=AES_BLOCK_SIZE;
    }
    return 1;
}
openssl之aes编程(AES_cbc_encrypt 与 AES_encrypt) - yuanshuilee - 勇敢的劳尤条

上面这个加密解密后的结果。如果仔细观察的话,可以看出,两种加密方式得到的密文,前面的16个字节是一样的。而后面的就不一样了。这是因为,cbc模式使用了初始化向量,而我初始化向量设置为0,等于不起作用,而cbc模式的加密也是调用了AES_encrypt接口,所以前面的16个字节是一样的,接着的内容,会跟前一次得到的密文进行异或,所以就不一样了。

关于cbc加密和ecb加密,强烈推荐看openssl之aes加密(源码分析 AES_encrypt 与 AES_cbc_encrypt ,加密模式),是一个很好的理解和入门。

开发环境:
我是ubuntu12.04,安装openssl,可以参考下面的链接。
ubuntu12.04 源码编译安装openssl1.0.1e 以及md5test.c的测试代码
关于编译环境,我使用的是CodeBlocks,也有直接makefile搞定。参考下面的链接。
http://yuanshuilee.blog.163.com/blog/static/21769727520140241346693/


参考资料:
openssl之aes加密(源码分析 AES_encrypt 与 AES_cbc_encrypt ,加密模式)
http://blog.csdn.net/qncj666/article/details/8244893 (最初的参考代码来源)
http://fossies.org/dox/openssl-1.0.1f/index.html (详细源码)
http://www.cnblogs.com/adylee/archive/2007/09/14/893438.html

相关文章推荐

使用Openssl的AES加密算法

转自:http://www.thinkemb.com/wordpress/?p=18 在网络应用的信息安全是基于密码学的,所以如果想做安全方面的邻域需要有一定的密码学基础。当然最好的学习方法...

高级加密标准AES的工作模式(ECB、CBC、CFB、OFB)

最近在重构之前写的HTTP代理,这个代理是由代理客户端和代理服务端组成的,二者之前使用SSL保证通信内容不会受到中间人(MITM)攻击。而新的实现打算移除SSL,因为SSL握手的开销过大,尤其是客户端...

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

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

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

转自http://blog.csdn.net/chary8088/article/details/21124495 首先要了解AES加密是什么,以及几种加密模式的区别。之后才是编程。具体的编...

信息安全:OpenSSL之AES加密简单示例

AES      即高级加密标准,典型AES的基本操作是把128比特明文在128比特密钥的作用下加密成128比特密文。 函数      在openssl/openssl-1.0.1c/crypto/a...

密码学(一)——AES前端和后端的加解密以及对接

最早系统学习密码学的知识是在软考过程中,当时也是半瓶子醋晃悠,我记得最近技术分享中也分享过一些相关的知识,可惜也没有细细分析,老大说要在数据在B/S传输过程中要加密,所以自己就先研究的AES前端和后端...

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

续前几天的一篇博文 openssl之aes加密(源码分析 AES_encrypt 与 AES_cbc_encrypt ,加密模式) 现在利用AES的加密接口,进行加密解密编程以及接口封装。关于开...

C语言编程实现使用AES对文件进行加密

#include #include #include #include int main(int argc,char* argv[]) {   if(argc      printf("Usa...

OpenSSL提供了AES加解密算法的API

OpenSSL提供了AES加解密算法的API const char *AES_options(void); AES算法状态,是全部支持或者是部分支持。 返回值:“aes(full)” 或...

OPENSSL库的使用-AES篇

一、AES算法简介         密码学中的高级加密标准(Advanced Encryption Standard,AES),又称 Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)