[代码实战] c语言基于openssl实现的AES算法ECB模式加密代码解读

1 篇文章 0 订阅

1、先贴出代码样例,再解读。代码中依赖openssl库使用AES的ECB(电码本)模式进行加密和解密。
2、电码本模式将明文分为若干个大小相同的块,对每个块进行单独的加密。不同的块加密结果没有关联,每个块可以独立解密。ECB模式的优点是简单,缺点是会被重放攻击。代码如下:

#include <openssl/aes.h>
// PKCS#7填充添加
void pkcs7_padding_add(unsigned char *in, int in_len, int block_size) {
    int padding_len = block_size - (in_len % block_size);
    for (int i = in_len; i < in_len + padding_len; i++) {
        in[i] = (unsigned char)padding_len;
    }
}

// PKCS#7填充删除
int pkcs7_padding_remove(unsigned char *in, int in_len, int block_size) {
    int padding_len = in[in_len - 1];
    if (padding_len < 1 || padding_len > block_size) {
        return in_len; 
    }
    for (int i = 1; i <= padding_len; i++) { // 检查填充位的值是否和填充长度相等,不等就返回实际长度。
        if(in[in_len - i] != padding_len) { 
            return in_len; 
        }
    }
    return in_len - padding_len; 
}

// 变长字符串,要带填充分块加密
int aes_ecb_pad_encode(const unsigned char* in, const unsigned int in_len, const unsigned char* aes_key, const unsigned int key_len, unsigned char* out, const unsigned int out_men_len)
{
    if (in==NULL || in_len<=0 || aes_key==NULL || key_len<=0 || out==NULL || out_men_len<=0)
        return -1;
    // 计算填充后的大小
    int block_size = AES_BLOCK_SIZE; // AES块的大小
    int enc_slack_space = in_len % block_size;
    int enc_spaces = in_len + (block_size - enc_slack_space);
    if (enc_spaces > out_men_len)
    {
        return -2;
    }
    unsigned char enc_in[enc_spaces];
    memset(enc_in, 0, sizeof(enc_in));
    memcpy(enc_in, in, in_len);
    pkcs7_padding_add(enc_in, in_len, block_size);
    
    // 加密
    AES_KEY enc_key;
    AES_set_encrypt_key(aes_key, 128, &enc_key);
    for (int i = 0; i < enc_spaces; i += block_size) {
        AES_encrypt(enc_in + i, out + i, &enc_key);
    }
    return enc_spaces; //如果成功,返回密文长度
}

int aes_ecb_pad_decode(const unsigned char* in, const unsigned int in_len, const unsigned char* aes_key, const unsigned int key_len, unsigned char* out, const unsigned int out_men_len)
{
    if (in==NULL || in_len<=0 || aes_key==NULL || key_len<=0 || out==NULL || out_men_len<=0)
        return -1;
    unsigned char dec_out[1024];
    memset(dec_out, 0, sizeof(dec_out));

    int enc_spaces = in_len;
    int block_size = AES_BLOCK_SIZE;
    if (enc_spaces%block_size != 0)
    {   //密文不是block大小的整数倍
        return -2;
    }
    if (enc_spaces-block_size>out_men_len)
    {   //输出的明文内存太小
        return -3;
    }
    AES_KEY dec_key;
    AES_set_decrypt_key(aes_key, 128, &dec_key);
    for (int i = 0; i < enc_spaces; i += block_size) {
        AES_decrypt(in + i, out + i, &dec_key);
    }
    int dec_message_len = pkcs7_padding_remove(out, enc_spaces, block_size);
    return dec_message_len; // 如果成功,返回明文长度
}

3、代码说明:
(1)加密函数 aes_ecb_pad_encode :
一个加密块的大小为16字节。调用 pkcs7_padding_add,这是填充函数。不管明文满不满足16字节的块大小,都需要进行填充。不是16的整数倍时,要填充补齐16字节。如果是16的整数倍,则需要填充一个整块。被填充的字节的值就是填充的长度。
AES_set_encrypt_key(aes_key, 128, &enc_key);是设置AES加密算法密钥的函数。
AES_encrypt(enc_in + i, out + i, &enc_key);这里进行加密。上述代码的调用可以看出该函数输入和输出是一个字节一个字节的处理的。enc_spaces是填充后的长度。
(2)解密函数 aes_ecb_pad_decode:
在函数AES_set_decrypt_key调用之前,都是参数检查,块长度计算等。
调用 AES_decrypt(in + i, out + i, &dec_key), 它也是一个字符一个字符的计算。
调用 pkcs7_padding_remove(out, enc_spaces, block_size),去除填充,便得到明文。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_44764006

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值