First, familiarity with your stream cipher is probably warranted. Blowfish encrypts/decrypts using a block size of 64 bits; not bytes. So long as you understand the 64 "bytes" you're referring to is your requirement and not Blowfishes, and that Blowfish only requires 8-byte blocks.
That said, a loop passing over a file with a size that is a multiple of the algorithm block size, extracting decrypted data one 64 byte frame at a time is certainly doable.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <openssl/blowfish.h>
int main(int argc, char *argv[])
{
if (argc < 2)
return EXIT_FAILURE;
FILE * fp = fopen(argv[1], "rb");
if (fp == NULL)
{
perror(argv[1]);
return EXIT_FAILURE;
}
// your key bytes would be here (obviously).
unsigned char key[16] = "1234567890123456";
int key_len = sizeof(key)-1;
// setup the key schedule.
BF_KEY bf_key;
BF_set_key(&bf_key, key_len, key);
// and setup the initialization vector. normally the IV is
// randomly generated when encrypting, then stored as the
// lead 8 bytes of ciphertext output. this assumes you're
// iv is static (all zeros) similar to SSH
unsigned char iv[8] = {0};
int n = 0;
// finally, begin reading the data in chunks of 64 bytes
// sending it through the blowfish algorithm
unsigned char source[64];
unsigned char dest[64];
while (fread(source, sizeof(source), 1, fp) == 1)
{
BF_cfb64_encrypt(source, dest, sizeof(dest), &bf_key, iv, &n, BF_DECRYPT);
// do something with your dest[] plaintext block
}
fclose(fp);
return 0;
}
That sample is fairly trivial, but it brings up some things about symmetric block algorithms and padding that you may not be considering (or perhaps you have, and it simply has nothing to do with this question).
Symmetric block algorithms like Blowfish operate on a block size. In the case of Blowfish that block size is 64 bits (8 bytes). This means that the encryption/decryption operation always happens in 64-bit-sized chunks. If if you were using the lower level openssl apis you would have to encrypt (and decrypt) the data in blocks no larger than that. The higher-level APIs (such as BF_cfb64_encrypt
) are designed to allow "stream mode" meaning you can submit your data in larger chunks, so long as they're sized to be a multiple of the block size. and you retain the iv
and n
values between chained successive calls to the API.
Finally, I started writing this rather long diatribe about symmetric block algorithms and padding modes, but realized this isn't really appropriate to this question, so I can only suggest you research into them. I've a suspicion you'll need to at some point.