c++ 如何乘以十六进制数来实现AES的逆MixColumns?

63lcw9qa  于 2022-12-27  发布在  其他
关注(0)|答案(1)|浏览(88)

我正在用c++编写AES,并且遇到了逆Mixcolumns函数的问题。我必须将一个数组与一个矩阵相乘,本质上是做点积。我使用此资源here解决了加密MixColumns,并尝试使用此资源here实现逆函数。我使用第一个资源中的解乘以2,如下所示:

  • (d4×02)为d4〈〈1,与1b异或(因为d4高位置位)

使用第二个资源,我将实现乘以9、11、13、14

  • x×9=(((x×2)×2)×2)+x
  • x×11=((((x×2)×2)+x)×2)+x
  • x×13=((((x×2)+x)×2)×2)+x
  • x×14=((((x×2)+x)×2)+x)×2

这是我的函数,我试图实现逆MixColumns:

void InvMixColumns(unsigned char plainText[4][4])
{

    unsigned char temp[4] = { 0x00,0x00,0x00,0x00 };

    unsigned char newState[4][4] = { {0,0,0,0},
                                     {0,0,0,0},
                                     {0,0,0,0},
                                     {0,0,0,0} };

    int rijndaelMatric[4][4] = { {14,11,13,9},
                                 {9,14,11,13},
                                 {13,9,14,11},
                                 {11,13,9,14} };

    for (int y = 0; y < 4; y++)
    {
        int z = 0;
        for (int i = 0; i < 4; i++)
        {
            temp[i] = 0x00;
        }
        for (int x = 0; x < 4; x++)
        {
            for (int j = 0; j < 4; j++)
            {
                unsigned char constant = 0x00;
                switch (rijndaelMatric[z][j])
                {
                case 9:
                    // Check if highest bit is 1.
                    if ((plainText[j][y] & 0x80) == 0x80)
                        constant = 0x1B;

                    temp[j] = ((((((plainText[j][y] << 1) ^ constant) << 1) ^ constant) << 1) ^ constant) ^ plainText[j][y];
                    break;
                case 11:
                    // Check if highest bit is 1.
                    if ((plainText[j][y] & 0x80) == 0x80)
                        constant = 0x1B;

                    temp[j] = (((((((plainText[j][y] << 1) ^ constant) << 1) ^ constant) ^ plainText[j][y]) << 1) ^ constant) ^ plainText[j][y];
                    break;
                case 13:
                    // Check if highest bit is 1.
                    if ((plainText[j][y] & 0x80) == 0x80)
                        constant = 0x1B;

                    temp[j] = (((((((plainText[j][y] << 1) ^ constant) ^ plainText[j][y]) << 1) ^ constant) << 1) ^ constant) ^ plainText[j][y];
                    break;
                case 14:
                    // Check if highest bit is 1.
                    if ((plainText[j][y] & 0x80) == 0x80)
                        constant = 0x1B;

                    temp[j] = (((((((plainText[j][y] << 1) ^ constant) ^ plainText[j][y]) << 1) ^ constant) ^ plainText[j][y]) << 1) ^ constant;
                    break;
                }

            }
            newState[x][y] = int(temp[0]) ^ int(temp[1]) ^ int(temp[2]) ^ int(temp[3]);
            z++;
        }

    }

    for (int x = 0; x < 4; x++)
    {
        for (int y = 0; y < 4; y++)
        {
            plainText[x][y] = newState[x][y];
        }
    }

}

以下是将通过函数运行的状态之一的示例:
| 是|阿埃|六十五|1a|
| 4e|七十八|交流|七日|
| c3|二十五|九十四|二十七|
| c1|七十六|八十八|六十四|
应为:
| 八十九|c2|二十二|FD|
| 六十六|第3b段|6b|四十四|
| 0b|五十八|六十二|c7|
| 十六|二十四|铁|f0|
但我得到:
| 八十九|c2| 0f| CB|
| 4b|十六|七十|四十四|
| 十个|四十三|五十四|埃亚|
| 二十个|十二|铁|电子束|
我是不是漏掉了什么?我是不是看漏了什么?与上面的普通MixColumns和反函数相比,唯一的变化是sswitch中的乘法部分,所以它一定是实现中的某个部分,但我看不出来是什么。
如果你想看到所有的代码/想运行它,你可以here

wn9m85ua

wn9m85ua1#

你必须小心中间乘法。你必须在每次乘法之前检查结果是否会溢出,并相应地与0x1B异或。
换句话说,内部switch()应该更像这样(为了可读性,我缩短了变量名:

unsigned char x = plainText[j][y];
unsigned char y = 0;
switch (rijndaelMatric[z][j]) {
    case 9:
        y = (x << 1) ^ ((x & 0x80) ? 0x1B : 0x00); // x 2
        y = (y << 1) ^ ((y & 0x80) ? 0x1B : 0x00); // x 4
        y = (y << 1) ^ ((y & 0x80) ? 0x1B : 0x00); // x 8
        y ^= x;                                    // x 9
        temp[j] = y;
        break;
    case 11:
        y = (x << 1) ^ ((x & 0x80) ? 0x1B : 0x00); // x 2
        y = (y << 1) ^ ((y & 0x80) ? 0x1B : 0x00); // x 4
        y ^= x;                                    // x 5
        y = (y << 1) ^ ((y & 0x80) ? 0x1B : 0x00); // x 10
        y ^= x;                                    // x 11
        temp[j] = y;
        break;
    case 13:
        y = (x << 1) ^ ((x & 0x80) ? 0x1B : 0x00); // x 2
        y ^= x;                                    // x 3
        y = (y << 1) ^ ((y & 0x80) ? 0x1B : 0x00); // x 6
        y = (y << 1) ^ ((y & 0x80) ? 0x1B : 0x00); // x 12
        y ^= x;                                    // x 13
        temp[j] = y;
        break;
    case 14:
        // Check if highest bit is 1.
        y = (x << 1) ^ ((x & 0x80) ? 0x1B : 0x00); // x 2
        y ^= x;                                    // x 3
        y = (y << 1) ^ ((y & 0x80) ? 0x1B : 0x00); // x 6
        y ^= x;                                    // x 7
        y = (y << 1) ^ ((y & 0x80) ? 0x1B : 0x00); // x 14

        temp[j] = y;
        break;
}

您可以在这里检查代码:https://godbolt.org/z/hccnvcqex

相关问题