博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C语言利用openSSL库AES模块加密
阅读量:2066 次
发布时间:2019-04-29

本文共 4682 字,大约阅读时间需要 15 分钟。

概述

在密码学里面一共有3中分类:

1.对称加密/解密

对称加密比较常见的有DES/AES。加密方和解密方都持有相同的密钥。对称的意思就是加密和解密都是用相同的密钥。

2.非对称加密/解密

常见的加密算法DSA/RSA。如果做过Google Pay的话,应该不会陌生。非对称意味着加密和解密使用的密钥不是相同的。这种应用的场合是需要保持发起方的权威性,比如Google中一次支付行为,只能Google通过私钥来加密产出来,但是大家都能通过公钥来认证这个是真的。打个更加浅显的比方:私钥可以理解成美联储的印钞机,公钥可以理解成在民间无数的美元验钞机。

还有一个场合也是https使用证书方式登录的时候,也是使用的双向的非对称加密模式来做的。

3.离散

这种只能被称为验签,而不是加密。因为这类算法只能一个方向(将输入数据离散到某个特定的数字,反向解密是无法做到的。)。最常见的算法就是MD5。在写php的时候大量的使用这种验签来做认证。他可以将字符串离散成32byte的16进制的数字。

本次使用AES CBC方式来加密。CBC模式加密是SSL的通讯标准,所以在做游戏的时候经常会使用到。openSSL的基本用法可以

两个细节

这种加密的需要了解下面两个细节:

1.加密的内存块一般按照16字节(这个也可以调整)对齐;当原始内存块没有对齐字节数的时候,需要填充;
2.加密解密不会引发内存的膨胀或者缩小;
最近在使用python,java,c#都去看过AES的接口,最轻松的是c#,java。当使用C来写,才能明显感受到在这些操作过程中,有多少次内存的分配,多少的内存拼接。啥事都有成本,封装良好的语言损失掉的效率可能来自于这些便利。

准备知识

函数接口

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);// 设置加密keyAES_KEY aes;AES_set_encrypt_key(key,128,&aes);// 这里填写的128是bit位,128bit=(128/8)bytes=16bytes,这个换算和32bit对应int为内存指针的原理一样。// 初始化自己的keychar key[16];// 加密函数void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,                     size_t length, const AES_KEY *key,                     unsigned char *ivec, const int enc);# define AES_BLOCK_SIZE 16 // aes.h 71 lines# define AES_ENCRYPT     1 // aes.h 63 lines# define AES_DECRYPT     0 // aes.h 64 lines// 定义一个加密的初始化向量unsigned char iv[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存储起来// hex string to byte in c    const char hexstring[] = "deadbeef10203040b00b1e50", *pos = hexstring;    unsigned char val[12];    size_t count = 0;     /* WARNING: no sanitization or error-checking whatsoever */    for(count = 0; count < sizeof(val)/sizeof(val[0]); count++) {        sscanf(pos, "%2hhx", &val[count]);        pos += 2;    }    printf("0x");    for(count = 0; count < sizeof(val)/sizeof(val[0]); count++)        printf("%02x", val[count]);    printf("\n");

padding算法

char *raw_buf = ...;    int raw_size = ...;    char *final_buf = NULL;    int pidding_size = AES_BLOCK_SIZE - (raw_size % AES_BLOCK_SIZE);    int i;    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++ ) {            // zero padding算法:            final_buf[i] = 0;            or            // PKCS5Padding算法            final_buf[i] = pading;        }    }

完整的代码

c语言代码

// main.c#include 
#include
#include
#include
#include
unsigned char* str2hex(char *str) { unsigned char *ret = NULL; int str_len = strlen(str); int i = 0; assert((str_len%2) == 0); ret = (char *)malloc(str_len/2); for (i =0;i < str_len; i = i+2 ) { sscanf(str+i,"%2hhx",&ret[i/2]); } return ret;}char *padding_buf(char *buf,int size, int *final_size) { char *ret = NULL; int pidding_size = AES_BLOCK_SIZE - (size % AES_BLOCK_SIZE); int i; *final_size = size + pidding_size; ret = (char *)malloc(size+pidding_size); memcpy( ret, buf, size); if (pidding_size!=0) { for (i =size;i < (size+pidding_size); i++ ) { ret[i] = 0; } } return ret;}void printf_buff(char *buff,int size) { int i = 0; for (i=0;i

编译scons脚本:

# SConstructimport globenv = 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_buf6C 69 66 65 27 73 20 61 20 73 74 72 75 67 67 6C 65 ------------------after_padding_buf6C 69 66 65 27 73 20 61 20 73 74 72 75 67 67 6C 65 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ------------------encrypt_bufDB 63 28 C5 2C 6A 3F 1B FD 4B C5 47 94 4E 24 9D D2 15 4C F2 6B 3B 1D C0 E7 D2 7B D6 1E 78 60 EA ------------------decrypt_buf6C 69 66 65 27 73 20 61 20 73 74 72 75 67 67 6C 65 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

总结

代码中还是有很多地方都是直接malloc内存出来,这些点都能扣得更加细。在每次加密调用的时候IV内存将会改变。

转载地址:http://sdfmf.baihongyu.com/

你可能感兴趣的文章
Redis学习笔记(四)—— redis的常用命令和五大数据类型的简单使用
查看>>
Win10+VS2015编译libcurl
查看>>
Windows下使用jsoncpp
查看>>
Ubuntu下测试使用Nginx+uWsgi+Django
查看>>
Windows下编译x264
查看>>
visual studio调试内存泄漏工具
查看>>
开源Faac实现PCM编码AAC
查看>>
Windows下wave API 音频采集
查看>>
借船过河:一个据说能看穿你的人性和欲望的心理测试
查看>>
AndroidStudio 导入三方库使用
查看>>
Ubuntu解决gcc编译报错/usr/bin/ld: cannot find -lstdc++
查看>>
解决Ubuntu14.04 - 16.10版本 cheese摄像头灯亮却黑屏问题
查看>>
解决Ubuntu 64bit下使用交叉编译链提示error while loading shared libraries: libz.so.1
查看>>
MFC程序添加console窗口+printf打印输出信息
查看>>
VS生成DLL文件供第三方调用
查看>>
Android Studio color和font设置
查看>>
Python 格式化打印json数据(展开状态)
查看>>
Centos7 安装curl(openssl)和libxml2
查看>>
Centos7 离线安装RabbitMQ,并配置集群
查看>>
Centos7 or Other Linux RPM包查询下载
查看>>