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;
}
相关推荐
唐青枫42 分钟前
别再只会用 cron:Linux systemd Timer 定时任务实战详解
linux
AlfredZhao2 天前
生产环境里,为什么不建议把普通端口直接暴露到公网?
linux·https·443·80
戴为沐3 天前
Linux内存扩容指南
linux
zylyehuo3 天前
Linux 彻底且安全地删除文件
linux
用户805533698034 天前
主线 U-Boot 上 RK3506:和闭源 rkbin 拔河的三个隐性契约
linux·嵌入式
用户034095297914 天前
linux fcitx 5 雾凇拼音 设置在中文输入法下仍然输入英文标点
linux
Web3探索者6 天前
可视化服务器管理和传统命令行区别是什么?新手教程:Linux 运维到底该用图形界面还是 SSH 命令行?
linux·ssh
zylyehuo6 天前
Linux系统中网线与USB网络共享冲突
linux
Sokach10157 天前
Linux Shell 脚本从零到能用:一个新手的一天学习总结
linux
AlfredZhao8 天前
Docker 容器时区不对,`timedatectl` 不存在怎么办?
linux·timezone