技术标签: PKCS7Padding CBC openssl AES加密 C语言学习 base64编码
最近学习对接平台 需要用到 AES BASE64 加密对接接口
非常少的资料
而且满足不了需要或者有bug,譬如无偏移,base解码超位数输出不正常等
最后整理出如标题所示的结果
希望能帮助到有需要的朋友 也给自己往后回顾用
使用前需要安装openssl库
使用方法:
<./aes 数据> <例子:./aes test> <注意:有空格会被当成多个参数>
功能介绍:
1.对数据进行PKCS7Padding填充
2.进行AES CBC 加密 数据块128bit 秘钥32位(256bit)
3.对加密数据进行base4编码
关于openssl:
编译命令:gcc aes.c -o aes -lssl -lcrypto
自行搜索安装openssl库的方法
测试验证网站:
http://tool.chacuo.net/cryptaes
CBC pkcs7padding 128 E10ADC3949BA59ABBE56E056F20F883E E10ADC3949BA59AB base64 utf-8
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "openssl/pem.h"
#include "openssl/aes.h"
// #include "openssl/bio.h"
// #include "openssl/evp.h"
#define KEY_BLOCK_BIT 33
#define IV_BLOCK_BIT 17
/*
这个是你自己写的一个十六字节的秘钥,aes加密解密都用这同一个
命令:find /usr/include/ -name *.h | xargs grep 'AES_BLOCK_SIZE'
结果:/usr/include/openssl/aes.h:# define AES_BLOCK_SIZE 16
//256下 key为秘钥32 iv为偏移16
*/
unsigned char key[KEY_BLOCK_BIT] = "E10ADC3949BA59ABBE56E056F20F883E"; ///usr/include/openssl/aes.h:# define AES_BLOCK_SIZE 16
unsigned char iv[IV_BLOCK_BIT] = "E10ADC3949BA59AB";
#define AES_BITS 10240
#define MSG_LEN 10240
/**********************************************************
函数名:getlen
参数:char *str --字符串地址
返回值:int --字符串长度
说明:输入字符串地址获取字符串长度
***********************************************************/
int getlen(char *str) {
int i = 0;
while (str[i] != '\0') {
i++;
}
return i;
}
/**********************************************************
函数名:PKCS7Padding
参数:unsigned char *str --字符串地址
返回值:int --正向测试填充后的字符串长度
说明:对初始数据进行PKCS7Padding填充
***********************************************************/
int PKCS7Padding(unsigned char *str)
{
int remain, i;
int len=getlen(str);
remain = 16 - len%16;
//printf("remain = %d\n",remain);
for(i=0; i<remain; i++)
{
str[len+i] = remain;
//printf("str[len+i]= %d\n",str[len+i]);
}
str[len+i] = '\0';
return len + remain;
}
/**********************************************************
函数名:DePKCS7Padding
参数:unsigned char *p --字符串地址
返回值:int --反填充个数
说明:对明文进行PKCS7Padding填充反填充(去除后面的填充乱码)
***********************************************************/
int DePKCS7Padding(unsigned char *str)
{
int remain,i;
while (*str != '\0'){str++;} //定位到\0
str--;
remain = *str;//读取填充的个数
//printf("remain = %d\n",remain);
//定位到最前面的填充数
for(i=0;i<remain;i++){str--;}
str++;
*str = '\0';//截断
return remain;
}
/**********************************************************
函数名:aes_encrypt
参数:char* str_in --输入字符串地址
参数:char* out --输出字符串地址
参数:char* key --秘钥key 32位
参数:char* iv --偏移key 16位
返回值:int --0失败 1成功
说明:输入"明文"字符串地址 输出ase加密后的"密文"的字符串(乱码不可读)到地址
***********************************************************/
int aes_encrypt(char* str_in, char* str_out,char *key, char *iv)
{
//检测是否有 输入 KEY 输入 有其1为NULL则退出
if (!str_in || !key || !str_out) return 0;
//抽取数据
char aes_encode_temp[1024];
strcpy(aes_encode_temp,str_in);
//加密的初始化向量 (偏移量)
unsigned char iv_temp[IV_BLOCK_BIT];
strcpy(iv_temp,iv);
//进行PCK7填充 获取填充后长度
int len = PKCS7Padding((unsigned char*)aes_encode_temp);
//printf("PKCS7Padding str : %s\n",aes_encode_temp); //打印填充后的数据
//通过自己的秘钥获得一个aes秘钥以供下面加密使用
AES_KEY aes;
if (AES_set_encrypt_key((unsigned char*)key, 256, &aes) < 0)//256表示32位字符秘钥
{
return 0;
}
//加密接口,使用之前获得的aes秘钥
AES_cbc_encrypt((unsigned char*)aes_encode_temp, (unsigned char*)str_out, len, &aes, iv_temp, AES_ENCRYPT);
return 1;
}
/**********************************************************
函数名:aes_decrypt
参数:char* str_in --输入字符串地址
参数:char* str_out --输出字符串地址
参数:char* key --秘钥key 32位
参数:char* iv --偏移key 16位
返回值:int --0失败 1成功
说明:输入"密文"字符串地址 输出ase解密后的"明文"后的字符串(乱码不可读)到地址
***********************************************************/
int aes_decrypt(char* str_in, char* str_out,char* key,char* iv)
{
if (!str_in || !key || ! str_out) return 0;
//这个也是加密解密同一个确保十六字节里面的内容加密解密一样
unsigned char iv_temp[IV_BLOCK_BIT];
strcpy(iv_temp,iv);
//通过自己的秘钥获得一个aes秘钥以供下面解密使用,128表示16字节
AES_KEY aes;
if (AES_set_decrypt_key((unsigned char*)key, 256, &aes) < 0)//成功返回0
{
return 0;
}
char aes_encode_temp[1024];
strcpy(aes_encode_temp,str_in);
int len = getlen(aes_encode_temp);
//这边是解密接口,使用之前获得的aes秘钥
AES_cbc_encrypt((unsigned char*)aes_encode_temp, (unsigned char*) str_out, len, &aes, iv_temp, AES_DECRYPT);
DePKCS7Padding(str_out);
return 1;
}
/**********************************************************
函数名:base64_encode
参数:char* in_str --输入字符串地址
参数:char* out_str --输出字符串地址
返回值:int --0失败 成功返回编号的字节数
说明:对in_str进行base64编码 输出到out_str
***********************************************************/
int base64_encode(char *in_str, char *out_str)
{
int in_len = getlen(in_str);
BIO *b64 = NULL, *bio = NULL;
BUF_MEM *bptr = NULL;
size_t size = 0;
if (in_str == NULL || out_str == NULL)
return 0;
b64 = BIO_new(BIO_f_base64());
bio = BIO_new(BIO_s_mem());
bio = BIO_push(b64, bio);
BIO_write(bio, in_str, in_len);
BIO_flush(bio);
BIO_get_mem_ptr(bio, &bptr);
memcpy(out_str, bptr->data, bptr->length);
out_str[bptr->length] = '\0';
size = bptr->length;
BIO_free_all(bio);
return size;
}
/**********************************************************
函数名:base64Decode
参数:char* in_str --输入字符串地址
参数:char* out_str --输出字符串地址
返回值:int --0
说明:对str_in进行base64编码 输出到out_str
***********************************************************/
int base64Decode(char *in_str, char *out_str)
{
int length =getlen(in_str);
BIO *b64 = NULL;
BIO *bmem = NULL;
/* char *buffer = (char *)malloc(length);
memset(buffer, 0, length);*/
b64 = BIO_new(BIO_f_base64());
/* if (!newLine) {
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
}*/
bmem = BIO_new_mem_buf(in_str, length);
bmem = BIO_push(b64, bmem);
BIO_read(bmem, out_str, length);
BIO_free_all(bmem);
//strcpy(out_str,buffer);
return 0;
}
/**********************************************************
函数名:main
使用方法:
./aes 数据 例子:./aes test
***********************************************************/
int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("<./aes 数据> <例子:./aes test> <注意:有空格会被当成多个参数>\n");
return 0;
} else
{
printf("-------------------------------------------------------\n");
printf("原始数据:\n%s\n", argv[1]);
printf("秘钥:\n%s\n",key);
printf("偏移量:\n%s\n",iv);
}
printf("------------------------正向测试-----------------------------\n");
//aes加密
printf("-------------------------------------------------------\n");
char aes_encode_out[1024];
bzero(aes_encode_out, 1024);
aes_encrypt(argv[1], aes_encode_out,key, iv);
printf("加密-密文:\n%s\n", aes_encode_out); //打印密文
printf("-------------------------------------------------------\n");
//base64加密
char base64_encode_out[1024] = {0};
bzero(base64_encode_out, 1024);
base64_encode(aes_encode_out, base64_encode_out);
printf("编码-64:\n%s\n", base64_encode_out);
printf("-------------------------------------------------------\n");
printf("------------------------逆向测试-----------------------------\n");
//base64解密
char base64_decode_out[1024] = {0};
bzero(base64_decode_out, 1024);
base64Decode(base64_encode_out, base64_decode_out);
printf("解码-64:\n%s\n", base64_decode_out);
printf("-------------------------------------------------------\n");
//aes解密
char aes_decode_out[1024] = {0};
bzero(aes_decode_out, 1024);
aes_decrypt(base64_decode_out, aes_decode_out,key,iv);
printf("解密-明文:\n%s\n", aes_decode_out);
printf("-------------------------------------------------------\n");
return 0;
}
网站对比通过测试。
拉格朗日乘数法 要找函数z=f(x,y)z=f(x,y)在附加条件φ(x,y)=0φ(x,y)=0下的可能极值点,可以先做拉格朗日函数:L(x,y)=f(x,y)+λφ(x,y)L(x,y) = f(x,y)+λφ(x,y)其中λλ为参数。求其对x与y的一阶偏导数,并使之为零,然后与约束函数联立起来:⎧⎩⎨⎪⎪fx(x,y)+λφx(x,y)=0,fy(x,y)+λφy(x,y)=0,φ(x,y
tensorflow2.1显存限制1.tensorflow v1使用如下用法opts = tf.GPUOptions(per_process_gpu_memory_fraction=0.5)sess = tf.Session(config=tf.ConfigProto(gpu_options=opts))2.tensorflow v2.0α版本使用如下用法tensorflow.con...
春晚红包史堪称互联网公司宕机血泪史,再强的高并发能力在海内外超过 10 亿人的观看规模面前都显得那么脆弱。在互联网人的固有印象里,春晚活动是 BAT 三家轮番坐庄的技术盛事,毕竟只有具备足够的用户体量,才可能有足够的技术能力支撑起春晚级别的高并发流量。今年除夕,作为 BAT 以外第一家扛起春晚战旗的互联网公司,快手在今年的春晚红包活动中,红包互动总量达到 639 亿次,创春晚史上最大的视频点赞纪录...
现实生产环境中,一些大表免不了需要进行拆分,那么这里我们介绍一下Greenplum对大表的处理方法一般我们表都是堆表,按行存储的,Greenplum支持列存储,并且支持数据压缩如果当你的表大到一个度,那么就需要进行逻辑上的拆分,将一张大表拆分为多张小表,这样可以提升相关表操作的效率,一般我们的行存储在返回多列的效率上比较高,所以一般OLTP都是使用行存储,列存储更适合用于统计的相关
生命周期先看网上这张经典图AMS -&gt; ApplicationThread -&gt; 通过ActivityThread H handler切到主线程,handleLaunchActivity会完成OnCreate,onStart,onResume的调用每个生命周期的意义先来了解下每个生命周期的意义 名字 意义 Activity状态 备注...
前端代码<div class="layui-upload"> <button type="button" class="layui-btn" id="test1">上传图片</button> <div class="layui-upload-list"> <img class="layui-upload-img" id="demo1" width="200px" height="200px"> &
JVM-G1垃圾收集器和ZGC收集器G1收集器(-XX:+UseG1GC)Region 分区G1 过程Young GCMixed GC特点G1的垃圾回收分类参数设置优化建议G1收集器(-XX:+UseG1GC)G1 (Garbage-First)是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器. 以极高概率满足GC停顿时间要求的同时,还具备高吞吐量性能特征.Region 分区G1将Java堆划分为多个大小相等的独立区域(Region),JVM目标是不超过2048个Region
linux c检测网线热插拔(netlink)2016-02-19 09:37 本站整理 浏览(14) #include #include #include #include #include #include #include #include #include #include #include #define
总是感觉暑假留校刚刚开始,想想已经两个周了呢生活: 老天开眼这周终于下雨了T.T…没有上周那么炎热,鸭鸭晚上总算是可以睡好觉了,橘宝也乖乖的~依旧是盒饭,miamiaaaa..最开心的是大家一起订外卖的那天,蛋包饭迟迟不来,饿到炸裂又订了汉堡粽子等小吃,刚订完,蛋包饭就来了哈哈哈哈哈…不得不说刘嘉辉同学推荐的蛋包饭真的很好次,吃完蛋包饭又吃汉堡,真的是留校以来吃的最好的一顿午餐惹.还有就是不知道怎
1.padding testinput = tf.placeholder(tf.float32, shape=(1,2, 2,1))simpleconv=slim.conv2d(input,1,[3,3],stride = 1,activation_fn = None,scope = 'simpleconv3')sess.run(tf.global_variables_init...
1、id(obj) 用于获取对象的内存地址name = 'alex'print(id(name)) #2398210474200li = [1,2,3]print(id(li)) #23982113095122、obj1 is obj2 比较判断两个对象是否相同,id做为判断因素 obj1 == obj2 用来比较...
Linux 管理员手册(8)--备份 http://www.lelew.com/ 2004-05-10 13:05:14 硬件不肯定是可靠的 软件肯定是不可靠的 人不肯定是不可靠的 而自然肯定是可靠的 本张说明为什么、如何、何时要做备份,及如何回存备份的东西。 备份的重要 数据是有价值的。重新产生它需要你花费时间和努力,并且要花费金钱或至少伤心和眼泪,有时