1

最近、なんとなく、SHA-3 の背後にある暗号化プリミティブである Keccak の実装を試してみました。ただし、特に順列の「イオタ」ステップで使用されるラウンド定数の計算で、いくつかの問題に遭遇しました。

邪魔にならないように:はい。私はそれらがラウンド定数であることを知っています。それらを定数としてハードコーディングできることはわかっています。しかし、それのどこが楽しいのでしょうか。

特に、SHA-3 に関するFIPS 202 仕様書と、Keccak チーム独自のKeccak リファレンスを参照しています。しかし、私の努力にもかかわらず、正しい定数にたどり着くことができないようです。これまでビット操作を扱ったことがないので、完全に間違った方法で何かをしている場合は、遠慮なくお知らせください。

rc は、フィードバック多項式 の線形フィードバック シフト レジスタである Keccak の FIPS 202 標準で定義されている関数ですx^8 + x^6 + x^5 + x^4 + 1

(SHA-3 に固有の)の値は、i_r = {0, 1, ..., 22, 23} および j = {0, 1, ..., 4,tを含む整数のセットとして定義されます。 j + 7 * i_r5}。

The expected outputs (the round constants) are defined as follows: 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);
}

この問題に関するヘルプは大歓迎です。

4

1 に答える 1