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;
}
相关推荐
stormsha6 分钟前
Linux中su与sudo命令的区别:权限管理的关键差异解析
linux·运维·服务器·鸿蒙系统·ux·batch命令
草莓熊Lotso21 分钟前
【数据结构初阶】--算法复杂度的深度解析
c语言·开发语言·数据结构·经验分享·笔记·其他·算法
KyollBM27 分钟前
【CF】Day75——CF (Div. 2) B (数学 + 贪心) + CF 882 (Div. 2) C (01Trie | 区间最大异或和)
c语言·c++·算法
筏.k1 小时前
grep、wc 与管道符快速上手指南
linux
Johny_Zhao1 小时前
华为MAAS、阿里云PAI、亚马逊AWS SageMaker、微软Azure ML各大模型深度分析对比
linux·人工智能·ai·信息安全·云计算·系统运维
CodeOfCC1 小时前
c语言 封装跨平台线程头文件
linux·c语言·windows
科文小白狼1 小时前
Linux下VSCode开发环境配置(LSP)
linux·vscode·里氏替换原则·lsp
momo卡2 小时前
MinGW-w64的安装详细步骤(c_c++的编译器gcc、g++的windows版,win10、win11真实可用)
c语言·c++·windows
jugt3 小时前
CentOS 7.9安装Nginx1.24.0时报 checking for LuaJIT 2.x ... not found
linux·运维·centos
超的小宝贝3 小时前
数据结构算法(C语言)
c语言·数据结构·算法