基于OpenSSL的AES加密(C/C++)

环境

操作系统:WSL2-Ubuntu22.04

加密库:OpenSSL,Base64

在线AES计算网站:SSLeye

代码中需要用到OpenSSL和Base64,可以根据上述链接获取



简介

高级加密标准(Advanced Encryption Standard,AES),是一种对称加密方式。AES支持三种加密方式:AES128,AES192,AES256,AES128标识密钥长度为128bit,AES128运算速度最快,AES256安全性最佳,三种方式的本质区别是加密轮数不同。



模式

一共有4种加密模式,即ECB、CBC、CFB、OFB,本文仅讲解最常见的ECB、CBC模式,有机会更新后续两种。

ECB模式:

优点:1.简单;2.有利于并行计算;3.误差不会被传送
缺点: 1.不能隐藏明文的模式(例如加密一张图片,虽然看不到原图,但是可能看到其轮廓);2.可能对明文进行主动攻击

CBC模式:

优点:1.不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准
缺点:1.不利于并行计算;2.误差传递;3.需要初始化向量IV



API简介

生成加/解密的密钥

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:密钥,必须16、24或32Bytes

bits:密钥长度,128、192或256bit

key:密钥指针




ECB加/解密,每次执行一个块,一个块为16Bytes,明文不足一个块的需要进行补位

void AES_ecb_encrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key, const int enc);

in:明文指针,长度不足一个块16Bytes的需要进行补位

out:密文,长度为一个块16Bytes

key:密钥指针

enc:AES_ENCRYPT或AES_DECRYPT




CBC加/解密,可以加密任意长度的明文,但是密文长度必须为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);

in:明文指针

out:密文指针

length:明文实际长度(不足一个块16Bytes会自动补0),但是密文的长度应该是补0后长度,例如length=8,那么为密文分配的空间应该为16

key:密钥指针

ivec:初始化向量,必须为16字节且可读写。每个块运算完之后会生成新的向量传给下一个块运算,所以加密完成后此值会改变,解密时应该重新赋值。

enc:AES_ENCRYPT或AES_DECRYPT


ECB加/解密DEMO

#include 
#include 
#include 
#include "base64.h"

int main(void)
{
    unsigned char aes_in[16] = "123456789abcdef";
    unsigned char aes_out[16];
    unsigned char b64_out[1024] = {0};
    AES_KEY encrypt_key, decrypt_key;

/****************************加密****************************/
    // 生成加密密钥  必须128bit/16BYTE
    AES_set_encrypt_key("1234567890123456", 128, &encrypt_key);

    // 加密 一次执行一个块即16BYTE
    AES_ecb_encrypt(aes_in, aes_out, &encrypt_key, AES_ENCRYPT);

    // 以base64编码形式打印
    base64_encode(aes_out, 16, b64_out);
    printf("%s\r\n", b64_out);
    // ahBLMYUa/tgH+sxQNzZxyw==

/****************************解密****************************/
    memset(aes_in, 0, 16);

    // 生成解密密钥  必须128bit/16BYTE
    AES_set_decrypt_key("1234567890123456", 128, &decrypt_key);

    // 解密 一次执行一个块即16BYTE
    AES_ecb_encrypt(aes_out, aes_in, &decrypt_key, AES_DECRYPT);

    printf("%s\r\n", aes_in);
    // 123456789abcdef
}



CBC加/解密DEMO

#include 
#include 
#include 
#include "base64.h"

int main(void)
{
    unsigned char ivec[16] = "1234567890123456";
    unsigned char aes_in[20] = "1234567890123456789";
    unsigned char aes_out[32];
    unsigned char b64_out[1024] = {0};
    AES_KEY encrypt_key, decrypt_key;

/****************************加密****************************/
    // 生成加密密钥  必须128bit/16BYTE
    AES_set_encrypt_key("1234567890123456", 128, &encrypt_key);

    // 加密
    AES_cbc_encrypt(aes_in, aes_out, 20,  &encrypt_key, ivec, AES_ENCRYPT);

    // 以base64编码形式打印
    base64_encode(aes_out, 32, b64_out);
    printf("%s\r\n", b64_out);
    // 2LWYSMdnDJSym1TSN54uer0JwNlyHlQcjnl1uQ7ofOw=

/****************************解密****************************/
    memset(aes_in, 0, 20);

    // 生成解密密钥  必须128bit/16BYTE
    AES_set_decrypt_key("1234567890123456", 128, &decrypt_key);

    memcpy(ivec, "1234567890123456", 16);

    // 解密
    AES_cbc_encrypt(aes_out, aes_in, 20,  &decrypt_key, ivec, AES_DECRYPT);
    printf("%s\r\n", aes_in);
    // 1234567890123456789
}

你可能感兴趣的:(物联网,SSL,C语言,AES,AES128,ssl)