该代码有一个简单的任务,即解密/加密文件并将密码写入新文件,该文件非常适合4GB以下的文件。任何大于4GB(2 ^ 32Bytes)的文件,将产生4GB(2 ^ 32 Bytes)的文件,而不是输入文件的大小。我已经尝试了64Bit扩展(fseeko64,fopen64等),它不会有所作为! 除了我有一个标准程序外,似乎没有这种类型的问题,因为它一次将所有数据写入文件中,而不是成块地写入。我对两个程序使用了相同的功能。如果相关的话,我使用g ++进行了编译
任何帮助将不胜感激。 谢谢
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int i, a, pwlen, response;
char passwd[64];
__uint8_t pwhash[512];
__uint8_t *message;
int tmp;
char *filename, *sourcefilename;
long int len;
int chunk_length, round, chunkqu, rest;
long int file_length_counter;
int progress;
// functions init
void password();
void encrypt();
void decrypt();
int main(int argc, char **argv) {
// set chunksize
chunk_length = 4096*64;
// check arguments,
if (!argv[1]) {
printf("Usage: <inputfile> <mode(x/o)> <sourcefile>\nRead documentation for more info\n");
return 0;
}
if (!argv[2]) {
printf("No mode specified. Exiting\n");
return 0;
}
if (*argv[2] != 'x' && *argv[2] != 'o') {
printf("Bad argument. Exiting...\n");
return 0;
}
FILE *fileptr2;
fileptr2 = fopen(argv[3], "rb");
if (fileptr2 != NULL) {
printf("Source file already exists\n");
return 0;
}
sourcefilename = argv[3];
// open file in read mode to verify its existance
FILE *fileptr1;
fileptr1 = fopen(argv[1], "rb");
if (!fileptr1) {
printf("File does not exist or is not accessible\n");
return 0;
}
filename = argv[1];
fseek(fileptr1, 0, SEEK_END);
len = ftell(fileptr1);
fseek(fileptr1, 0, SEEK_SET);
// request password and hash it
password();
// allocate memory for chunk_length
message = (__uint8_t*)malloc(chunk_length);
if (message == NULL) {
printf("Failed to allocate required memory\n This may be caused by insufficient RAM\n");
return 0;
}
// open output file
fileptr2 = fopen(sourcefilename,"wb");
// find out chunk quantity and length as well as the leftover "chunk"
file_length_counter =0;
round =0;
while (1) {
round++;
file_length_counter += chunk_length;
if (file_length_counter>=len) {
rest=chunk_length-(file_length_counter-len);
chunkqu=round;
break;
}
}
// main routine
printf("Progress:\n ");
for (round=1; round<=chunkqu; round++) {
progress = round*100/chunkqu;
printf("\r%d\%%", progress);
fseek(fileptr1, (round-1)*chunk_length, SEEK_SET);
fread(message, 1, chunk_length, fileptr1);
if (*argv[2] == 'x') {encrypt();}
if (*argv[2] == 'o') {decrypt();}
if (round==chunkqu) {
fseek(fileptr2, (round-1)*chunk_length, SEEK_SET);
fwrite(message, 1, rest, fileptr2);
}
else {
fseek(fileptr2, (round-1)*chunk_length, SEEK_SET);
fwrite(message, 1, chunk_length, fileptr2);
}
}
// cleanup and exit
printf("\n");
fclose(fileptr1);
fclose(fileptr2);
free (message);
return 0;
}
void password() {
int count, h1, h2, h3, h4, s1, s2, s3, s4, r1, r2;
count = 0;
int tmphash[512];
// request password
do {
if (count != 0) {
printf("Password must exceed 9 characters!\n");
}
printf("Enter Passphrase:\n");
fgets(passwd, 64, stdin);
count++;
} while (strlen(passwd) <= 9);
pwlen = strlen(passwd) -1;
// initialise variables
s1 = 0;
s2 = 0;
s3 = 0;
s4 = 0;
// hash algorithm
for (i=0; i<pwlen; i++) {
h1 = passwd[i];
h2 = passwd[pwlen-i];
h3 = passwd[pwlen];
h4 = i<<2;
for (a=0; a<512; a++) {
if (i==0) {tmphash[a] = 0;}
s1 += i&a;
s1 += h1^h4;
s2 += a^i;
s3 += h2>>i%3;
s4 += h3<<i%5;
r1 = s1^s2;
r2 = s3^s4;
r1 += r1<<i;
r2 += r2>>5;
tmphash[a] +=r1&r2;
tmphash[a] %= 256;
}
}
for (i=0; i<512; i++) {
pwhash[i] = tmphash[i];
}
}
void encrypt() {
for (i=0; i<chunk_length; i++) {
tmp = message[i];
tmp += pwhash[i%512];
tmp %= 256;
message[i] = tmp;
}
}
void decrypt() {
for (i=0; i<chunk_length; i++) {
tmp = message[i];
tmp += 256;
tmp -= pwhash[i%512];
tmp %= 256;
message[i] = tmp;
}
}