C 语言中的 Rijndael S-box

Rijndael S-box in C

我正在尝试根据这篇维基百科文章编写一个计算 Rijndael S-box 的函数。 Rijndael S-box

#define ROTL8(x,shift) ((uint8_t) ((x) << shift | ((x) >> (8 - (shift)))))
uint8_t sbox(uint8_t b)
{
    uint8_t s = b ^ ROTL8(b,1) ^ ROTL8(b,2) ^ ROTL8(b,3) ^ ROTL8(b,4) ^ 0x63;
    return s;
}

现在,当我尝试 sbox(0x00)=0x63 和 sbox(0x01)=0x7c 时,它可以正常工作,但它开始偏离 sbox(0x02),它应该是 0x77,但我得到的是 0x5d。我怀疑问题可能是轮换工作不正常,但现在看来这不是问题...

这里有什么问题?

这是实现 AES 的 S-box 的错误方法 - 大多数实现要么是硬编码的(它们明确地将整个 S-box 写为 256 字节数组),要么是迭代 构建 S-box 的条目,如您链接的维基百科文章所示:

void initialize_aes_sbox(uint8_t sbox[256]) {
    uint8_t p = 1, q = 1;
    
    /* loop invariant: p * q == 1 in the Galois field */
    do {
        /* multiply p by 3 */
        p = p ^ (p << 1) ^ (p & 0x80 ? 0x1B : 0);

        /* divide q by 3 (equals multiplication by 0xf6) */
        q ^= q << 1;
        q ^= q << 2;
        q ^= q << 4;
        q ^= q & 0x80 ? 0x09 : 0;

        /* compute the affine transformation */
        uint8_t xformed = q ^ ROTL8(q, 1) ^ ROTL8(q, 2) ^ ROTL8(q, 3) ^ ROTL8(q, 4);

        sbox[p] = xformed ^ 0x63;
    } while (p != 1);

    /* 0 is a special case since it has no inverse */
    sbox[0] = 0x63;
}

请注意 xformed 的值 - 这是您在自己的实现中计算的值 - 在迭代过程中不断变化(并且它不是其 q 的 S-box 值你实施的方式)。在实践中,每个手动 S-box 构造都有某种类似的迭代过程 - look over at Code Golf 对于一些创造性的实现。