导致EOF的简单加密/解密算法

时间:2015-02-28 11:57:44

标签: c encryption stdio

我正在玩这种非常简单的加密/解密算法;

#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键是程序的第一个命令行参数。我希望这可以在使用相同的密钥加密/解密时获取原始文件。但是,如果我加密/解密它,我有时只会获得少量文件。我的猜测是算法在文件中间添加了EOF控制字符。

如何解决这个问题?

我在Windows XP上使用MinGW gcc 4.8.1编译了这个。如果您有兴趣,可以在the edit history of this question找到一个示例输入文件来说明问题。

1 个答案:

答案 0 :(得分:2)

好吧,你的代码在Linux上运行(用GCC 4.8.2编译),甚至使用你的示例输入和密钥。这表明该问题特定于Windows - 最有可能的是,它是由stdin和stdout默认位于text mode引起的。 (在Linux和其他Unix-ish系统上,文本模式和二进制模式之间通常没有区别,因此这些问题不会出现在那里。)

要解决此问题,您需要set stdin and stdout to binary mode。从standard way of doing this开始,C99将是:

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

但是,根据我上面链接的帖子中的答案,Windows C库does not support this C99 feature,所以你需要重新使用非标准的_setmode()

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

如果您想保持便携性,可以随时使用某些条件代码,例如:像这样(警告:实际上没有在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);

或者,当然,您可以通过打开自己的输入和输出文件(以二进制模式)而不是使用stdinstdout来回避整个问题。