在C中逐块读取二进制文件

Fun_Dan3

我是 C 新手,习惯于 python。但是由于当前世界的情况,我的主计算机被毁坏了,我只剩下 12 年的笔记本电脑。Python 在那里不能很好地工作。

我的目标是创建加密算法。 目前它相当简单,但我稍后会升级它

如何分块读取文件并覆盖其数据?这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef unsigned char byte;

void printa(byte a[]) {
    printf("[");
    for (int i = 0; i < strlen(a); i++) {
        printf("%d", a[i]);
        if (i != strlen(a) - 1) {
            printf(", ");
        };
    };
    printf("]\n");
};

int encrypt(byte data[], byte key[], int keyi) {
    for (int i = 0; i < strlen(data); i++) {
        data[i] += key[keyi];
        keyi = (keyi + 1) * (keyi < strlen(key) - 1); //branchless if (keyi<strlen(key)) {keyi++;} else {keyi=0;};
    };
    return keyi;
};

void encrypt_file(byte filename[], byte key[], int buffer_size) {
    FILE *file;
    byte *buff = calloc(sizeof(byte), buffer_size);
    file = fopen(filename, "rb");
    if (file == NULL) {
        printf("UNABLE TO OPEN FILE\n");
    };
};

int main() {
    encrypt_file("test.txt", "key", 1024);
    return 0;
};

我的文件大小约为 2GB,但我的笔记本电脑内存为 512MB,所以我必须使用分块。

chqrlie

要以块为单位加密文件,您应该使用freadfwrite

keyi要在键的末尾重置键索引,将其与 进行比较strlen(key) - 1可能非常低效,因为strlen()迭代整个字符串以定位空终止符。只需测试是否key[keyi]为空字节。

也不必担心无分支代码:

  • 任何好的编译器都会为简单的测试生成无分支代码if (key[keyi] == '\0') keyi = 0;
  • 分支在现代处理器上并不是一个真正的问题,只要它们可以被一致地预测。

这是修改后的版本:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef unsigned char byte;

int encrypt(byte data[], size_t size, const byte key[], int keyi) {
    for (size_t i = 0; i < size; i++) {
        data[i] ^= key[keyi++];  // involutory encryption (apply twice to decrypt)
        if (key[keyi] == '\0')
            keyi = 0;
    }
    return keyi;
}

int encrypt_file(const char *filename, const char *filename2,
                 const byte key[], size_t buffer_size)
{
    byte *buff = calloc(sizeof(*buff), buffer_size);
    if (buff == NULL) {
        fprintf(stderr, "Cannot allocate memory\n");
        return 1;
    }
    FILE *f1 = fopen(filename, "rb");
    if (f1 == NULL) {
        fprintf(stderr, "Cannot open file %s: %s\n", filename, strerror(errno));
        free(buff);
        return 1;
    }
    FILE *f2 = fopen(filename2, "wb");
    if (f2 == NULL) {
        fprintf(stderr, "Cannot open file %s: %s\n", filename2, strerror(errno));
        fclose(f1);
        free(buff);
        return 1;
    }
    size_t nread;
    int keyi = 0;
    while ((nread = fread(buff, sizeof(*buff), size, f1)) != 0) {
        keyi = encrypt(buff, nread, key, keyi);
        if (fwrite(buff, sizeof(*buff), nread, f2) != nread) {
            fprintf(stderr, "Error writing to file %s: %s\n", filename2, strerror(errno));
            break;
        }
    }
    fclose(f1);
    fclose(f2);
    free(buff);
    return 0;
}

int main() {
    return encrypt_file("test.txt", "test.out", (const byte *)"key", 1024);
}

您可以修改程序以就地加密文件,但请注意,如果进程中断,部分加密的文件将难以恢复。您还应该尝试保留文件修改时间。一种更安全的方法是使用适当的工具对分区进行加密,其中一些工具支持隐藏分区和合理的可否认性。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章