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

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

一、接口及头文件

openssl的aes头文件

#include <openssl/aes.h>

1.AES_ecb_encrypt接口原型

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

参数名称释义
in加解密接口输入
out加解密接口输出
keyAES_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三个参数可供选择
keyAES_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输入明文数据长度
AES-128 CMAC(Cipher Mode with Additional Authentication Code)是一种基于AES(高级加密标准)的消息认证码计算方法,用于验证数据的完整性和来源。在C语言中实现AES-128 CMAC需要以下步骤: 1. **准备库**:首先确保你已经包含了相应的AES加密库,如OpenSSL、Crypto++或自定义的AES模块。 ```c #include <openssl/aes.h> ``` 2. **生成随机初始化向量(IV)**:CMAC使用一个特定的IV,通常是在加密过程中生成并保密的。 3. **设置CMAC函数**:AES-CMAC的计算过程涉及到对AES进行两次操作:一次作为加密,一次作为解密(反向模式)。你需要创建一个`AES_KEY`结构并将其配置为AES-128。 4. **计算CMAC**:定义一个函数,输入数据块、长度以及预设的密钥和IV。使用AES_ECB_encrypt函数(ECB模式下)和AES_decrypt函数来完成计算。 ```c void cmac(const unsigned char *key, const unsigned char *iv, const unsigned char *data, size_t data_len, unsigned char mac[AES_BLOCK_SIZE]) { AES_KEY aes_key; AES_set_encrypt_key(key, 128, &aes_key); // 使用128位密钥 unsigned char input[AES_BLOCK_SIZE + data_len]; memcpy(input, iv, AES_BLOCK_SIZE); memcpy(&input[AES_BLOCK_SIZE], data, data_len); AES_cmac_encrypt(input, mac, &aes_key, NULL, AES_ENCRYPT); // 第一轮加密 AES_cmac_encrypt(mac, mac, &aes_key, NULL, AES_DECRYPT); // 第二轮解密 } ``` 5. **验证**:接收一个MAC和一组数据,再次使用相同的密钥和IV通过上述函数计算MAC,然后比较两者是否一致。 注意:这个例子是一个简化的版本,实际应用中需要考虑错误处理、数据分块和填充等问题,并且一些库可能会提供专门的API来进行更高效和安全的CMAC计算。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值