我们有一个嵌入式产品,自5年前以来,我们一直在进行多次硬件迭代。我们拥有所有源代码,其中大多数文档都有很好的记录。由于产品积极销售且需要升级,因此我受命设计下一代改进版本。

虽然我们拥有所有源代码,并且大多数文档都有据可查,但是安全性部分还是不是,特别是最慢的部分,是具有72个回合的128位哈希函数。我可以将其放入调试器中,执行它,除了运行缓慢以外,代码可以正常工作。如果我知道它是哪种加密标准,我可以尝试将其升级为在硬件中执行,这将大大加快其速度。 (编写此功能的原始顾问不在我们公司,而且我找不到她。)

是否有任何逻辑方法可以确定我们正在执行哪种加密?在帮助我完成工作时,我正在寻求建议,如果有任何策略可以查看代码(“未优化的混乱”);学习它的原理(像这样有72个回合并散列128位);然后找到做同样事情的候选标准。

我认为,找到已记录的标准后,我应该能够通过使用我们的哈希和标准哈希来哈希各种数字,并简单地查看结果匹配吗?

我在网上寻找了使用Skein算法的72轮已知函数的信息,但是找不到类似的东西。已知标准的值,例如哈希0的结果?此哈希将0转换为这16个十六进制字节:

ae c5 40 44 df 2d 91 1c 87 ab 1a ff 59 09 aa b7


函数的开头和结尾在下面,如您中某些人所要求的,完整功能在以下位置:
full_function_code

以前的程序员似乎让旧的C编译器进行了转换,然后以“汇编”样式使用了它。也许是因为避免编译器优化,这只是我的猜测。

有72个回合,每个回合以对函数TricoreDextr()的调用结束;与Infineon TriCore DEXTR指令的C等效项。认为DEXTR是将64位数字分为两部分(在选定的位位置)并交换它们。 >
/*
 * @param in_arr    16 byte long array, input data (128 bits)
 * @param out_arr   16 byte long array, output data (128 bits)
 */
void Hash16bytes(unsigned char *in_arr, unsigned char *out_arr) 
{
  long d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d15;
  long IN[16];

  d4 = 0xB12E8FB5;

  int i;
  for (i = 0; i < 16; i++)
  {
      IN[i] = (long) (*(in_arr + i));
  }

  d11 = (IN[3] << 24) | (IN[2] << 16) | (IN[1] << 8) | IN[0];
  d10 = (IN[7] << 24) | (IN[6] << 16) | (IN[5] << 8) | IN[4];
  d12 = (IN[0xB] << 24) | (IN[0xA] << 16) | (IN[9] << 8) | IN[8];
  d13 = (IN[0xF] << 24) | (IN[0xE] << 16) | (IN[0xD] << 8) | IN[0xC];

  /* block like this below repeats 72 times... */
  d3 = 0x7025BD47;
  d8 = 0xCCEE4EFE;
  d8 += d13; 
  d8 += d3;
  d8 = TricoreDextr(d8, 6);

  /* 
     etc., TricoreDextr is called total of 72 times 
   */

  d0 += d15;
  d0 += 0x5C4E0000;
  d0 -= 0x2EDC;
  d0 = TricoreDextr(d0, 5);

  *(out_arr + 3) = (unsigned char) ((d5 >> 24) & 0xFF);
  *(out_arr + 2) = (unsigned char) ((d5 >> 16) & 0xFF);
  *(out_arr + 1) = (unsigned char) ((d5 >> 8) & 0xFF);
  *(out_arr + 0) = (unsigned char) ((d5) & 0xFF);

  *(out_arr + 7) = (unsigned char) ((d6 >> 24) & 0xFF);
  *(out_arr + 6) = (unsigned char) ((d6 >> 16) & 0xFF);
  *(out_arr + 5) = (unsigned char) ((d6 >> 8) & 0xFF);
  *(out_arr + 4) = (unsigned char) ((d6) & 0xFF);

  d8 += d0;
  d8 += 0x10320000;
  d8 += 0x5476;

  *(out_arr + 0xB) = (unsigned char) ((d8 >> 24) & 0xFF);
  *(out_arr + 0xA) = (unsigned char) ((d8 >> 16) & 0xFF);
  *(out_arr + 9) = (unsigned char) ((d8 >> 8) & 0xFF);
  *(out_arr + 8) = (unsigned char) ((d8) & 0xFF);

  *(out_arr + 0xF) = (unsigned char) ((d7 >> 24) & 0xFF);
  *(out_arr + 0xE) = (unsigned char) ((d7 >> 16) & 0xFF);
  *(out_arr + 0xD) = (unsigned char) ((d7 >> 8) & 0xFF);
  *(out_arr + 0xC) = (unsigned char) ((d7) & 0xFF);
}


