Linux C openssl aes-128-cbc demo

openssl 各版本下载

bash 复制代码
https://openssl-library.org/source/old/index.html
cpp 复制代码
#include <stdio.h>
#include <string.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/evp.h>

#define AES_KEY_BITS 128
#define GCM_IV_SIZE 12
#define GCM_TAG_SIZE 16

int aes_cbc_encrypt(const unsigned char *plaintext,
        int plaintext_len, const unsigned char *aad,
        int aad_len, const unsigned char *key,
        unsigned char *ciphertext, unsigned char *tag)
{
    EVP_CIPHER_CTX *ctx = NULL;
    int len = 0;
    int ciphertext_len = 0;

    // 创建并初始化 EVP_CIPHER_CTX 对象
    ctx = EVP_CIPHER_CTX_new();
    EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, NULL, NULL);

    // 设置加密密钥
    EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL);

    // 加密明文数据
    if (EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len) > 0)
    {
        ciphertext_len = len;
    }
    else
    {
        printf("Error! \n");
    }

    // 结束加密过程,并生成认证标签
    EVP_EncryptFinal_ex(ctx, ciphertext + len, &len);
    ciphertext_len += len;
    EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, GCM_TAG_SIZE, tag);

    // 释放EVP_CIPHER_CTX对象
    EVP_CIPHER_CTX_free(ctx);

    return ciphertext_len;
}

int aes_cbc_decrypt(const unsigned char *ciphertext,
        int ciphertext_len, const unsigned char *aad,
        int aad_len, const unsigned char *tag,
        const unsigned char *key, unsigned char *plaintext)
{
    EVP_CIPHER_CTX *ctx;
    int len;
    int plaintext_len;
    int ret;

    // 创建并初始化EVP_CIPHER_CTX对象
    ctx = EVP_CIPHER_CTX_new();
    EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, NULL, NULL);

    // 设置解密密钥
    EVP_DecryptInit_ex(ctx, NULL, NULL, key, NULL);

    // 设置附加的认证数据(可选)
    EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len);

    // 解密密文数据
    EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len);
    plaintext_len = len;

    // 设置接收到的认证标签
    EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, GCM_TAG_SIZE, (void *)tag);

    // 结束解密过程,如果认证失败则返回错误
    ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
    plaintext_len += len;

    // 释放EVP_CIPHER_CTX对象
    EVP_CIPHER_CTX_free(ctx);

    return ret == 1 ? plaintext_len : -1;
}

int main()
{
    unsigned char key[AES_KEY_BITS / 8];
    unsigned char iv[GCM_IV_SIZE];
    unsigned char plaintext[] = "Hello, AES 128!";
    unsigned char ciphertext[sizeof(plaintext)];
    unsigned char decryptedtext[sizeof(plaintext)];
    unsigned char tag[GCM_TAG_SIZE];

    // 生成密钥
    if (RAND_bytes(key, sizeof(key)) != 1)
    {
        printf("error  generating AES key.\n");
        return 1;
    }

    printf("key: \n");
    for (int i = 0; i < AES_KEY_BITS / 8; i++)
    {
        printf("0x%0x  ", key[i]);
    }
    printf("\n");

    // 生成初始化向量
    if (RAND_bytes(iv, sizeof(iv)) != 1)
    {
        printf("Error generating GCM IV.\n");
        return 1;
    }
    printf("\n");


    // 加密明文数据
    int ciphertext_len = aes_cbc_encrypt(plaintext, sizeof(plaintext) - 1, NULL, 0, key, ciphertext, tag);

    printf("line: %d  ciphertext_len: %d Ciphertext: ", __LINE__, ciphertext_len);
    for (int i = 0; i < ciphertext_len; i++)
    {
        printf("%02x", ciphertext[i]);
    }
    printf("\n");

    printf("line: %d  Tag: ", __LINE__);
    for (int i = 0; i < GCM_TAG_SIZE; i++)
    {
        printf("%02x", tag[i]);
    }
    printf("\n");

    // 解密密文数据
    int decryptedtext_len = aes_cbc_decrypt(ciphertext, ciphertext_len, NULL, 0, tag, key, decryptedtext);

    decryptedtext[decryptedtext_len] = '\0';

    printf("line: %d  Decrypted text: %s\n", __LINE__, decryptedtext);

    return 0;
}

