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

标签 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;
}

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

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

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

最佳答案

好吧,即使使用您的示例输入和 key ,您的代码也适用于 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 来回避整个问题。

关于c - 导致EOF的简单加密/解密算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28781430/

相关文章:

c - 为什么我的程序从其他函数返回后中断?

flash - 将未经篡改的数据从 Flash 应用程序传递到服务器?

c# - 在 C# 中使用 Bouncy CaSTLe 验证 ECDSA 签名

编译器颠倒了 C 行顺序?

c - 从/dev/random读取字节失败

从现有的 x 宏创建相关的 x 宏

c - 如何在C中将字符串添加到二维数组

c - fwrite() 如果任何单个字节的符号位为 1,则将全 1 写入更高有效位(写入 int)

c - sprintf 代码占用大量空间(嵌入式)

Java 8 使用带有 SealedObject 的 ECIES 密码失败,并显示 'NullPointerException' - 字符串不能为空