【问题标题】:128-bit type error128 位类型错误
【发布时间】:2009-11-01 16:18:04
【问题描述】:

感谢 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;
}

感谢您的任何建议。

道格

【问题讨论】:

    标签: c string types xor


    【解决方案1】:

    用常量的前半部分屏蔽偶数“块”,用另一半屏蔽奇数“块”。

    /* ... */
    unsigned int xormask[2] = {0xA37c54f173f02889, 0xa64be02f2bc44112};
    /* ... */
            for(i = 0;i < end; ++i)
            {
                    ((unsigned int *)buffer)[i] ^= xormask[i & 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 仍然适用。

      【讨论】:

      • 将蒙版拆分这么多并在pmg的方法上添加额外循环的目的是什么?
      • 我会说这个例子更“通用”,你可以改变密钥的长度而不需要改变任何其他东西。
      • 如果count 不是sizeof(key) 的倍数,buffer[i+j] 将溢出。您应该删除内部循环并使用 mod 运算符将 key 数组与 [i % sizeof(key)] 索引。
      • @Groo - 我最初发布的版本肯定有问题(不仅仅是缓冲区溢出)。我想我通过使用单独的指针来遍历关键位数组来修复错误。
      • 您的意思是if( pKeyByte == (key + sizeof(key)) )
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

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

        【讨论】:

          【解决方案5】:

          根据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] 不检查缓冲区的实际长度)。

          【讨论】:

            【解决方案6】:

            整数类型的大小是一个核心语言特征。不能通过包含任何库来更改它。如果你坚持使用内置的整数类型,克服这个限制的唯一方法是切换到另一个在核心语言级别原生支持更大整数类型的实现。

            否则,您将不得不明确地将“长”常量拆分为两个或多个“更短”常量,或者使用一些“在后台”执行完全相同的库。

            【讨论】:

              猜你喜欢
              • 2022-06-17
              • 1970-01-01
              • 1970-01-01
              • 2011-07-11
              • 2016-02-08
              • 2020-10-31
              • 1970-01-01
              • 2013-08-13
              • 1970-01-01
              相关资源
              最近更新 更多