评论

您尚未显示如何在Hash16bytes()中填充out_arr []。另外,您的代码段中出现的常量(即:0xB12E8FB5、0x7025BD47、0xCCEE4EFE)不会出现在Google之外的任何地方,但会出现此问题,这使这个难题变得有些挑战。我可以推断出:1)此哈希函数是自生的,2)这是键控哈希函数,并且常量以某种方式表示键,或3)这是代码生成和/或以一种奇怪的方式转换的。 >
mhum:我也添加了函数的结尾

该代码是未优化的烂摊子,几乎可以肯定不是标准的,您应该发布完整的链接,因为注释的块可能无法精确地重复
看起来它可能是模糊的RIPEMD-128。常量似乎匹配为0x5C4E0000-0x2EDC = 0x5C4DD124和0x50A30000-0x741A = 0x50A28BE6。应该易于确认。 (在这里,反向工程不在主题之列,标记为迁移。)

该代码看起来有些丑陋,但是您确实以源代码形式拥有它。为什么不分析一些运行并尝试按原样加快运行速度,而不是尝试查找看起来相似但产生稍微不同结果的另一种算法,从而破坏协议?

#1 楼

正如otus所说,这很可能是RIPEMD128损坏或非常类似的东西。 br />通常,当试图识别与密码相关的代码时,您依赖于发现常量。在这种情况下,常量似乎是故意被混淆了,因此您需要使用数字,将其放入Google并希望得出一些结果。 (通过不断的搜寻),我寻找了一些代码。因为输入/输出是128位,所以我从这里下载了RIPE128的代码:

https://homes.esat.kuleuven.be/~bosselae/ripemd160/ps/AB-9601/rmd128 .c

然后我查看了一下。我注意到compress()中的操作似乎使用了向左旋转(检查宏定义的头文件),并且奇怪的TricoreDextr()实际上是类似的东西。 TricoreDextr()行,并将其与compress()中的操作进行比较,并出现了一些相似之处:

GG(aa, bb, cc, dd, X[ 7],  7);
GG(dd, aa, bb, cc, X[ 4],  6);
GG(cc, dd, aa, bb, X[13],  8);
GG(bb, cc, dd, aa, X[ 1], 13);


比较: br />。 TricoreDextr调用未完全匹配rich128实现。我还注意到在这些操作中仅使用了一些幻数。

例如出现在

d8 = TricoreDextr(d8, 7);
d6 = TricoreDextr(d6, 6);
d5 = TricoreDextr(d5, 8);
d7 = TricoreDextr(d7, 0xD);


出现:

#define GG(a, b, c, d, x, s)        {\
  (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\
  (a) = ROL((a), (s));\
}


,但其他却没有,所以肯定缺少一些如果是RIPE128的操作。在RIPE160(和RIPE128)之前,曾有一个128位RIPEMD哈希函数的原始设计,但我当时无法找到任何源代码。到

https://www.springer.com/in/book/9783540606406

,其中应该包含我认为的原始算法,但这是一本花钱的书。

知道了所有这些,我最好的猜测是这是故意混淆的原始RIPEMD 128位哈希函数,因为现代实现中有部分但不是全部操作都在这里,暗示它们可能是第二个版本的补充,它将解释他们为什么失踪。那人或某人使用了现代的RIPEMD128实现,并对它做了奇怪的事情。

评论


谢谢您提供的书链接,我订购了该书,它具有教育意义,甚至更多,它描述了代码

– EmbeddedGuy
18年4月25日在15:05