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;
}
相关推荐
虾..3 小时前
Linux 软硬链接和动静态库
linux·运维·服务器
Evan芙3 小时前
Linux常见的日志服务管理的常见日志服务
linux·运维·服务器
晨晖24 小时前
单链表逆转,c语言
c语言·数据结构·算法
hkhkhkhkh1235 小时前
Linux设备节点基础知识
linux·服务器·驱动开发
HZero.chen6 小时前
Linux字符串处理
linux·string
张童瑶6 小时前
Linux SSH隧道代理转发及多层转发
linux·运维·ssh
汪汪队立大功1236 小时前
什么是SELinux
linux
石小千6 小时前
Linux安装OpenProject
linux·运维
柏木乃一6 小时前
进程(2)进程概念与基本操作
linux·服务器·开发语言·性能优化·shell·进程
Lime-30906 小时前
制作Ubuntu 24.04-GPU服务器测试系统盘
linux·运维·ubuntu