c++ openssl 使用ECC算法对大文件进行非对称加密和解密示例代码,包括生成密钥并写入文件
时间: 2024-03-06 08:47:39 浏览: 249
以下是使用 OpenSSL 的 ECC 算法对大文件进行非对称加密和解密的示例代码,包括生成密钥并写入文件:
```c++
#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include <openssl/ecdsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#define KEY_SIZE 256 // ECC 密钥长度,单位为位
// 生成 ECC 密钥对并写入文件
void generate_ecc_keypair(const char* private_key_file, const char* public_key_file)
{
EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
if (ec_key == NULL)
{
printf("Failed to create EC key\n");
return;
}
if (EC_KEY_generate_key(ec_key) != 1)
{
printf("Failed to generate EC key\n");
EC_KEY_free(ec_key);
return;
}
// 写入私钥文件
FILE* fp_private = fopen(private_key_file, "wb");
if (fp_private == NULL)
{
printf("Failed to open private key file\n");
EC_KEY_free(ec_key);
return;
}
PEM_write_ECPrivateKey(fp_private, ec_key, NULL, NULL, 0, NULL, NULL);
fclose(fp_private);
// 写入公钥文件
FILE* fp_public = fopen(public_key_file, "wb");
if (fp_public == NULL)
{
printf("Failed to open public key file\n");
EC_KEY_free(ec_key);
return;
}
PEM_write_EC_PUBKEY(fp_public, ec_key);
fclose(fp_public);
EC_KEY_free(ec_key);
}
// 从文件中读取 ECC 密钥
EC_KEY* read_ecc_key(const char* key_file)
{
FILE* fp = fopen(key_file, "rb");
if (fp == NULL)
{
printf("Failed to open key file\n");
return NULL;
}
EC_KEY* ec_key = PEM_read_ECPrivateKey(fp, NULL, NULL, NULL);
if (ec_key == NULL)
{
printf("Failed to read EC private key\n");
EC_KEY_free(ec_key);
fclose(fp);
return NULL;
}
fclose(fp);
return ec_key;
}
// 加密文件
int encrypt_file(const char* input_file, const char* output_file, EC_KEY* ec_key)
{
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
{
printf("Failed to create cipher context\n");
return 0;
}
// 获取 ECC 密钥长度,单位为字节
int key_len = (EC_GROUP_get_degree(EC_KEY_get0_group(ec_key)) + 7) / 8;
if (key_len <= 0)
{
printf("Failed to get ECC key length\n");
EVP_CIPHER_CTX_free(ctx);
return 0;
}
// 分配密钥和 IV
unsigned char* key = (unsigned char*)malloc(key_len);
unsigned char* iv = (unsigned char*)malloc(16);
if (key == NULL || iv == NULL)
{
printf("Failed to allocate memory\n");
free(key);
free(iv);
EVP_CIPHER_CTX_free(ctx);
return 0;
}
// 生成随机密钥和 IV
if (RAND_bytes(key, key_len) != 1 || RAND_bytes(iv, 16) != 1)
{
printf("Failed to generate random bytes\n");
free(key);
free(iv);
EVP_CIPHER_CTX_free(ctx);
return 0;
}
// 加载 ECC 公钥
EVP_PKEY* public_key = EVP_PKEY_new();
if (public_key == NULL)
{
printf("Failed to create EVP_PKEY\n");
free(key);
free(iv);
EVP_CIPHER_CTX_free(ctx);
return 0;
}
if (EVP_PKEY_set1_EC_KEY(public_key, ec_key) != 1)
{
printf("Failed to set EVP_PKEY\n");
free(key);
free(iv);
EVP_PKEY_free(public_key);
EVP_CIPHER_CTX_free(ctx);
return 0;
}
// 初始化加密操作
if (EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv) != 1)
{
printf("Failed to initialize encryption\n");
free(key);
free(iv);
EVP_PKEY_free(public_key);
EVP_CIPHER_CTX_free(ctx);
return 0;
}
// 读取输入文件和写入输出文件
FILE* fp_in = fopen(input_file, "rb");
FILE* fp_out = fopen(output_file, "wb");
if (fp_in == NULL || fp_out == NULL)
{
printf("Failed to open file\n");
free(key);
free(iv);
EVP_PKEY_free(public_key);
EVP_CIPHER_CTX_free(ctx);
fclose(fp_in);
fclose(fp_out);
return 0;
}
// 写入密钥和 IV
fwrite(key, 1, key_len, fp_out);
fwrite(iv, 1, 16, fp_out);
// 加密文件
unsigned char in_buf[512];
unsigned char out_buf[512 + EVP_CIPHER_CTX_block_size(ctx)];
int in_len, out_len;
while ((in_len = fread(in_buf, 1, sizeof(in_buf), fp_in)) > 0)
{
if (EVP_EncryptUpdate(ctx, out_buf, &out_len, in_buf, in_len) != 1)
{
printf("Failed to encrypt file\n");
free(key);
free(iv);
EVP_PKEY_free(public_key);
EVP_CIPHER_CTX_free(ctx);
fclose(fp_in);
fclose(fp_out);
return 0;
}
fwrite(out_buf, 1, out_len, fp_out);
}
if (EVP_EncryptFinal_ex(ctx, out_buf, &out_len) != 1)
{
printf("Failed to finalize encryption\n");
free(key);
free(iv);
EVP_PKEY_free(public_key);
EVP_CIPHER_CTX_free(ctx);
fclose(fp_in);
fclose(fp_out);
return 0;
}
fwrite(out_buf, 1, out_len, fp_out);
// 释放资源
free(key);
free(iv);
EVP_PKEY_free(public_key);
EVP_CIPHER_CTX_free(ctx);
fclose(fp_in);
fclose(fp_out);
return 1;
}
// 解密文件
int decrypt_file(const char* input_file, const char* output_file, EC_KEY* ec_key)
{
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
{
printf("Failed to create cipher context\n");
return 0;
}
// 获取 ECC 密钥长度,单位为字节
int key_len = (EC_GROUP_get_degree(EC_KEY_get0_group(ec_key)) + 7) / 8;
if (key_len <= 0)
{
printf("Failed to get ECC key length\n");
EVP_CIPHER_CTX_free(ctx);
return 0;
}
// 分配密钥和 IV
unsigned char* key = (unsigned char*)malloc(key_len);
unsigned char* iv = (unsigned char*)malloc(16);
if (key == NULL || iv == NULL)
{
printf("Failed to allocate memory\n");
free(key);
free(iv);
EVP_CIPHER_CTX_free(ctx);
return 0;
}
// 读取密钥和 IV
FILE* fp_in = fopen(input_file, "rb");
if (fp_in == NULL)
{
printf("Failed to open input file\n");
free(key);
free(iv);
EVP_CIPHER_CTX_free(ctx);
return 0;
}
fread(key, 1, key_len, fp_in);
fread(iv, 1, 16, fp_in);
// 加载 ECC 私钥
EVP_PKEY* private_key = EVP_PKEY_new();
if (private_key == NULL)
{
printf("Failed to create EVP_PKEY\n");
free(key);
free(iv);
EVP_CIPHER_CTX_free(ctx);
fclose(fp_in);
return 0;
}
if (EVP_PKEY_set1_EC_KEY(private_key, ec_key) != 1)
{
printf("Failed to set EVP_PKEY\n");
free(key);
free(iv);
EVP_PKEY_free(private_key);
EVP_CIPHER_CTX_free(ctx);
fclose(fp_in);
return 0;
}
// 初始化解密操作
if (EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv) != 1)
{
printf("Failed to initialize decryption\n");
free(key);
free(iv);
EVP_PKEY_free(private_key);
EVP_CIPHER_CTX_free(ctx);
fclose(fp_in);
return 0;
}
// 读取输入文件和写入输出文件
FILE* fp_out = fopen(output_file, "wb");
if (fp_out == NULL)
{
printf("Failed to open output file\n");
free(key);
free(iv);
EVP_PKEY_free(private_key);
EVP_CIPHER_CTX_free(ctx);
fclose(fp_in);
fclose(fp_out);
return 0;
}
// 解密文件
unsigned char in_buf[512 + EVP_CIPHER_CTX_block_size(ctx)];
unsigned char out_buf[512];
int in_len, out_len;
fseek(fp_in, key_len + 16, SEEK_SET);
while ((in_len = fread(in_buf, 1, sizeof(in_buf), fp_in)) > 0)
{
if (EVP_DecryptUpdate(ctx, out_buf, &out_len, in_buf, in_len) != 1)
{
printf("Failed to decrypt file\n");
free(key);
free(iv);
EVP_PKEY_free(private_key);
EVP_CIPHER_CTX_free(ctx);
fclose(fp_in);
fclose(fp_out);
return 0;
}
fwrite(out_buf, 1, out_len, fp_out);
}
if (EVP_DecryptFinal_ex(ctx, out_buf, &out_len) != 1)
{
printf("Failed to finalize decryption\n");
free(key);
free(iv);
EVP_PKEY_free(private_key);
EVP_CIPHER_CTX_free(ctx);
fclose(fp_in);
fclose(fp_out);
return 0;
}
fwrite(out_buf, 1, out_len, fp_out);
// 释放资源
free(key);
free(iv);
EVP_PKEY_free(private_key);
EVP_CIPHER_CTX_free(ctx);
fclose(fp_in);
fclose(fp_out);
return 1;
}
```
使用示例:
```c++
int main()
{
// 生成 ECC 密钥对并写入文件
generate_ecc_keypair("ecc_private.pem", "ecc_public.pem");
// 加载 ECC 密钥
EC_KEY* ec_key = read_ecc_key("ecc_private.pem");
if (ec_key == NULL)
{
printf("Failed to read ECC key\n");
return 0;
}
// 加密文件
if (encrypt_file("input.txt", "encrypted.bin", ec_key) != 1)
{
printf("Failed to encrypt file\n");
EC_KEY_free(ec_key);
return 0;
}
// 解密文件
if (decrypt_file("encrypted.bin", "decrypted.txt", ec_key) != 1)
{
printf("Failed to decrypt file\n");
EC_KEY_free(ec_key);
return 0;
}
// 释放资源
EC_KEY_free(ec_key);
return 1;
}
```
阅读全文