0

感谢 pbos 帮助及其程序(在此处发布,用于 xoring 一个大文件),我执行了一些测试,发现我还有另一个问题:将掩码更改为另一个 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;
}

感谢您的任何建议。

道格

4

6 回答 6

2

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

/* ... */
unsigned int xormask[2] = {0xA37c54f173f02889, 0xa64be02f2bc44112};
/* ... */
        for(i = 0;i < end; ++i)
        {
                ((unsigned int *)buffer)[i] ^= xormask[i & 1];
        }
/* ... */
于 2009-11-01T16:28:50.090 回答
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定义在每个循环中从文件中读取的字节数 - 它不是密钥中的位数。

请注意,我在您上一个问题中发布的有关 XOR 加密的警告仍然适用。

于 2009-11-01T16:32:33.500 回答
1

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

于 2009-11-01T16:27:56.503 回答
0

你还需要把你的面具分成几块。

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

然后,您需要将读入的缓冲区作为一系列无符号整数而不是字符和 xor 块与掩码的适当块一起使用:

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

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

于 2009-11-01T16:28:58.717 回答
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];
}

Having the inner loop presumes that your is aligned at 16 bytes (i.e. buffer[i + j] doesn't check for the actual length of the buffer).

于 2009-11-01T16:41:14.557 回答
0

Sizes of integer types are a core language characteristic. It cannot be changed by including any libraries. If you insist on using the built-in integral types, the only way to overcome ths limitition is to switch to another implementation that natively supports larger integer types at the core language level.

Otherwise, you'll have to either explictly split your "long" constant into two or more "shorter" constants, or use some library that will do exactly the same "under the hood".

于 2009-11-01T16:53:50.883 回答