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;
}
相关推荐
zwhSunday3 小时前
线程概念、操作
linux·线程
_zwy4 小时前
【Linux权限】—— 于虚拟殿堂,轻拨密钥启华章
linux·运维·c++·深度学习·神经网络
huazi994 小时前
C语言编译过程全面解析
c语言·开发语言
半夏云流4 小时前
CMake常用命令指南(CMakeList.txt)
linux·makefile·cmake
鲁子狄5 小时前
[笔记] 极狐GitLab实例 : 手动备份步骤总结
linux·运维·笔记·ubuntu·centos·gitlab
马浩同学5 小时前
【ESP32】ESP-IDF开发 | WiFi开发 | UDP用户数据报协议 + UDP客户端和服务器例程
c语言·单片机·mcu·网络协议·udp
Xam_d_LM5 小时前
【Linux】列出所有连接的 WiFi 网络的密码
linux·服务器·网络
水饺编程6 小时前
简易CPU设计入门:控制总线的剩余信号(四)
linux·嵌入式硬件·fpga开发·硬件工程
bst@微胖子7 小时前
Linux查看服务器的内外网地址
linux