【问题标题】:pyfinite gives wrong result for multiplication in field GF(2^8)pyfinite 在字段 GF(2^8) 中给出错误的乘法结果
【发布时间】:2019-01-04 13:19:20
【问题描述】:

我正在使用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?如何解决?

【问题讨论】:

  • 您能否再格式化和/或注释您的手工数学?我很难跟上它。已经有一段时间了,但我遵循了Wikipedia's 的指导并像 pyfinite 一样得到了 0xdc。 (编辑:我猜这更像是一个数学问题而不是编程问题。)
  • @glibdud 只需一分钟,让我的手解决得更好
  • @glibdud 我按照你的要求做了并更新了我的问题,包括手动解决乳胶详细格式
  • 怎么知道模数是0x11B?
  • @MattTimmermans 这是我们几天前在大学学习的方式,但我不知道我是否误解了这里的总结:在 AES 的 MixColumns 阶段将任何数字 X 乘以 03 时,我们将 X 乘以 02然后用 X 异或。将 X 乘以 2 如下:我们将 X 转换为二进制表示,如果它是 1 或 0,我们查看最左边的位,然后将 X 向左移动 1,如果最左边的位是 1,则将其与 0x1B 进行异或运算。我不知道我是否将我们所学的内容与我在网上阅读的关于 AES 的内容混淆了我认为我们所学的是乘以 GF(2^8) 的快捷方式

标签: python aes finite-field


【解决方案1】:

我对 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'

【讨论】:

  • 我可以确认 AES 使用 0x11b,其中所有非零元素都可以被认为是 0x03 的某个幂。对于 0x11d,所有非零元素都可以认为是 0x02 的幂。大多数涉及有限域的实现都会选择一个多项式,其中所有非零元素都是 2 的幂。我不知道为什么 AES 选择 0x11b。
【解决方案2】:

问题在于 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-24
    • 2023-04-07
    • 1970-01-01
    • 2014-11-29
    • 1970-01-01
    • 2014-01-11
    • 1970-01-01
    相关资源
    最近更新 更多