我正在使用pyfinte来计算AES在它使用的字段F(2 ^ 8)上的乘法,但是当我执行以下操作时:
from pyfinite import ffield
a = 0xbf
b = 0x03
F = ffield.FField(8)
c = F.Multiply(a, b)
print(hex(c))
实际结果是0xdc,但应该是0xda,这是我手动解决的方法:
0xbf * 0x03 = 0xbf * 0x02 + 0xbf * 0x01 = 0b10111111 * 0x02 + 0xbf = 0b01111110 + 0x1B + 0xbf = 0b11011010 = 0xda
这是我的手爱抚的更好形式:
那哪里错了?是我手工解决的吗?还是在pyfinite中?该如何解决?
答案 0 :(得分:2)
我对AES并不十分熟悉,但是从您提供的链接来看,该字段的生成多项式似乎是0x11b。默认情况下,pyfinite使用不同的生成器,它将生成不同的乘法结果:
>>> f = ffield.FField(8)
>>> hex(f.generator)
'0x11d'
如果在创建字段对象时指定生成器,则会得到期望的结果:
>>> f = ffield.FField(8, gen=0x11b, useLUT=0)
>>> hex(f.Multiply(0xbf, 0x03))
'0xda'
答案 1 :(得分:0)
问题在于 AES 为其扩展字段使用了一个不可约但不是原始的多项式。大多数扩展字段使用原始多项式,因此 x
是该字段的原始元素。我想这就是 pyfinite 的默认设置。
相反,AES 使用 x^8 + x^4 + x^3 + x + 1
作为其不可约多项式,并将 x + 1
作为原始元素(或乘法群的生成器)。
虽然我不知道 pyfinite 的详细信息,但我创建了一个类似的库 galois,它扩展了 NumPy 数组以对 Galois 字段进行操作。它支持任意大小的数组算术、伽罗瓦域矩阵上的线性代数、伽罗瓦域上的多项式等。该库是用 Python 编写的,但使用 Numba 进行 JIT 编译,因此数组算法是 as fast as native NumPy。
这是一个实现您想要的示例。
In [1]: import galois
In [2]: GF = galois.GF(2**8, irreducible_poly=0x11b)
In [3]: print(GF.properties)
GF(2^8):
characteristic: 2
degree: 8
order: 256
irreducible_poly: x^8 + x^4 + x^3 + x + 1
is_primitive_poly: False
primitive_element: x + 1
In [4]: a = GF(0xbf); a
Out[4]: GF(191, order=2^8)
In [5]: b = GF(0x03); b
Out[5]: GF(3, order=2^8)
In [6]: a * b
Out[6]: GF(218, order=2^8)
In [7]: 0xda
Out[7]: 218