【问题标题】:Simple encryption/decryption algorithm causing EOF导致EOF的简单加密/解密算法
【发布时间】:2015-02-28 11:57:43
【问题描述】:

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

#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;
}

加密密钥是程序的第一个命令行参数。我希望这应该在用相同的密钥加密/解密时得到我的原始文件。但是,如果我对它进行加密/解密,有时我只能取回少量文件。我的猜测是算法在文件中间添加了 EOF 控制字符。

我怎样才能解决这个问题?

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

【问题讨论】:

  • 您的代码对我来说很好(在 Linux / GCC 上)。您使用的是什么操作系统和编译器?此外,如果您可以粘贴一个简短的文件示例和说明问题的密钥,这将有所帮助。
  • 无论如何,你可能想试试setting stdin and stdout to binary mode.
  • 我猜 ciphertext 中有一个 00 值的字节,其余的没有被读取。
  • @Maarten:实际上,对于fread(),空值不是问题。然而,显然,在文本模式下的 WINdows 上,Ctrl-Z 字符 (0x1A) 是。
  • @IlmariKaronen 呃,这是我脑海中 Windows 怪异表中的另一个条目。不断成长,希望有一天我能把它放到{any folder at all}/NUL

标签: c encryption stdio


【解决方案1】:

好吧,即使使用您的示例输入和密钥,您的代码在 Linux(使用 GCC 4.8.2 编译)上也适用于我。这表明该问题特定于 Windows — 很可能是由默认情况下位于 text mode 中的 stdin 和 stdout 引起的。 (在 Linux 和其他 Unix-ish 系统上,文本模式和二进制模式通常没有区别,因此不会出现此类问题。)

要修复它,您需要set stdin and stdout to binary mode。从C99 开始,standard way of doing this 将是:

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 来回避整个问题。

【讨论】:

  • 我打开了自己的输入和输出文件。我认为这是一个更简单的解决方案。它也有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-31
  • 2014-06-28
相关资源
最近更新 更多