C语言使用openSSL库AES模块实现加密功能详解
本文实例讲述了C语言使用openSSL库AES模块实现加密功能。分享给大家供大家参考,具体如下:
概述
在密码学里面一共有3中分类:
1.对称加密/解密
对称加密比较常见的有DES/AES。加密方和解密方都持有相同的密钥。对称的意思就是加密和解密都是用相同的密钥。
2.非对称加密/解密
常见的加密算法DSA/RSA。如果做过GooglePay的话,应该不会陌生。非对称意味着加密和解密使用的密钥不是相同的。这种应用的场合是需要保持发起方的权威性,比如Google中一次支付行为,只能Google通过私钥来加密产出来,但是大家都能通过公钥来认证这个是真的。打个更加浅显的比方:私钥可以理解成美联储的印钞机,公钥可以理解成在民间无数的美元验钞机。
还有一个场合也是https使用证书方式登录的时候,也是使用的双向的非对称加密模式来做的。
3.离散
这种只能被称为验签,而不是加密。因为这类算法只能一个方向(将输入数据离散到某个特定的数字,反向解密是无法做到的。)。最常见的算法就是MD5。在写php的时候大量的使用这种验签来做认证。他可以将字符串离散成32byte的16进制的数字。
本次使用AESCBC方式来加密。CBC模式加密是SSL的通讯标准,所以在做游戏的时候经常会使用到。openSSL的基本用法可以参考这个
两个细节
这种加密的需要了解下面两个细节:
1.加密的内存块一般按照16字节(这个也可以调整)对齐;当原始内存块没有对齐字节数的时候,需要填充;
2.加密解密不会引发内存的膨胀或者缩小;
最近在使用Python,Java,c#都去看过AES的接口,最轻松的是c#,java。当使用C来写,才能明显感受到在这些操作过程中,有多少次内存的分配,多少的内存拼接。啥事都有成本,封装良好的语言损失掉的效率可能来自于这些便利。
准备知识
函数接口
intAES_set_encrypt_key(constunsignedchar*userKey,constintbits,AES_KEY*key); intAES_set_decrypt_key(constunsignedchar*userKey,constintbits,AES_KEY*key); //设置加密key AES_KEYaes; AES_set_encrypt_key(key,128,&aes);//这里填写的128是bit位,128bit=(128/8)bytes=16bytes,这个换算和32bit对应int为内存指针的原理一样。 //初始化自己的key charkey[16]; //加密函数 voidAES_cbc_encrypt(constunsignedchar*in,unsignedchar*out,size_tlength,constAES_KEY*key,unsignedchar*ivec,constintenc); #defineAES_BLOCK_SIZE16//aes.h71lines #defineAES_ENCRYPT1//aes.h63lines #defineAES_DECRYPT0//aes.h64lines //定义一个加密的初始化向量 unsignedchariv[AES_BLOCK_SIZE]; //加密 AES_cbc_encrypt(raw_buf,encrypt_buf,buf_size,&aes,iv,AES_ENCRYPT); //解密 AES_cbc_encrypt(raw_buf,encrypt_buf,buf_size,&aes,iv,AES_DECRYPT);
字串转换
//16进制的字串转换成16byte存储起来 //hexstringtobyteinc constcharhexstring[]="deadbeef10203040b00b1e50",*pos=hexstring; unsignedcharval[12]; size_tcount=0; /*WARNING:nosanitizationorerror-checkingwhatsoever*/ for(count=0;countpadding算法
char*raw_buf=...; intraw_size=...; char*final_buf=NULL; intpidding_size=AES_BLOCK_SIZE-(raw_size%AES_BLOCK_SIZE); inti; final_buf=(char*)malloc(raw_size+pidding_size); if(pidding_size!=0){ memcpy(final_buf,raw_buf,raw_size); for(i=raw_size;i<(raw_size+pidding_size);i++){ //zeropadding算法: final_buf[i]=0; or //PKCS5Padding算法 final_buf[i]=pading; } }完整的代码
c语言代码
//main.c #include#include #include #include #include unsignedchar*str2hex(char*str){ unsignedchar*ret=NULL; intstr_len=strlen(str); inti=0; assert((str_len%2)==0); ret=(char*)malloc(str_len/2); for(i=0;i 编译scons脚本:
#SConstruct importglob env=Environment() env["CPPPATH"]=['/usr/include/openssl'] env['LIBPATH']=['/home/abel/lib/openssl-1.0.2f'] env['CPPDEFINES']=['LINUX','_DEBUG'] env['CCFLAGS']='-g-std=gnu99' env['LIBS']=['m','crypto','dl'] env.Program(target="./test_aes",source=(glob.glob('./*.c')))输出结果:
:!./test_aes ------------------raw_buf 6C69666527732061 207374727567676C 65 ------------------after_padding_buf 6C69666527732061 207374727567676C 6500000000000000 0000000000000000 ------------------encrypt_buf DB6328C52C6A3F1B FD4BC547944E249D D2154CF26B3B1DC0 E7D27BD61E7860EA ------------------decrypt_buf 6C69666527732061 207374727567676C 6500000000000000 0000000000000000总结
代码中还是有很多地方都是直接malloc内存出来,这些点都能扣得更加细。在每次加密调用的时候IV内存将会改变。
PS:关于加密解密感兴趣的朋友还可以参考本站在线工具:
文字在线加密解密工具(包含AES、DES、RC4等):
http://tools.jb51.net/password/txt_encodeMD5在线加密工具:
http://tools.jb51.net/password/CreateMD5Password在线散列/哈希算法加密工具:
http://tools.jb51.net/password/hash_encrypt在线MD5/hash/SHA-1/SHA-2/SHA-256/SHA-512/SHA-3/RIPEMD-160加密工具:
http://tools.jb51.net/password/hash_md5_sha在线sha1/sha224/sha256/sha384/sha512加密工具:
http://tools.jb51.net/password/sha_encode希望本文所述对大家C语言程序设计有所帮助。