Question

I am implementing a Feistel cipher of block size 16 bits. I read from an input file into an integer (32bits), encrypt and write to output file.

unsigned int buf1, buf2;
FILE *fin = fopen("input", "r");
FILE *fout = fopen("output", "w");
while(!feof(fin)) {
    fread(&buf1, 4, 1, fin);
    buf2  = encrypt(buf1);
    fwrite(&buf2, 4, 1, fout);
}

The program is almost done. The only problem is that encryption followed by decryption is not the source file. They're almost same but the difference is only in the last bits. My question is what happens if the no of bytes in the file is not a multiple of 4. What will happen to the last call to fread()?

Was it helpful?

Solution

If the number of bytes in the file is not a multiple of 4, the last call to fread() will return 0.

size_t fread(void * restrict ptr, size_t size, size_t nmemb, FILE * restrict stream);
"The fread function returns the number of elements successfully read, which may be less than nmemb if a read error or end-of-file is encountered."

The result value of fread() should be used to detect an incomplete read and EOF. OP code, as is, will read once too often.

Also suggest using uint32_t instead of unsigned int for greater portability and checking `fwrite() results.

uint32_t buf1, buf2;
int cnt;
while((cnt = fread(&buf1, sizeof buf1, 1, fin)) == 1) {
  buf2  = encrypt(buf1);
  if (fwrite(&buf2, sizeof buf2, 1, fout) != 1) {
    Handle_WriteError();
  }
}

OTHER TIPS

You need to know the size of the file you are reading in advance (using stat() or equivalent), read the number of complete blocks available and then handle the residual bytes, if any, as a special case, perhaps by padding. If you don't want ciphertext expansion, then look at block stealing modes of operation, which are available for both ECB and CBC modes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top