提示词如下:
请编写利用LZ4_compressHC函数来压缩文件的代码,并用EVP_sm4_cbc来加密,同时编写解压缩和解密后和原文比较的代码,这些函数都位于libchdb.so,用-lchdb链接。
结果他编出来的程序引用了lz4hc.h和evp.h。还把压缩和加密步骤放在同一个函数,解密和解压放在另一个函数。
于是继续提示:
chdb没有提供lz4hc.h和evp.h,请把用到的函数和结构用extern "C"声明在ext.h源代码里,让main.c包含ext.h,请单独分出来解密、解密、压缩、解压4个函数,以便检查。
输出结果如下:
头文件ext3.h
#ifndef EXT_H
#define EXT_H
#ifdef __cplusplus
extern "C" {
#endif
/* LZ4 配置 */
#define LZ4HC_CLEVEL_MAX 12 // 更高效的压缩级别
#define BUFFER_SIZE (16 * 1024)
#define SM4_KEY_SIZE 16
#define SM4_IV_SIZE 16
#define EVP_MAX_BLOCK_LENGTH (16 * 1024)
/* LZ4 HC 函数 */
typedef struct LZ4HC_CCtx_internal LZ4_streamHC_t;
int LZ4_compress_HC(const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel);
int LZ4_compressBound(int inputSize);
int LZ4_decompress_safe(const char* src, char* dst, int compressedSize, int dstCapacity);
/* SM4 函数 */
typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX;
typedef struct evp_cipher_st EVP_CIPHER;
const EVP_CIPHER* EVP_sm4_cbc(void);
int EVP_EncryptInit_ex(EVP_CIPHER_CTX* ctx, const EVP_CIPHER* cipher, void* impl, const unsigned char* key, const unsigned char* iv);
int EVP_EncryptUpdate(EVP_CIPHER_CTX* ctx, unsigned char* out, int* outl, const unsigned char* in, int inl);
int EVP_EncryptFinal_ex(EVP_CIPHER_CTX* ctx, unsigned char* out, int* outl);
int EVP_DecryptInit_ex(EVP_CIPHER_CTX* ctx, const EVP_CIPHER* cipher, void* impl, const unsigned char* key, const unsigned char* iv);
int EVP_DecryptUpdate(EVP_CIPHER_CTX* ctx, unsigned char* out, int* outl, const unsigned char* in, int inl);
int EVP_DecryptFinal_ex(EVP_CIPHER_CTX* ctx, unsigned char* out, int* outl);
EVP_CIPHER_CTX* EVP_CIPHER_CTX_new(void);
void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX* ctx);
/* 工具函数 */
void handle_errors(const char* msg);
#ifdef __cplusplus
}
#endif
#endif // EXT_H
c实现ops3.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ext3.h"
/* ========== 错误处理 ========== */
void handle_errors(const char* msg) {
fprintf(stderr, "Error: %s\n", msg);
exit(EXIT_FAILURE);
}
/* ========== 压缩函数 ========== */
int compress_data(const char* input_path, const char* compressed_path) {
FILE* fin = fopen(input_path, "rb");
FILE* fout = fopen(compressed_path, "wb");
if (!fin || !fout) handle_errors("File open failed");
unsigned char in_buf[BUFFER_SIZE];
unsigned char cmp_buf[LZ4_compressBound(BUFFER_SIZE)];
int bytes_read, cmp_size;
while ((bytes_read = fread(in_buf, 1, BUFFER_SIZE, fin)) > 0) {
cmp_size = LZ4_compress_HC((const char*)in_buf, (char*)cmp_buf,
bytes_read, sizeof(cmp_buf), LZ4HC_CLEVEL_MAX);
if (cmp_size <= 0) handle_errors("Compression failed");
fwrite(cmp_buf, 1, cmp_size, fout);
}
fclose(fin);
fclose(fout);
return 0;
}
/* ========== 加密函数 ========== */
int encrypt_data(const char* input_path, const char* encrypted_path,
const unsigned char* key, const unsigned char* iv) {
FILE* fin = fopen(input_path, "rb");
FILE* fout = fopen(encrypted_path, "wb");
if (!fin || !fout) handle_errors("File open failed");
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
if (!EVP_EncryptInit_ex(ctx, EVP_sm4_cbc(), NULL, key, iv))
handle_errors("SM4 init failed");
unsigned char in_buf[BUFFER_SIZE], out_buf[BUFFER_SIZE + EVP_MAX_BLOCK_LENGTH];
int bytes_read, enc_size, final_size;
while ((bytes_read = fread(in_buf, 1, BUFFER_SIZE, fin)) > 0) {
if (!EVP_EncryptUpdate(ctx, out_buf, &enc_size, in_buf, bytes_read))
handle_errors("Encryption failed");
fwrite(out_buf, 1, enc_size, fout);
}
if (!EVP_EncryptFinal_ex(ctx, out_buf, &final_size))
handle_errors("Final encryption failed");
fwrite(out_buf, 1, final_size, fout);
EVP_CIPHER_CTX_free(ctx);
fclose(fin);
fclose(fout);
return 0;
}
/* ========== 解密函数 ========== */
int decrypt_data(const char* input_path, const char* decrypted_path,
const unsigned char* key, const unsigned char* iv) {
FILE* fin = fopen(input_path, "rb");
FILE* fout = fopen(decrypted_path, "wb");
if (!fin || !fout) handle_errors("File open failed");
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
if (!EVP_DecryptInit_ex(ctx, EVP_sm4_cbc(), NULL, key, iv))
handle_errors("SM4 init failed");
unsigned char in_buf[BUFFER_SIZE], out_buf[BUFFER_SIZE + EVP_MAX_BLOCK_LENGTH];
int bytes_read, dec_size, final_size;
while ((bytes_read = fread(in_buf, 1, BUFFER_SIZE, fin)) > 0) {
if (!EVP_DecryptUpdate(ctx, out_buf, &dec_size, in_buf, bytes_read))
handle_errors("Decryption failed");
fwrite(out_buf, 1, dec_size, fout);
}
if (!EVP_DecryptFinal_ex(ctx, out_buf, &final_size))
handle_errors("Final decryption failed");
fwrite(out_buf, 1, final_size, fout);
EVP_CIPHER_CTX_free(ctx);
fclose(fin);
fclose(fout);
return 0;
}
/* ========== 解压函数 ========== */
int decompress_data(const char* input_path, const char* decompressed_path) {
FILE* fin = fopen(input_path, "rb");
FILE* fout = fopen(decompressed_path, "wb");
if (!fin || !fout) handle_errors("File open failed");
unsigned char in_buf[BUFFER_SIZE * 2]; // 压缩数据可能需要更多空间
unsigned char out_buf[BUFFER_SIZE];
int bytes_read, decompressed_size;
while ((bytes_read = fread(in_buf, 1, sizeof(in_buf), fin)) > 0) {
decompressed_size = LZ4_decompress_safe((const char*)in_buf,
(char*)out_buf, bytes_read, sizeof(out_buf));
if (decompressed_size < 0) handle_errors("Decompression failed");
fwrite(out_buf, 1, decompressed_size, fout);
}
fclose(fin);
fclose(fout);
return 0;
}
int compare_files(const char* file1, const char* file2) {
FILE* f1 = fopen(file1, "rb");
FILE* f2 = fopen(file2, "rb");
if (!f1 || !f2) return -1;
int result = 0;
char buf1[BUFFER_SIZE], buf2[BUFFER_SIZE];
size_t n1, n2;
do {
n1 = fread(buf1, 1, BUFFER_SIZE, f1);
n2 = fread(buf2, 1, BUFFER_SIZE, f2);
if (n1 != n2 || memcmp(buf1, buf2, n1)) {
result = 1;
break;
}
} while (n1 > 0);
fclose(f1);
fclose(f2);
return result;
}
int main(int argc, char** argv) {
if (argc != 4) {
printf("Usage: %s <input> <encrypted> <decrypted>\n", argv[0]);
return 1;
}
// 测试用密钥和IV(实际应用中应从安全源获取)
unsigned char key[SM4_KEY_SIZE] = "0123456789abcdef";
unsigned char iv[SM4_IV_SIZE] = "1234567890abcdef";
// 临时文件路径
const char* compressed_file = "temp_compressed.bin";
const char* decrypted_file = "temp_decrypted.bin";
// 1. 单独压缩测试
if (compress_data(argv[1], compressed_file)) {
fprintf(stderr, "Compression failed\n");
return 1;
}
printf("Compression successful. Verifying...\n");
// 验证压缩/解压
if (decompress_data(compressed_file, decrypted_file)) {
fprintf(stderr, "Decompression verification failed\n");
return 1;
}
if (compare_files(argv[1], decrypted_file) != 0) {
fprintf(stderr, "Error: Compression/decompression mismatch!\n");
return 1;
}
printf("Compression/decompression verified OK\n");
// 2. 单独加密测试
if (encrypt_data(argv[1], argv[2], key, iv)) {
fprintf(stderr, "Encryption failed\n");
return 1;
}
printf("Encryption successful. Verifying...\n");
// 验证加密/解密
if (decrypt_data(argv[2], argv[3], key, iv)) {
fprintf(stderr, "Decryption failed\n");
return 1;
}
if (compare_files(argv[1], argv[3]) != 0) {
fprintf(stderr, "Error: Encryption/decryption mismatch!\n");
return 1;
}
printf("Encryption/decryption verified OK\n");
// 3. 完整流程测试 (压缩->加密->解密->解压)
printf("Testing full pipeline...\n");
if (compress_data(argv[1], compressed_file) ||
encrypt_data(compressed_file, argv[2], key, iv) ||
decrypt_data(argv[2], decrypted_file, key, iv) ||
decompress_data(decrypted_file, argv[3])) {
fprintf(stderr, "Pipeline failed\n");
return 1;
}
if (compare_files(argv[1], argv[3]) != 0) {
fprintf(stderr, "Error: Full pipeline mismatch!\n");
return 1;
}
printf("Full pipeline verified OK\n");
// 清理临时文件
remove(compressed_file);
remove(decrypted_file);
return 0;
}
编译执行命令行
export LD_LIBRARY_PATH=/par:/usr/local/lib
export LIBRARY_PATH=/par:/usr/local/lib
gcc -o ops3 ops3.c -lchdb -I . -O3
./ops3 ops3.c ops3.lz4.sm4 ops3a.c
Compression successful. Verifying...
Compression/decompression verified OK
Encryption successful. Verifying...
Encryption/decryption verified OK
Testing full pipeline...
Full pipeline verified OK
已知问题,这个代码只能正确处理小于BUFFER_SIZE的文件, 超过这个文件大小就出错,应该是分块压缩的代码有错,下次慢慢改。
./ops3 ops3 ops3a.lz4.sm4 ops3a
Compression successful. Verifying...
Error: Decompression failed