寻找有限域同构映射

一、有限域简介

有限域亦称伽罗瓦域(Galois Fields),是伽罗瓦于 18 世纪 30 年代研究代数方程根式求解问题时引出的概念。有限域在密码学、近代编码、计算机理论、组合数学等方面有着广泛的应用

在抽象代数中,域是一个对加法和乘法封闭的集合,其中要求每个元素都有加法逆元,每个非零元素都有乘法逆元。若域 \(F\) 只包含有限个元素,则称为有限域,有限域中元素的个数称为有限域的阶。可以证明,有限域的阶必为素数的幂,即有限域的阶可表示为 \(p^n\)\(p\) 是素数,\(n\) 是正整数)。有限域通常记为 \(GF(p^n)\)

二、有限域同构

因为网上似乎都没有如何寻找有限域同构映射的资料,而正好我上课学到了相关的内容,在此结合自己的理解作简单的介绍。因为不是数学系相关的学生,而且对有限域的理解仅处于皮毛,有很多定理没办法给出详细的证明,在逻辑上或许会多有漏洞,如果读者发现我的漏洞希望能够指出。
(虽然指出了我也不一定能听懂,但还是希望能够指出)

另外,有限域的相关知识(例如有限域的性质,有限域的构造等)将默认读者已经了解,在阅读后续内容前先保证对上述知识有所了解

关于复合域强烈建议参考这篇博客: AES 和 SM4 S 盒复合域实现方法,本文提到的内容参考了论文《适合SMS4算法硬件实现的S盒构造新方法》中给出的求解同构映射的方法 (--- 2022.04.28 更新 ---)

上面的链接好像打不开了,不过我在github上好像找到了对应的作者,SM4-with-AESENCLAST 这个链接是对应的资料。
很多寻找有限域同构的方法采用的都是正规基之类的,但我这块不是很了解,可能没法给各位满意的答复。我这里提到的方法是《适合 SMS4 算法硬件实现的 S 盒构造新方法》(徐艳华、白雪飞、郭立)这篇论文中的采用的方法,但论文里边原理部分感觉不是很清楚。这篇博客是我根据上课学到的内容结合自己的理解写的,原理上应该会有纰漏 (--- 2022.12.27 更新 ---)

关于复合域优化SM4算法强烈建议参考下方论文: (--- 2023.05.27 更新 ---)
[1] 陈晨,郭华,王闯等.一种基于复合域的国密SM4算法快速软件实现方法[J].密码学报,2023,10(02):289-305.

2.1 寻找同构映射思路

首先,任意相同阶数的有限域都同构。假设 \(p(x)\)\(q(x)\) 都是域 \(F_p\) 上的 \(n\) 阶不可约多项式,那么有限域 \(F_1 = F_p[x] / p(x)\)\(F_2 = F_p[x] / q(x)\) 都是 \(p^n\) 阶有限域。

有下面两条重要定理:

  • 如果假设 \(\alpha\) 是多项式 \(p(x)\) 的一个根,那么有限域 \(F_1\) 可以表示成 \(F_p[\alpha]\)
  • 如果假设 \(\beta\) 是多项式 \(q(x)\) 的一个根,那么有限域 \(F_2\) 可以表示成 \(F_p[\beta]\)

现在需要找到一个两者的同构映射 \(\phi\)
首先,根 \(\alpha\)\(\beta\) 满足 \(p(\alpha)=0\)\(q(\beta)=0\)
直接将 \(\alpha\) 映射到 \(\beta\) 是不可行的,因为线性关系无法保证,即无法保证 \(p(\beta)=0\)
那么如果找到 \(\beta ' \in F_p[\beta]\) 使得 \(p(\beta')=0\) 成立,这样就可以构造 \(\alpha \to \beta '\) 的映射

2.2 寻找同构映射例子

求有限域 \(Z_3[x] / (x^2 + 1)\)\(Z_3[x] / (x^2 + x +2)\) 之间的同构映射

\(p(x) = x^2 + 1\)\(q(x) = x^2 + x + 2\)
且有 \(\alpha = \overline{x} \; mod \; p(x)\)\(p(x)\) 的一个根
且有 \(\beta = \overline{x} \; mod \; q(x)\)\(q(x)\) 的一个根

寻找得到 \(\beta' = \beta + 2\) ,使得 \(p(\beta') = (\beta + 2)^2 + 1 = \beta^2 + \beta + 2 = 0\)
那么对应的映射为 \(\alpha \to \beta + 2\)

