借助DeepSeek调用libchdb中的lz4和sm4函数实现对文件压缩加密

提示词如下:

请编写利用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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值