Simple encryption/decryption algorithm causing EOF

孤者浪人 提交于 2019-12-24 10:38:56

问题


I was playing with very simple encryption/decryption algorithm like this;

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

#define BUFFESIZE 1024

int main(int argc, char *argv[]) {

    int keylen = 0;
    char *key = argv[1];
    char *buffer = NULL;
    size_t buffersize = 0;
    size_t nbytes = 0;
    size_t nread;
    int i = 0;
    while(*key++ != 0) keylen++;
    key = argv[1];

    do {
        buffersize+=BUFFESIZE;
        buffer = realloc(buffer, buffersize);
        nread = fread(buffer+nbytes, 1, BUFFESIZE, stdin);
        nbytes+=nread;
    } while (nread > 0);

    for(i=0; i<nbytes; i++) {
        putchar(buffer[i] ^ key[i % keylen]);
    }
    return 0;
}

Encyption key is the first command-line argument to the program. I expect that this should get me originial file when encrypted/decrypted with same key. However, I sometimes get only small amount of the file back if I encrypt/decrypt it. My guess is that algorithm adds EOF control character in the middle of file.

How can I get around this problem?

I compiled this using MinGW gcc 4.8.1 on windows XP. If you're interested, you can find a sample input file demonstrating the problem in the edit history of this question.


回答1:


Well, your code works for me on Linux (compiled with GCC 4.8.2), even using your sample input and key. This suggests that the issue is specific to Windows — most likely, that it's caused by stdin and stdout being in text mode by default. (On Linux and other Unix-ish systems, there's usually no difference between text mode and binary mode, so such issues do not show up there.)

To fix it, you will need to set stdin and stdout to binary mode. The standard way of doing this, as of C99, would be:

freopen(NULL, "rb", stdin);
freopen(NULL, "wb", stdout);

but alas, according to the answers in the thread I linked to above, the Windows C library does not support this C99 feature, so you'll need to fall back on the non-standard _setmode() instead:

_setmode(_fileno(stdin), _O_BINARY);
_setmode(_fileno(stdout), _O_BINARY);

If you want to remain portable, you could always use some conditional code, e.g. like this (warning: not actually tested on Windows!):

#if __STDC_VERSION__ >= 199901L
  #define binmode(fh, w) freopen(NULL, ((w) ? "wb" : "rb"), (fh)) /* C99 */
#elif _MSC_VER >= 1200
  #include <io.h>
  #include <fcntl.h>
  #define binmode(fh, w) _setmode(_fileno(fh), _O_BINARY) /* MSVC 6.0+ */
#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
  #define binmode(fh, w) /* Unix-ish, just do nothing */
#else
  #error Not sure how to define binmode() on this platform
#endif

binmode(stdin, 0);
binmode(stdout, 1);

Or, of course, you could just sidestep the whole issue by opening your own input and output files (in binary mode) instead of using stdin and stdout.



来源:https://stackoverflow.com/questions/28781430/simple-encryption-decryption-algorithm-causing-eof

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!