AES-128-ECB-zeropadding填充加解密openssl标准库使用 linux C语言

背景:openwrt环境下使用openssl标准库进行aes-128-ecb-zerospadding加解密。

一、接口及头文件

openssl的aes头文件

#include 

1.AES_ecb_encrypt接口原型

简介:openssl标准库将加解密函数统一封装成AES_ecb_encrypt函数,通过第四个参数来选择调用加密程序或者解密程序,需要注意的是第三个参数需要通过AES_set_decrypt_key、AES_set_encrypt_key来生成。ECB模式相较于CBC模式少一个输入参数iv向量,整体调用大同小异。

参数名称 释义
in 加解密接口输入
out 加解密接口输出
key AES_KEY类型密钥需要通过接口生成(后面有介绍)
enc 常量AES_ENCRYPT表示用于加密、AES_DECRYPT表示用于解密
void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,
                     const AES_KEY *key, const int enc)
{

    assert(in && out && key);
    assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));

    if (AES_ENCRYPT == enc)
        AES_encrypt(in, out, key);
    else
        AES_decrypt(in, out, key);
}

2. AES_set_decrypt_key、AES_set_encrypt_key

简介:用于生成AES_ecb_encrypt加解密所需要的KEY,注意加解密的密钥使用对应函数生成。

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);
参数名称 释义
userKey 输入密钥
bits 密钥长度的比特位数即字节数*8,128,192,256三个参数可供选择
key AES_KEY类型输出密钥用于AES_ecb_encrypt加密
返回值 0:表示成功,-1:输入参数1为空,-2:bit位输入错误

一、封装填充函数

说明:运用标准库的加密函数和密钥生成函数就可以加密解密了,但是对于上述加解密接口一次之只能处理16个字节长度的数据,如果需要加密的明文小于等于十六个字节,则可以直接使用上述的加解密接口,当明文长度大于16个字节时则需要将明文分组加密再将密文拼接起来。所以对于输入数据的字节长度要求为16的整倍数,当分组后不足16字节的一组用0x00填充,即为zeros padding,这里介绍zeros padding的填充方式,其他填充方式网上介绍很多这里就不赘述。

1. 封装AES-128-ECB-zeropadding 加密接口

int AES_ECB128_Encrypt(const unsigned char *in, unsigned char *out, unsigned char key, int input_len) {

    AES_KEY key;
	int i;
	int ret = 0;
	int round = 0;
	int rest = 0;
	int in_len = 0;
	unsigned char in_tmp[1024] = {0};
	unsigned char out_tmp[1024] = {0};
	unsigned char zero[16] = {0};
	//DEBUG_INFO() 是自定义打印接口函数,使用中可以修改为对应的打印函数
	ret = AES_set_encrypt_key(key, 128, &key);
    if ( ret < 0) {
    	DEBUG_INFO("ret =  %d,%s\n", ret, "get the Encrypt aes key error");
    	return false;
    } else {
    	DEBUG_INFO("%s\n", "get the Encrypt key successful");
    }
	
	in_len = input_len;
	memset(zero, 0x00, 16);
	if (in_len <= 16) {
		AES_ecb_encrypt(in, out, &key, AES_ENCRYPT);
	} else{
		rest = in_len%16;
		round = (in_len - rest)/16;
		memcpy(in_tmp, in, 1024); 
		strcat(in_tmp, zero);
		memcpy(in, in_tmp, (round+1) * 16); //zero padding
		for (i = 0; i < round + 1; i++) { //分组循环加密并且拼接
			memcpy(in_tmp, in + 16 * i, 16);
			AES_ecb_encrypt(in_tmp, out_tmp, &key, AES_ENCRYPT);
			memcpy(out + 16 * i, out_tmp, 16);
			memset(in_tmp, 0, 1024);
			memset(out_tmp, 0, 1024);
		}
	}
    return true;
}
参数名称 释义
in 加密接口输入
out 加密接口输出
key 输入密钥key
input_len 输入明文数据长度

2. 封装AES-128-ECB-zeropadding 解密接口

int AES_ECB128_Decrypt(const unsigned char *in, unsigned char *out, unsigned char key,int input_len) {

    AES_KEY key;
	int i;
	int j;
	int cnt;
	int ret = 0;
	int rest = 0;
	int round = 0;
	int in_len = 0;
	int out_len=0;
	unsigned char in_tmp[1024] = {0};
	unsigned char out_tmp[1024] = {0};
	
	ret = AES_set_decrypt_key(dct_conf.servers[server_index].mqtt_conf.aes_key, 128, &key);
    if ( ret < 0) {
    	DEBUG_INFO("ret =  %d,%s\n", ret, "get the Decrypt aes key error");
    	return false;
    } else {
    	DEBUG_INFO("%s\n", "get the Decrypt key successful");
    }
    
	in_len = input_len;
	
	if (in_len == 16) {
		AES_ecb_encrypt(in, out, &key, AES_DECRYPT);
	} else {
		round = in_len/16;

		for (i = 0; i < round; i++) { //分组解密
			if (i == round -1) {
				memcpy(in_tmp, in + 16 * i, 16);
				AES_ecb_encrypt(in_tmp, out_tmp, &key, AES_DECRYPT);
				for (j = 0; j < 16; j++) {  //去掉填充在末尾的零(事实上这边的算法需要改进可以评论出你的想法噢哈哈哈)
					if (out_tmp[j] == '\0') {
						ret = 16 - j;
						break;
					}
				}
				memcpy(out + 16 * i, out_tmp, 16);
			} else {
				memcpy(in_tmp, in + 16 * i, 16);
				AES_ecb_encrypt(in_tmp, out_tmp, &key, AES_DECRYPT);
				memcpy(out + 16 * i, out_tmp, 16);
				memset(in_tmp, 0, 1024);
				memset(out_tmp, 0, 1024);
			}
		}
	}
参数名称 释义
in 加密接口输入
out 加密接口输出
key 输入密钥key
input_len 输入明文数据长度

你可能感兴趣的:(linux,安全,arm,c语言,算法)