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;
}