也就是原先 \(Z_3[\alpha]\) 中的元素 \(a_1 \alpha + a_0\) 将被映射成 \(a_1 (\beta + 2) + a_0 = a_1 \beta + (2a_1 + a_0) \in Z_3[\beta]\)
或者说原先 \(Z_3[x] / (x^2 + 1)\) 中的元素 \(a_1 x + a_0\) 将被映射到 \(Z_3[x] / (x^2 + x +2)\) 中的 \(a_1 x + (2a_1 + a_0)\)

2.3 同构映射逆映射

在 2.2 中已经求出了一个同构映射 \(\alpha \to \beta + 2\)
很容易发现 \(q(\alpha - 2) = (\alpha - 2)^2 + (\alpha - 2) + 2 = \alpha^2 + 1 = 0\)

也就是说逆映射为 \(\beta \to \alpha - 2\)

三、复合域与同构

3.1 复合域

接下来介绍一个稍微复杂的有限域——复合域,复合域在密码学中具有非常大的用途,将一个高阶的有限域转化为两个或多个低阶有限域的复合,便于后续分析

\(p(x) = x^2 + x + 4\)\(F_2[x] / p(x)\)\(2^2\) 阶有限域
\(q(x) = x^4 + x^3 + 1\)\(F_2[x] / q(x)\)\(2^4\) 阶有限域
那么将两者复合得到 \(F : b_1 x + b_2 \; mod \; p(x), \; b_i \in F_2[x] / q(x)\) ,为 \((2^4)^2 = 2^8\) 阶有限域(复合域)

3.2 复合域同构

通过一个例子来了解求复合域同构的过程

\(F_2[x] / r(x)\)\(2^8\) 阶有限域, \(r(x) = x^8 + x^7 + x^6 + x^5 + x^4 + x^2 + 1\)

\(F[x] / (p(x), q(y)) = (a_3 y^3 + a_2 y^2 + a_1 y + a_0) x + (b_3 y^3 + b_2 y^2 + b_1 y + b_0)\) 为上述 3.1 中的 \((2^4)^2\) 阶有限域

\(F_2[x] / r(x) \to F[x] / (p(x), q(x))\) 的一个同构映射

