Keccak中的舍入常数

时间:2018-10-22 04:41:28

标签: c cryptography bit-manipulation sha-3 keccak

最近,仅就此而已,我一直在尝试实现Keccak(SHA-3背后的加密原语)。但是,我遇到了一些问题,特别是在计算排列的“ Iota”步骤中使用的舍入常数。

只是为了解决问题:是的。我知道他们是圆形的常数。我知道我可以将它们硬编码为常量。但是那有什么乐趣呢?

我特别提到了SHA-3上的FIPS 202 specification document以及Keccak团队自己的Keccak reference。但是,尽管我付出了很多努力,但最终似乎无法获得正确的常数。我以前从未处理过位操作,因此,如果我以完全错误的方式进行操作,请随时告诉我。

rc是Keccak的FIPS 202标准中定义的函数,它是线性多项式移位寄存器,其反馈多项式为x^8 + x^6 + x^5 + x^4 + 1

t的值(特定于SHA-3)定义为包含j + 7 * i_r的整数集,其中i_r = {0,1,...,22,23}和j = {0,1,...,4,5}。

预期输出(舍入常数)定义如下:0x0000000000000001,0x0000000000008082,0x800000000000808a, 0x8000000080008000、0x000000000000808b,0x0000000080000001, 0x8000000080008081、0x8000000000008009、0x000000000000008a, 0x0000000000000088、0x0000000080008009、0x000000008000000a, 0x000000008000808b,0x800000000000008b,0x8000000000008089, 0x8000000000008003、0x8000000000008002、0x8000000000000080, 0x000000000000800a,0x800000008000000a,0x8000000080008081, 0x8000000000008080、0x0000000080000001和0x8000000080008008。

rc函数实现

uint64_t rc(int t)
{
    if(t % 255 == 0)
    {
        return 0x1;
    }

    uint64_t R = 0x1;

    for(int i = 1; i <= t % 255; i++)
    {
        R = R << 0x1;
        R |= (((R >> 0x0) & 0x1) ^ ((R >> 0x8) & 0x1)) << 0x0;
        R |= (((R >> 0x4) & 0x1) ^ ((R >> 0x8) & 0x1)) << 0x4;
        R |= (((R >> 0x5) & 0x1) ^ ((R >> 0x8) & 0x1)) << 0x5;
        R |= (((R >> 0x6) & 0x1) ^ ((R >> 0x8) & 0x1)) << 0x6;
        R &= 0xFF;
    }

    return R & 0x1;
}

rc函数调用

for(int i_r = 0; i_r < 24; i_r++)
{

    uint64_t RC = 0x0;

    // TODO: Fix so the limit is not constant
    for(int j = 0; j < 6; j++)
    {
        RC ^= (rc(j + 7 * i_r) << ((int) pow(2, j) - 1));
    }

    printf("%llu\n", RC);
}

在此问题上的任何帮助都将受到赞赏。

1 个答案:

答案 0 :(得分:2)

我对代码进行了一些随机更改,现在可以使用了。这些是亮点:

  1. j循环需要从0到6进行计数。这是因为2 ^ 6-1 =63。因此,如果j从不为6,则输出将永远不会具有MSB。设置,即不可能输出0x8...。

  2. 对于这种类型的应用程序,使用pow函数通常是一个坏主意。 double值有一个讨厌的习惯,就是比期望值要低一些,例如4实际上是3.99999999999,当您将其转换为int时,它会被截断为3。在这种情况下,这种情况令人怀疑,但为什么要冒险呢,因为每次通过循环时,很容易将变量shift乘以2。

  3. t的最大值为7 * 23 + 6 = 167,因此% 255不执行任何操作(至少使用i和{{1}的值})。另外,也不需要将t视为特例。当t == 0为0时,循环将不会运行,因此默认情况下结果为0x1。

  4. 在C中实现线性反馈移位寄存器非常简单。多项式中的每个项都对应于一个位。 t只是2 ^ 8,即x^8,而0x100x^6 + x^5 + x^4 + 1。因此,只要设置了0x71位,就可以对0x100的结果进行XOR。

这是更新的代码:

0x71