如何每次从文件读取16字节存入数组并逐块加密写入输出文件
逐16字节文件加密的正确实现
原代码的核心问题
- 错误处理不到位:文件打开失败后没有终止函数,后续对空指针操作会直接崩溃。
- 未处理末尾不足16字节的块:原循环只读取完整的16字节块,剩余字节会被直接丢弃。
- 悬空指针风险:如果
shift_encrypt返回的是函数内局部数组的指针,fwrite会写入无效内存(局部变量在函数返回后会被销毁)。 - 资源泄漏:没有关闭输入文件流
input_stream,会导致系统资源占用。
修正后的完整实现
#include <stdio.h> #include <string.h> #define MAX_PATH_LEN 256 #define CIPHER_BLOCK_SIZE 16 // 调整shift_encrypt为传入输出缓冲区,避免返回局部指针 void shift_encrypt(const char *plaintext, const char *password, char *ciphertext) { // 这里替换为你的实际加密逻辑,示例为简单异或加密 for (int i = 0; i < CIPHER_BLOCK_SIZE; i++) { ciphertext[i] = plaintext[i] ^ password[i % strlen(password)]; } } void encryption(char filename[MAX_PATH_LEN], char password[CIPHER_BLOCK_SIZE + 1]) { char output[256]; snprintf(output, sizeof(output), "%s.ecb", filename); FILE *output_stream = fopen(output, "wb"); if (output_stream == NULL) { perror(output); return; // 打开失败直接终止函数 } FILE *input_stream = fopen(filename, "rb"); if (input_stream == NULL) { perror(filename); fclose(output_stream); // 先关闭已打开的输出流,避免泄漏 return; } char plaintext[CIPHER_BLOCK_SIZE]; char ciphertext[CIPHER_BLOCK_SIZE]; size_t bytes_read; // 循环读取,每次最多读16字节,返回实际读取的字节数 while ((bytes_read = fread(plaintext, 1, CIPHER_BLOCK_SIZE, input_stream)) > 0) { // 处理不足16字节的块:按PKCS#7标准填充(可根据加密算法调整) if (bytes_read < CIPHER_BLOCK_SIZE) { int pad_len = CIPHER_BLOCK_SIZE - bytes_read; memset(plaintext + bytes_read, pad_len, pad_len); } // 加密到预先分配的ciphertext缓冲区 shift_encrypt(plaintext, password, ciphertext); // 写入完整的16字节加密块 fwrite(ciphertext, 1, CIPHER_BLOCK_SIZE, output_stream); } // 关闭所有文件流,释放资源 fclose(input_stream); fclose(output_stream); }
关键细节说明
- 读取逻辑调整:用
fread(plaintext, 1, CIPHER_BLOCK_SIZE, ...)代替原写法,这样能准确获取实际读取的字节数,不会漏掉末尾的不完整块。 - 填充机制:块加密算法通常要求输入块大小固定,示例中用PKCS#7填充(填充值等于需要填充的字节数),解密时需要对应移除填充。
- 加密函数安全:让
shift_encrypt使用外部传入的缓冲区存储加密结果,彻底避免局部指针悬空问题。 - 资源管理:无论成功失败,都确保打开的文件流被关闭,防止资源泄漏。
内容的提问来源于stack exchange,提问作者FreeAntiVirus
相关产品推荐
相关产品推荐