编译:

bash 复制代码
gcc main.c -o main -lssl -lcrypto

使用:

复制代码
./main

读取文件到内存

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <openssl/bio.h>
#include <sys/stat.h>
#include <sys/types.h>

// 修改这,要预算大于文件内容
#define LENGTH 4096

#define DEBUG_LOG(fmt, args...)                                           \
    do                                                                    \
    {                                                                     \
        printf("[debug] %s:%d %s() :", __FILE__, __LINE__, __FUNCTION__); \
        printf(fmt, ##args);                                              \
        printf("\n");                                                     \
    } while (0)

/**
 * @brief
 *
 * @param file_name 文件名称
 * @param pBuf 传出的文件内容指针
 * @param bufLen 传出文件内容的长度
 * @return int
 *      
 */
int readFileBuf(const char *file_name, unsigned char **pBuf, int *bufLen)
{
    FILE *fp = NULL;
    int numRead = 0;
    int fileSize = 0;
    struct stat fileStat;

    if (NULL == file_name)
    {
        DEBUG_LOG("input parameter is NULL");
        return -1;
    }

    memset(&fileStat, 0, sizeof(fileStat));
    if (stat(file_name, &fileStat) < 0)
    {
        DEBUG_LOG("stat is error!\n");
        return -1;
    }
    else
    {
        DEBUG_LOG("size: 0x%X\n", fileStat.st_size);
    }

    // 创建跟文件大小一样的 buf
    fileSize = fileStat.st_size;
    *pBuf = (unsigned char *)malloc(fileSize);

    if (NULL == *pBuf)
    {
        DEBUG_LOG("malloc failed\n");
        return -1;
    }

    if ((fp = fopen(file_name, "r")) == NULL)
    {
        DEBUG_LOG("open %s failed.\n", file_name);
        return -1;
    }

    numRead = fread(*pBuf, sizeof(unsigned char), fileSize, fp);
    if (numRead < fileSize)
    {
        DEBUG_LOG("read file data failed.\n");
        fclose(fp);
        free(pBuf);
        return -1;
    }
    else
    {

        DEBUG_LOG("read file data success. fileSize: %d\n", fileSize);
        *bufLen = fileSize;
    }

    fclose(fp);

    return fileSize;
}

int main()
{
    int numRead = 0;
    unsigned char *pBuf = NULL;
    // 目标文件
    const char *fileName = "./openssl-3.3.2.tar.gz";
    int length = 0;

	// 注意传进的 pBuf 是二重指针
    numRead = readFileBuf(fileName, &pBuf, &length);
    if (numRead > 0)
    {
        DEBUG_LOG("length = %d\n", length);
    }

    // BIO_dump_fp(stdout, pBuf, length);

    free(pBuf);

    return 0;
}
相关推荐
RuoZoe7 小时前
重塑WPF辉煌?基于DirectX 12的现代.NET UI框架Jalium
c语言
chlk1232 天前
Linux文件权限完全图解:读懂 ls -l 和 chmod 755 背后的秘密
linux·操作系统
舒一笑2 天前
Ubuntu系统安装CodeX出现问题
linux·后端
改一下配置文件2 天前
Ubuntu24.04安装NVIDIA驱动完整指南(含Secure Boot解决方案)
linux
深紫色的三北六号2 天前
Linux 服务器磁盘扩容与目录迁移:rsync + bind mount 实现服务无感迁移(无需修改配置)
linux·扩容·服务迁移
SudosuBash2 天前
[CS:APP 3e] 关于对 第 12 章 读/写者的一点思考和题解 (作业 12.19,12.20,12.21)
linux·并发·操作系统(os)
哈基咪怎么可能是AI3 天前
为什么我就想要「线性历史 + Signed Commits」GitHub 却把我当猴耍 🤬🎙️
linux·github
十日十行3 天前
Linux和window共享文件夹
linux
木心月转码ing4 天前
WSL+Cpp开发环境配置
linux
祈安_4 天前
C语言内存函数
c语言·后端