aes加密字符串 openssl_openssl之aes加密 cbc方式与实现案例

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

#include

#include

#include

#include

#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

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

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;

}

71179237_1.jpg

上图是运行程序的测试结果。可见加密解密已经完成。

这里也能够看出,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_key和AES_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

{

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

{

AES_decrypt((unsigned char*)in, (unsigned char*)out, &aes);

in+=AES_BLOCK_SIZE;

out+=AES_BLOCK_SIZE;

en_len+=AES_BLOCK_SIZE;

}

return 1;

}

71179237_2.jpg

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

开发环境:

我是ubuntu12.04,安装openssl,可以参考下面的链接。

关于编译环境,我使用的是CodeBlocks,也有直接makefile搞定。参考下面的链接。

参考资料:openssl之aes加密(源码分析 AES_encrypt 与 AES_cbc_encrypt ,加密模式)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值