128位类型错误

时间:2009-11-01 16:18:04

标签: c string types xor

感谢pbos帮助及其程序(已发布here,用于编写大文件),我执行了一些测试,我发现我还有另一个问题:将掩码更改为另一个128位,根据需要,没有默认类型。

我认为解决方案可以包括一个库来增加可用的整数类型...而是我更喜欢解释每个128位值,如字符串。这可能不会失去性能吗?

这是当前程序(错误“整数常量对于其类型来说太大了”):

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

#define BLOCKSIZE 128
#define MASK 0xA37c54f173f02889a64be02f2bc44112 /* a 128 bits constant */

void
usage(const char *cmd)
{
    fprintf(stderr, "Usage: %s <in-file> [<out-file>]\n", cmd);
    exit (EXIT_FAILURE);
}

int
main(int argc, char *argv[])
{
  if (argc < 3) usage(argv[0]);

  FILE *in = fopen(argv[1], "rb");

  if (in == NULL)
  {
    printf("Cannot open: %s", argv[2]);
    return EXIT_FAILURE;
  }

  FILE *out = fopen(argv[2], "wb");

  if (out == NULL)
  {
    fclose(in);
    printf("Unable to open '%s' for writing.", argv[2]);
  }

  char buffer[BLOCKSIZE];
  int count;

  while (count = fread(buffer, 1, BLOCKSIZE, in))
  {
    int i;
    for (i = 0; i < count; i++)
    {
      ((unsigned long *)buffer)[i] ^= MASK; /* this line is bugged */
    }

    if (fwrite(buffer, 1, count, out) != count)
    {
      fclose(in);
      fclose(out);
      printf("Cannot write, disk full?\n");
      return EXIT_FAILURE;
    }
  }

  fclose(in);
  fclose(out);

  return EXIT_SUCCESS;
}

感谢您的任何建议。

道格

6 个答案:

答案 0 :(得分:2)

用另一半的常数和奇数“块”的前半部分掩盖“块”。

/* ... */
unsigned int xormask[2] = {0xA37c54f173f02889, 0xa64be02f2bc44112};
/* ... */
        for(i = 0;i < end; ++i)
        {
                ((unsigned int *)buffer)[i] ^= xormask[i & 1];
        }
/* ... */

答案 1 :(得分:2)

逐字遍历您的密钥和明文,并分别对每个字节执行XOR。

将键更改为字节数组并创建指向该数组的指针,以方便使用键:

char const key[] = {
    0xA3, 0x7c, 0x54, 0xf1, 
    0x73, 0xf0, 0x28, 0x89, 
    0xa6, 0x4b, 0xe0, 0x2f, 
    0x2b, 0xc4, 0x41, 0x12
};

char const* pKeyByte = key;

然后更改加密的行

((unsigned long *)buffer)[i] ^= MASK; /* this line is bugged */

为:

buffer[i] ^= *pKeyByte++;
if (pKeyByte == (key + sizeof(key))) {
    /* wrap to start of key */
    pKeyByte = key;
}

现在,无论密钥长度如何,您都可以将BLOCKSIZE更改为您希望的I / O大小。请注意,在您使用它时,BLOCKSIZE定义了每个循环中要从文件中读取的字节数 - 它不是密钥中的位数。

请注意,我在上一个问题中发布的caveats about XOR encryption仍然适用。

答案 2 :(得分:1)

并非所有(很多?)平台都支持128位整数。您可以将直接处理128位数字的代码分解出来并编写两个版本,一个用于支持128位数字的平台,另一个用于支持128位数字的平台。配置脚本可以检查128位支持(检查“sizeof(long long)”和“uint128_t”,或许?)并在两个实现之间进行选择。

答案 3 :(得分:0)

你也需要将面具分成几块。

unsigned int mask[] = { 0xA37c54f1, 0x73f02889, 0xa64be02f, 0x2bc44112 };
unsigned int mask_len = sizeof(mask) / sizeof(*mask);

然后,您将需要使用您读入的缓冲区作为一系列unsigned int而不是chars,并将xunk块放在掩码的相应块上:

unsigned int *uint_buffer = (unsigned int *)buffer;
for (i = 0; i < count / sizeof(int); i++)
{
    uint_buffer[i] ^= mask[i % mask_len];
}

最后,根据您的任务细节,您可能需要处理从文件中读取的数据的字节序问题。

答案 4 :(得分:0)

根据Burr的答案,我更喜欢这个:

int i;
int sizeOfKey = sizeof(key); // key is an array of chars
for (i = 0; i < count; i++)
{
    buffer[i] ^= key[i % sizeOfKey];
}

让内循环假定你的对齐为16个字节(即buffer[i + j]不检查缓冲区的实际长度。)

答案 5 :(得分:0)

整数类型的大小是核心语言特征。包含任何库都无法更改。如果你坚持使用内置的整数类型,那么克服限制的唯一方法是切换到本地支持核心语言级别的更大整数类型的另一个实现。

否则,你必须明确地将你的“长”常量分成两个或更多“更短”的常量,或者使用一些在“引擎盖下”完全相同的库。