首先,需要遍历 \(F[x] / (p(x), q(y))\) 的全部元素,找到其中一个 \(\beta'\) 满足 \(r(\beta') = 0\) 的元素 \((y^2 + 1)x + (y^3 + y^2 + y)\)
\(\alpha = \overline{x} \; mod \; r(x)\)\(r(x)\) 的根
那么同构映射为 \(\alpha \to \beta'\)

四、映射矩阵

4.1 有限域与矩阵

在密码学中,常将多项式表示为矩阵的形式,例如在 \(GF(2^8)\) 上的多项式

\[x^7 + x^6 + x + 1 \equiv \begin{bmatrix} 1 & 1 & 0 & 0 & 0 & 0 & 1 & 1 \end{bmatrix}^T \]

假设 \(p(x)\)\(q(x)\) 都是 \(F_2\) 上的 \(8\) 次不可约多项式,那么可以构成 \(2^8\) 阶有限域 \(F_2[x]/p(x)\)\(F_2[x]/q(x)\)

假设 \(\alpha\) 是多项式 \(p(x)\) 的一个根,那么有限域 \(F_2[x]/p(x)\) 可以表示成 \(F_2[\alpha]\)
假设 \(\beta\) 是多项式 \(q(x)\) 的一个根,那么有限域 \(F_2[x]/q(x)\) 可以表示成 \(F_2[\beta]\)

且假设 \(c_7 x^7 + c_6 x^6 + c_5 x^5 + \cdots + c_1 x + c_0\)\(F_2[x]/p(x)\) 上的一个多项式,那么该多项式也可以等价于 \(c_7 \alpha^7 + c_6 \alpha^6 + c_5 \alpha^5 \cdots c_1 \alpha + c_0\) ,即

\[\begin{bmatrix} \alpha^7 & \alpha^6 & \alpha^5 & \alpha^4 & \alpha^3 & \alpha^2 & \alpha & 1 \end{bmatrix} \times \begin{bmatrix} c_7 & c_6 & c_5 & c_4 & c_3 & c_2 & c_1 & c_0\end{bmatrix}^T \]

4.2 多项式矩阵

假设 \(\alpha^i = a_{7,i} x^7 + a_{6,i} x^6 + \cdots a_{1,i} x + a_{0,i}\)

那么

\[\begin{bmatrix} \alpha^7 \\ \alpha^6 \\ \alpha^5 \\ \alpha^4 \\ \alpha^3 \\ \alpha^2 \\ \alpha \\ 1 \end{bmatrix}^T \equiv \begin{bmatrix} a_{7,7} & a_{7,6} & a_{7,5} & a_{7,4} & a_{7,3} & a_{7,2} & a_{7,1} & a_{7,0}\\ a_{6,7} & a_{6,6} & a_{6,5} & a_{6,4} & a_{6,3} & a_{6,2} & a_{6,1} & a_{6,0}\\ a_{5,7} & a_{5,6} & a_{5,5} & a_{5,4} & a_{5,3} & a_{5,2} & a_{5,1} & a_{5,0}\\ a_{4,7} & a_{4,6} & a_{4,5} & a_{4,4} & a_{4,3} & a_{4,2} & a_{4,1} & a_{4,0}\\ a_{3,7} & a_{3,6} & a_{3,5} & a_{3,4} & a_{3,3} & a_{3,2} & a_{3,1} & a_{3,0}\\ a_{2,7} & a_{2,6} & a_{2,5} & a_{2,4} & a_{2,3} & a_{2,2} & a_{2,1} & a_{2,0}\\ a_{1,7} & a_{1,6} & a_{1,5} & a_{1,4} & a_{1,3} & a_{1,2} & a_{1,1} & a_{1,0}\\ a_{0,7} & a_{0,6} & a_{0,5} & a_{0,4} & a_{0,3} & a_{0,2} & a_{0,1} & a_{0,0} \end{bmatrix} \]

\(\alpha = \overline{x} \; mod \; p(x)\) 时,上式为单位阵 \(I\)

4.3 同构映射与矩阵

假设 \(c_7 x^7 + c_6 x^6 + c_5 x^5 + \cdots + c_1 x + c_0\)\(F_2[x]/p(x)\) 上的多项式
假设 \(d_7 x^7 + d_6 x^6 + d_5 x^5 + \cdots + d_1 x + d_0\)\(F_2[x]/q(x)\) 上的多项式

记它们两者的矩阵表示为 \(C\)\(D\)

要找到两个域的映射关系,将一个多项式映射到另一个多项式
也就是要找到一个映射矩阵 \(T\) ,使得一个多项式的矩阵表示 \(C\) 和另一个多项式的矩阵表示 \(D\) 满足 \(TC = D\)

上文提到,可以找到一个同构映射 \(\alpha \to \beta'\) ,使得有限域 \(F_2[\alpha]\) 和有限域 \(F_2[\beta]\) 同构

根据同构关系的线性性质,有 \(\alpha^i \to \beta'^i\) ,故映射为

\[c_7 \alpha^7 + c_6 \alpha^6 + c_5 \alpha^5 \cdots c_1 \alpha + c_0 \to c_7 \beta'^7 + c_6 \beta'^6 + c_5 \beta'^5 \cdots c_1 \beta' + c_0 \]

\(\alpha\) 对应的矩阵(如4.2所示)为 \(A\)\(\beta'\) 对应的矩阵为 \(B\)
那么映射矩阵 \(T\) 满足 \(TAC = BC\) ,即 \(T= B A^{-1}\)

为了计算方便,一般选取的根 \(\alpha = \overline{x} \; mod \; p(x)\)
那么 \(\alpha\) 对应的矩阵 \(A\) 即为单位阵 \(I\)
那么 \(T = B\)

假设 \(\beta'^i = b_{7,i} x^7 + b_{6,i} x^6 + \cdots b_{1,i} x + b_{0,i}\)
那么

\[T = \begin{bmatrix} b_{7,7} & b_{7,6} & b_{7,5} & b_{7,4} & b_{7,3} & b_{7,2} & b_{7,1} & b_{7,0}\\ b_{6,7} & b_{6,6} & b_{6,5} & b_{6,4} & b_{6,3} & b_{6,2} & b_{6,1} & b_{6,0}\\ b_{5,7} & b_{5,6} & b_{5,5} & b_{5,4} & b_{5,3} & b_{5,2} & b_{5,1} & b_{5,0}\\ b_{4,7} & b_{4,6} & b_{4,5} & b_{4,4} & b_{4,3} & b_{4,2} & b_{4,1} & b_{4,0}\\ b_{3,7} & b_{3,6} & b_{3,5} & b_{3,4} & b_{3,3} & b_{3,2} & b_{3,1} & b_{3,0}\\ b_{2,7} & b_{2,6} & b_{2,5} & b_{2,4} & b_{2,3} & b_{2,2} & b_{2,1} & b_{2,0}\\ b_{1,7} & b_{1,6} & b_{1,5} & b_{1,4} & b_{1,3} & b_{1,2} & b_{1,1} & b_{1,0}\\ b_{0,7} & b_{0,6} & b_{0,5} & b_{0,4} & b_{0,3} & b_{0,2} & b_{0,1} & b_{0,0} \end{bmatrix} \]

4.4 一般算法流程

首先,需要找到两个域 \(F_2[x]/p(x)\)\(F_2[x]/q(x)\) 满足映射关系的 \(\alpha\)\(\beta'\)
其中 \(\alpha = \overline{x} \; mod \; p(x)\)\(\beta = \overline{x} \; mod \; q(x)\)
\(p(\beta') = 0, \beta' \in F_2[\beta] = F_2[x]/q(x)\)

计算 \(\beta'^i, i = 0, 1, \cdots , 7\) ,并将 \(\beta'^i\) 的系数值置于矩阵 \(T\) 的倒数第 \(i\) 列(从0开始)

五、代码实现(寻找同构映射)

有限域的四则运算:点击此处跳转

假设 \(p(x) = x^8 + x^4 + x^3 + x + 1\)\(q(x) = x^8 + x^7 + x^6 + x^5 + x^4 + x^2 + 1\)
需要求解 \(F_2[x]/p(x)\)\(F_2[x]/q(x)\) 之间的映射关系

5.1 有限域类(GF28)

def gf2_mul(a: int, b: int, poly: int) -> int:
    """有限域乘法"""
    ans = 0
    digit = poly.bit_length() - 1
    while b:
        if b & 1:
            ans = ans ^ a
        a, b = a << 1, b >> 1
        if a >> digit:
            a = a ^ poly
    return ans


class GF256:
    def __init__(self, value, poly):
        self.value = value
        self.poly = poly

    def __add__(self, other):
        """加法"""
        return GF256(self.value ^ other.value, self.poly)

    def __sub__(self, other):
        """减法"""
        return GF256(self.value ^ other.value, self.poly)

    def __mul__(self, other):
        """乘法"""
        return GF256(gf2_mul(self.value, other.value, self.poly), self.poly)

    def __pow__(self, power, modulo=None):
        """幂"""
        res = GF256(1, self.poly)
        for i in range(power):
            res = res * self
        return res

5.2 p(x)和q(x)定义

px = 0b100011011  # x^8 + x^4 + x^3 + x + 1
qx = 0b111110101  # x^8 + x^7 + x^6 + x^5 + x^4 + x^2 + 1
p = lambda x: x ** 8 + x ** 4 + x ** 3 + x + x ** 0
q = lambda x: x ** 8 + x ** 7 + x ** 6 + x ** 5 + x ** 4 + x ** 2 + x ** 0

5.3 遍历搜索

for i in range(2 ** 8):
    # 遍历 F_2[x]/q(x) 的元素
    t = GF256(i, qx)
    if p(t).value == 0:  # 满足p(t)=0
        print(bin(t.value))

得到8个结果

0b100000
0b110011
0b111110
0b1110000
0b10011111
0b10100110
0b10101010
0b11001110

5.4 结果

\(\alpha = \overline{x} \; mod \; p(x)\)\(p(x)\) 的一个根
\(\beta = \overline{x} \; mod \; q(x)\)\(q(x)\) 的一个根

上述结果也就是找到了8个映射关系,分别为

关系
0b100000 \(\alpha \to \beta^5\)
0b110011 \(\alpha \to \beta^5 + \beta^4 + \beta + \beta^0\)
0b111110 \(\alpha \to \beta^5 + \beta^4 + \beta^3 + \beta^2 + \beta^1\)
0b1110000 \(\alpha \to \beta^6 + \beta^5 + \beta^4\)
0b10011111 \(\alpha \to \beta^7 + \beta^4 + \beta^3 + \beta^2 + \beta^1 + \beta^0\)
0b10100110 \(\alpha \to \beta^7 + \beta^5 + \beta^2 + \beta^1\)
0b10101010 \(\alpha \to \beta^7 + \beta^5 + \beta^3 + \beta^1\)
0b11001110 \(\alpha \to \beta^7 + \beta^6 + \beta^3 + \beta^2 + \beta^1\)

六、有限域同构与密码学

在例如 AES 和 SM4 这类对称密码的 S 盒变换的底层,所使用的就是有限域 \(GF(2^8)\) 的求逆变换(除了求逆还涉及一些仿射变换)。

如果采用硬件(例如FPGA)实现密码算法,可将 \(GF(2^8)\) 的同构于 \(GF((2^4)^2)\) 复合域甚至同构于 \(GF(((2^2)^2)^2)\) 复合域,便于分析有限域的求逆表达式,使用逻辑函数代替原先的查表运算,能够节省门电路资源

如果使用软件实现,可以利用有限域同构关系将 SM4 的 S盒 转化为 AES 的 S盒,利用 AES 指令集完成 SM4 的 S盒 操作

七、求解复合域同构映射的示例代码

(--- 2023.11.24 更新 ---)

下面给出复合域同构映射的示例python代码,用于搜索SM4算法对应的复合域,参考论文是陈晨等人的《一种基于复合域的国密SM4算法快速软件实现方法》。论文里有比本博客更详细的原理介绍,流程详见论文中的算法1.

陈晨,郭华,王闯等.一种基于复合域的国密SM4算法快速软件实现方法[J].密码学报,2023,10(02):289-305.

python代码需要提前安装好一个有关复合域运算的库 gf2lib,通过指令 pip install gf2lib 即可安装。下方代码实现了Gf242复合域类以及Gf28有限域类,使用论文中的搜索算法搜索出复合条件的映射矩阵。代码的输出结果和论文中给出的数据完全一致

# -*- coding:utf-8 -*-
"""
需要安装的包:gf2lib
类:Gf242
    GF(2^4^2)复合域元素,为F[x]/(P(x),Q(y)),P(x) = x^2 + x + 4, Q(y) = y^4 + y^3 + 1
    支持加、减、乘、幂、判等运算
    (1,0)代表单位元e
类:Gf28
    GF(2^8)元素,为F[x]/r(x), r(x) = x^8 + x^7 + x^6 + x^5 + x^4 + x^2 + 1,即SM4复合域
    支持加、减、乘、幂、判等运算
函数:gf28_items
函数:gf242_items
函数:gf242_p
函数:gf28_p
函数:cast_gf28_to_gf242
函数:cast_gf242_to_gf28

功能1:搜索GF(2^4^2)本原元
功能2:搜索指定GF(2^8)和GF(2^4^2)的映射矩阵
"""
from math import gcd
from gf2lib import gf2poly
from gf2lib.gf2matrix import GF2Matrix
from typing import Tuple, List


class Gf28:
    @staticmethod
    def one():
        """单位元"""
        return Gf28(1)

    @staticmethod
    def zero():
        """零元"""
        return Gf28(0)

    def __init__(self, n: int):
        self.n = n

    def __mul__(self, other):
        sm4_poly = 0b111110101  # x^8 + x^7 + x^6 + x^5 + x^4 + x^2 + 1
        return Gf28(gf2poly.mul(self.n, other.n, sm4_poly))

    def __add__(self, other):
        return Gf28(self.n ^ other.n)

    def __pow__(self, power, modulo=None):
        assert not (power == 0 and self.n == 0)
        r = Gf28.one()
        for _ in range(power):
            r = r * self
        return r

    def __eq__(self, other):
        return self.n == other.n

    def __str__(self):
        return str(self.n)


class Gf242:
    def __init__(self, a: Tuple[int, int]):
        self.a = a

    @staticmethod
    def gf24_mul(a: int, b: int) -> int:
        gf24_poly = 0b11001  # y^4+y^3+1
        return gf2poly.mul(a, b, gf24_poly)

    @staticmethod
    def one():
        """单位元"""
        return Gf242((1, 0))

    @staticmethod
    def zero():
        """零元"""
        return Gf242((0, 0))

    def __add__(self, other):
        return Gf242((self.a[0] ^ other.a[0], self.a[1] ^ other.a[1]))

    def __mul__(self, other):
        # P(x) = x^2 + x + 4
        a0, a1 = self.a[0], self.a[1]
        b0, b1 = other.a[0], other.a[1]
        # c2x^2 + c1x + c0
        c0 = Gf242.gf24_mul(a0, b0)
        c1 = Gf242.gf24_mul(a0, b1) ^ Gf242.gf24_mul(a1, b0)
        c2 = Gf242.gf24_mul(a1, b1)
        # c2x^2 = c2x + 4*c2
        r0 = c0 ^ Gf242.gf24_mul(c2, 4)
        r1 = c1 ^ c2
        return Gf242((r0, r1))

    def __pow__(self, power, modulo=None):
        assert not (power == 0 and self == Gf242.zero())
        r = Gf242.one()
        for _ in range(power):
            r = r * self
        return r

    def __eq__(self, other):
        return self.a == other.a

    def __str__(self):
        return str(self.a)


def gf28_items() -> List[Gf28]:
    """返回GF(2^8)所有元素"""
    return [Gf28(a) for a in range(256)]


def gf242_items() -> List[Gf242]:
    """返回GF(2^4^2)中所有元素"""
    return [Gf242((a0, a1)) for a0 in range(16) for a1 in range(16)]


def gf242_p(a: Gf242) -> Gf242:
    """带入至GF(2^4^2)多项式"""
    return a * a + a + Gf242((4, 0))


def gf28_p(a):
    """带入至GF(2^8)多项式"""
    # x^8 + x^7 + x^6 + x^5 + x^4 + x^2 + 1
    return a ** 8 + a ** 7 + a ** 6 + a ** 5 + a ** 4 + a ** 2 + a ** 0


def cast_gf28_to_gf242(a: Gf28, T: GF2Matrix) -> Gf242:
    """将GF(2^8)元素映射至GF(2^4^2)

    :param a: GF(2^8)元素
    :param T: 映射矩阵
    :return: T*a
    """
    b = T * GF2Matrix.from_int(a.n, 8)
    b = b.to_int()
    return Gf242((b & 0x0F, b >> 4))


def cast_gf242_to_gf28(a: Gf242, T: GF2Matrix) -> Gf28:
    """将GF(2^4^2)元素映射至GF(2^8)

    :param a: GF(2^4^2)元素
    :param T: 映射矩阵
    :return: T*a
    """
    b = T * GF2Matrix.from_int((a.a[1] << 4) + a.a[0], 8)
    b = b.to_int()
    return Gf28(b)


# 计算GF242本原元,得到(0,1)和(1,1),即x和1+x
print("GF242本原元:")
for g in gf242_items():
    flag = True
    if gf242_p(g) != Gf242.zero():
        flag = False
    t = g
    for i in range(2, 255):
        t = t * g
        if t == Gf242.one():
            flag = False
    if flag:
        print(g)

print("搜索映射矩阵:beta=", (0, 1))
result = []
# step1 选择本原元 x
beta = Gf242((0, 1))
flag = [1 for _ in range(256)]
t = 1
while t <= 255:
    # step2
    beta_t = beta ** t
    if gf28_p(beta_t) == Gf242.zero():
        result.append(beta_t)
        t = t + 1
    # step3
    else:
        for j in range(8):
            flag[(t * (2 ** j)) % 255] = 0
    # step4,5
    t = t + 1
    while flag[t] == 0 or gcd(t, 255) > 1:
        t = t + 1
        if not t <= 255:
            break

for beta in result:
    # 打印结果
    print("满足条件的beta^t: ", beta, ", 映射矩阵 col 0-7: ", end='')
    for i in range(7, -1, -1):
        a = beta ** i
        print((a.a[1] << 4) + a.a[0], end=', ')
    print()
    # 计算映射矩阵
    M = GF2Matrix.from_int(0b00000001, 8)  # (0, 0, ..., 1)
    for i in range(1, 8):
        a = beta ** i
        a = (a.a[1] << 4) + a.a[0]
        M = GF2Matrix.from_int(a, 8) | M
    # 计算映射和逆映射矩阵
    T = M
    T_inv = M.inverse()
    # # 测试乘法是否满足同构,遍历所有元素
    # for i in range(256):
    #     for j in range(256):
    #         a28, b28 = Gf28(i), Gf28(j)
    #         a242 = cast_gf28_to_gf242(a28, T)
    #         b242 = cast_gf28_to_gf242(b28, T)
    #         assert a28 * b28 == cast_gf242_to_gf28(a242 * b242, T_inv)
    #         assert a28 + b28 == cast_gf242_to_gf28(a242 + b242, T_inv)
    # 打印映射矩阵
    for item in T.transpose().matrix:
        print(item)
posted @ 2021-12-04 23:16  kentle  阅读(2803)  评论(17编辑  收藏  举报