文章目录

  • 一、前言
  • 二、数学基础
    • 1、GF(2⁸)有限域内的多项式
    • 2、不可约多项式
    • 3、多项式模运算
    • 3、乘法逆元
  • 三、算法步骤
    • 1、扩展欧几里得算法
    • 2、多项式除法
    • 3、多项式乘法
  • 四、代码实现
    • 1、多项式除法
    • 2、多项式乘法
    • 3、欧几里得算法
    • 4、配上一个主程序
  • 五、心得

一、前言

在写这篇博客前,笔者刚赶完密码学与信息安全的实验报告,用了一天把这个问题涉及的算法仔仔细细啃了一遍,忍不住想写一篇博客。为什么呢?因为笔者昨天在查找资料时真的吐槽到无力!!各大博客网站的博文基本就那几篇,搬来搬去也不加自己的理解,甚至代码都没自己调通一遍。。。另外S_box相关问题的博文倒有几篇不错的,可惜基本都是C或者Java写的,终于看到一个Python的了,那代码冗杂得完全就是C直接翻译过来的,重点还是错的。。。最后,声明一下,笔者上课基本睡觉,涉及的知识基本就这两天看的William Stallings的那本密码编码学P86页,所以知识水平不高,以下写的内容,目标都是编出能用且优雅的代码,Heavy Math只说明不解释。

笔者期望好好写篇关于AES乘法逆元的博文,力求讲清楚每个算法,以免后来人爬我爬过的坑,如果你在这篇文章找到了解决方案,点个赞再走呗(づ ̄3 ̄)づ╭❤~

二、数学基础

1、GF(2⁸)有限域内的多项式

规定GF(2⁸)中的多项式
f(x)=a7x7+a6x6+⋯+a1x+a0=∑i=07aixif(x)=a_{7}x^{7}+a_{6}x^{6}+\cdots+a_1x+a_0=\sum_{i=0}^{7}a_ix^if(x)=a7​x7+a6​x6+⋯+a1​x+a0​=i=0∑7​ai​xi
其系数 aia_iai​ 只能为1或者0,则该多项式可以由组成它的二进制系数 (a7,a6,a5,a4,a3,a2,a1,a0)(a_7,a_6,a_5,a_4,a_3,a_2,a_1,a_0)(a7​,a6​,a5​,a4​,a3​,a2​,a1​,a0​) 组成。将这些数字按高位到低位排列,则可以形成一个二进制整数,整数的范围为0~256,代表了有限域中的256个多项式。

2、不可约多项式

大部分场景,包括S_box问题中,都遇到一个特殊的多项式 m(x)=x8+x4+x3+x+1m(x)=x^8+x^4+x^3+x+1m(x)=x8+x4+x3+x+1 ,称之为不可约多项式。

简单来说,相当于自然数中的质数,也就是它的的因式只有1和它本身,所以称为不可约多项式。

3、多项式模运算

到了这里,笔者开始飞炸,觉得自己15年读了个假数学。。。认真看了会书,笔者才看懂,原来多项式运算分为3种:

  • 使用代数基本规则的普通多项式运算
  • 系数运算是模 ppp 运算的多项式运算,即系数在 GF(p)GF(p)GF(p) 中
  • 系数在 GF(p)GF(p)GF(p) 中,且多项式被定义为模一个 nnn 次多项式 m(x)m(x)m(x) 的多项式运算

所以,我们的乘法逆元要用到的就是第三种,也就是按正常运算完后再对一个 m(x)m(x)m(x) 取余数,才是最终运算结果。惊了吧,15年就只学了个普通数学!!!

接下来笔者就举一个例子,各位读者。。爱看不看。。

现在假设这个m(x)m(x)m(x) 就是我们刚才说的不可约多项式 m(x)=x8+x4+x3+x+1m(x)=x^8+x^4+x^3+x+1m(x)=x8+x4+x3+x+1,对于多项式 f(x)=x6+x4+x2+x+1f(x)=x^6+x^4+x^2+x+1f(x)=x6+x4+x2+x+1 和 g(x)=x7+z+1g(x)=x^7+z+1g(x)=x7+z+1 ,做它们的加法和乘法。

坐稳了,这车我也不知道往哪开了。。。

惨不忍睹的加法:
f(x)+g(x)=x7+x6+x4+x2f(x)+g(x)=x^7+x^6+x^4+x^2f(x)+g(x)=x7+x6+x4+x2
匪夷所思的乘法:
f(x)×g(x)=f(x)×g(x)modm(x)=x7+x6+1f(x)\times g(x)=f(x)\times g(x) mod m(x)=x^7+x^6+1f(x)×g(x)=f(x)×g(x)modm(x)=x7+x6+1

总而言之,在这种运算规则中,做加法时,两边都有的幂次项会消失,只有一边有的幂次项会保留,也就是异或,具体原因请查模运算法则

至于乘法和除法的就相当复杂了,我们在算法步骤中再仔细说明,要详细解释的话就成数论博文了,当笔者只是个码农啊啊啊。

3、乘法逆元

在有限域中我们来定义:
b(x)×b−1(x)mod  a(x)=1b(x)\times b^{-1}(x)\mod a(x)=1b(x)×b−1(x)moda(x)=1

满足这个条件的 b−1(x)b^{-1}(x)b−1(x) 则称为 b(x)b(x)b(x) 模 a(x)a(x)a(x) 的乘法逆元。上述条件等价于下面这个条件:
a(x)v(x)+b(x)w(x)=1a(x)v(x)+b(x)w(x)=1a(x)v(x)+b(x)w(x)=1
这里的 w(x)w(x)w(x) 就是要求的乘法逆元。所以这就是我们最终要解决的问题啦,解出这个多项式等式就可以了。做过自然数乘法逆元的应该就很熟悉,用扩展欧几里得算法可以解决这个问题。

三、算法步骤

1、扩展欧几里得算法

关于扩展欧几里得算法,笔者不想重复书上的内容去解释这个内容,我们只看算法步骤,因为笔者对欧几里得算法的体验也只是到辗转相除法,再后面变化出来的妖魔鬼怪算法一律很务实地没看了。

我们先做一些符号的约定

符号 含义
a(x)a(x)a(x) 不可约多项式
b(x)b(x)b(x) 求乘法逆元的多项式
q(x)q(x)q(x) 整除的商多项式
r(x)r(x)r(x) 除法产生的余数多项式
v(x)v(x)v(x) 系数多项式
w(x)w(x)w(x) 所求的乘法逆元

接下来用最简单的方式来看这个算法的过程,笔者也是只看了书上那一页的内容写出来的代码:

第一步
r−1(x)=a(x),v−1=1,w−1=0r_{-1}(x)=a(x),v_{-1}=1,w_{-1}=0r−1​(x)=a(x),v−1​=1,w−1​=0
第二步
r0(x)=b(x),v0=0,w0=1r_{0}(x)=b(x),v_{0}=0,w_{0}=1r0​(x)=b(x),v0​=0,w0​=1
第三步
r1(x)=a(x)mod  b(x),q1=a(x)∣b(x),v1=v−1−q1(x)v0(x),w1=w−1−q1(x)w0(x)r_{1}(x)=a(x)\mod b(x),q_{1}=a(x)|b(x),v_{1}=v_{-1}-q_1(x)v_0(x),w_{1}=w_{-1}-q_1(x)w_0(x)r1​(x)=a(x)modb(x),q1​=a(x)∣b(x),v1​=v−1​−q1​(x)v0​(x),w1​=w−1​−q1​(x)w0​(x)
第四步
r2(x)=a(x)mod  b(x),q2=a(x)∣b(x),v2=v0−q2(x)v1(x),w2=w0−q2(x)w1(x)r_{2}(x)=a(x)\mod b(x),q_{2}=a(x)|b(x),v_{2}=v_{0}-q_2(x)v_1(x),w_{2}=w_{0}-q_2(x)w_1(x)r2​(x)=a(x)modb(x),q2​=a(x)∣b(x),v2​=v0​−q2​(x)v1​(x),w2​=w0​−q2​(x)w1​(x)
第五步
r3(x)=a(x)mod  b(x),q3=a(x)∣b(x),v3=v1−q3(x)v2(x),w3=w1−q3(x)w2(x)r_{3}(x)=a(x)\mod b(x),q_{3}=a(x)|b(x),v_{3}=v_{1}-q_3(x)v_2(x),w_{3}=w_{1}-q_3(x)w_2(x)r3​(x)=a(x)modb(x),q3​=a(x)∣b(x),v3​=v1​−q3​(x)v2​(x),w3​=w1​−q3​(x)w2​(x)
……
……
……
直到出现 rn(x)=0r_n(x)=0rn​(x)=0 时,此时得到逆元为 wn−1(n)w_{n-1}(n)wn−1​(n)。

那么有了算法步骤,构造一个递归函数就不难了

def poly_gcd(r1, r2, v1=1, v2=0, w1=0, w2=1):# 从第三步开始呈现递归规律,所以初值默认为第三步开始时if r2 == 0 or r2 == 1:   return w2# 做多项式除法 r1 ÷ r2 = q3 …… r3q3, r3 = ...# 计算v3 = v1 - q3 * v2# 计算w3 = w1 - q3 * w2v3, w3 = ...# 将几个值按位依次赋值,作为下一次的参数,就可以实现递归了return poly_gcd(r2, r3, v2, v3, w2, w3)

上面的算法思路与自然数求逆元的思路完全一模一样,而且,我们已经定义了多项式可以和有限域内的二进制整数一一对应起来,这就意味着,唯一的区别只是多项式的乘法和除法与代数的计算规则不太一样,那我们只需要自己定义好多项式乘法和除法,就可以解决问题了!

2、多项式除法

我们已经知道了,多项式的除法其实就是在二进制的除法的基础上加了一点东西而已,那么仔细观察有理多项式的长除法,将幂次项变为一个个1和0,很快我们就可以找到计算规律。

先回忆一下10进制怎么做的除法,例如 4890÷164890\div 164890÷16

第一步,拿48除以16,商值为3,而4890比16多了两个数量级,所以商的数量级为10²(左移两位)。余数为4890-300×16,进入第二次除法。

第二步,拿09除以16,商值为0,被除数数量级比除数大1,商的数量级为10。余数为被除数,进入第三次除法。

第三步,拿90除以16,商值为5,90和16同数量级,商数量级为1。余数90-5*16,进入第四次除法。

第四步,拿10除以16,本位得0,余数为被除数,已经小于除数且是最低位了,计算结束。

第五步,将前面的商加起来3×100+0×10+5×1为最终的商,余数为最后一步的余数。

同样的道理,计算二进制的除法,例如 (11101)2÷(10)2(11101)_2\div(10)_2(11101)2​÷(10)2​,区别在于二进制只有0和1,这就出现了一些很有趣的现象,比如判断被除数能否除除数的时候只要比较最高非零位数就可以,被除数减去除数乘以商得到余数的时候,因为每一次除法的商始终是商值为1数量级为n,所以商去乘除数的时候就相当于将除数左移n位,然后与被除数做异或运算(即模2加法)。

第一步,11101比10大3个数量级,商为1,数量级为3。余数为11101-10<<3=11101-10000=01101,进入第二次除法。

第二步,01101比10大2个数量级,商为1,数量级为2。余数为01101-10<<2=01101-1000=00101,进入第三次除法。

第三步,00101比10大1个数量级,商为1,数量级为1。余数为00101-10<<1=00101-100=00001,进入第四次除法。

第四步,00001比10小,商为0,余数为1.

第五步,将所有商加起来,1<<3 + 1<<2 + 1<<1 + 0 = 1110。余数为1。

所以结果就是 (11101)2÷(10)2=(1110)2⋯(1)2(11101)_2\div(10)_2=(1110)_2\cdots(1)_2(11101)2​÷(10)2​=(1110)2​⋯(1)2​ ,还原成多项式形式就是:
(x4+x3+x2+1)÷(x)=(x3+x2+x)mod&ThinSpace;&ThinSpace;1(x_4+x_3+x_2+1)\div(x)=(x^3+x^2+x)\mod1(x4​+x3​+x2​+1)÷(x)=(x3+x2+x)mod1
不可思议对吧,你我都不知道这是什么鬼,可是按运算规则这就是对的。。。

3、多项式乘法

乘法的思路也一样,是从十进制的方法到二进制的,只是在模2运算也就是做加法的时候遵循了另一套计算规则。举个例子,计算 (11011)2×(1110)2(11011)_2\times(1110)_2(11011)2​×(1110)2​ ,乘法比除法简单太多了。

我们可以把这个计算拆开成为:
(11011)2×(1000)2+(11011)2×(100)2+(11011)2×(10)2+(11011)2×(0)2(11011)_2\times(1000)_2+(11011)_2\times(100)_2+(11011)_2\times(10)_2+(11011)_2\times(0)_2(11011)2​×(1000)2​+(11011)2​×(100)2​+(11011)2​×(10)2​+(11011)2​×(0)2​
而且我们知道对于每一个乘式,都是对左数移位,也就是:
(11011)2&lt;&lt;3+(11011)2&lt;&lt;2+(11011)2&lt;&lt;1(11011)_2&lt;&lt;3+(11011)_2&lt;&lt;2+(11011)_2&lt;&lt;1(11011)2​<<3+(11011)2​<<2+(11011)2​<<1
也就是当第n位非零是,左数便左移相应的n位,最后相加就是最终的结果了:
(11011)2×(1110)2=(10000010)2(11011)_2\times(1110)_2=(10000010)_2(11011)2​×(1110)2​=(10000010)2​

四、代码实现

1、多项式除法

# 求最高幂次数
def Nonzero_MSB(value):v2str = '{:09b}'.format(value)for i in range(9):if int(v2str[i]):return 9-i# 模2除法:m为被除数。b为除数,q为商,r为余数
def Mode2_div(fx, gx):n = Nonzero_MSB(fx)m = Nonzero_MSB(gx)if n < m:return [0, fx]deg = n - mfx = fx ^ (gx << deg)[q, r] = Mode2_div(fx, gx) return [(1 << deg)|q, r]

2、多项式乘法

# v3 = v1 - q3 * v2
def Calculate(v1, q3, v2):value = 0for i in range(32):if(q3 & (1<<i)):value = value ^ (v2<<i)return v1^value

3、欧几里得算法

def poly_gcd(r1, r2, v1=1, v2=0, w1=0, w2=1):if r2==0 or r2==1:  return w2q3, r3 = Mode2_div(r1, r2)  # q3(x)=r1(x)|r2(x), r2(x)=r1(x) mod r2(x)v3 = Calculate(v1, q3, v2)  # v3 = v1 - q3 * v2w3 = Calculate(w1, q3, w2)  # w3 = w1 - q3 * w2return poly_gcd(r2,r3,v2,v3,w2,w3)

4、配上一个主程序

def sym2int(sym):power = [sym[i+2] for i in range(len(sym)) if sym[i] == 'x']if '+1' in sym: power.append('0')data = 0for p in power:data = data | (1<<int(p))return datadef int2sym(data):int2str = '{:09b}'.format(data)sym = ''for i in range(9):if int(int2str[i]) == 1:if 8-i:   sym += '+x^%d'%(8-i)else:   sym += '+1'return sym[1:]if __name__ == '__main__':xstr = input('请输入一个多项式(注意以x为变量,幂次以^表示):')# xstr = 'x^7+x+1'print('---- 多项式乘法逆元求解完成 ----')print('>>你输入的多项式 :', xstr)print('>>默认既约多项式 :', int2sym(283))print('>>输出的乘法逆元 :', int2sym(poly_gcd(283, sym2int(xstr))

放一张运行结果图,可以当标准数据来调试:

五、心得

一直以来认为这一点:不要死嗑数学,理论归理论,工程归工程。记得用Matlab写高斯消元法解线性方程组的时候,书上已经归纳出了一个递归迭代的求求和式了,所以应该想的是如何更优雅地利用这个数学结论去完成这个函数的功能,而不是死磕为什么,那是课堂上该做的(当然,笔者上课都是睡觉度过,所以也当笔者在找个合适的借口吧哈哈哈哈哈)!

Python在GF(2⁸)有限域上求解多项式的乘法逆元——基于扩展欧几里得算法相关推荐

  1. GF(2^8)上的多项式乘法(Matlab实现)

    文章目录 一.解析/思路 二.代码 三.Main 1.Poly_2_8 2.Func1 3.Func2 一.解析/思路 Main脚本:GF(2^8)上的多项式转换为1·8的数组 Poly_2_8函数: ...

  2. 扩展欧几里得算法 有限域上多项式求逆

    今年网络安全的一个小作业,简单用C++实现了下 有些粗糙 先放这儿吧 ^_^ 算法描述 考完试再附上 ExEuclid简单实现/* * 文件名称:myecu.cpp * 摘 要:Extend Eucl ...

  3. 如何利用扩展欧几里得算法求解不定方程_客户端不用的算法系列:从头条笔试题认识扩展欧几里得算法...

    难度较高,阅读时间大概 28 分钟 这是数论的第二篇,在<素数筛法>中,我们重温了素数这个数学定义,并且给出了区别于教科书上更高效的 Eratosthenes 筛法和欧拉线性筛.这篇文会从 ...

  4. C++ 二元一次不定方程巧妙求解——运用扩展欧几里得算法

    前言 在关于数论的学习中,求解二元一次不定方程是很重要的,在学习求解二元一次不定方程之前,要先了解欧几里得算法和扩展欧几里得算法. 关于数论的学习 欧几里得算法 欧几里得算法就是辗转相除法,欧几里得算 ...

  5. 扩展欧几里得算法 求解 丢番图方程

    丢番图方程: 有一个或者几个变量的整系数方程,它们的求解仅仅在整数范围内进行. a * x + b * y = c  ( 其中所有数均为整数, 已知 x, y, c )        例如:鸡兔同笼问 ...

  6. Python:实现extended euclidean algorithm扩展欧几里得算法(附完整源码)

    Python:实现extended euclidean algorithm扩展欧几里得算法 from __future__ import annotationsimport sysdef extend ...

  7. 扩展欧几里得算法、ax+by=c求解、ax≡c(mod m)、逆元求解、(b/a)%m计算c++代码

    参考 <算法笔记>(胡凡) 扩展欧几里得算法 求解ax+ by = gcd(a, b) int exGcd(int a, int b, int &x, int &y) {i ...

  8. 如何利用扩展欧几里得算法求解不定方程_欧几里德算法、拓展欧几里德、中国剩余定理...

    01.欧几里德算法(Euclidean algorithm)(辗转相除法) 欧几里德算法又称辗转相除法,主要是用于计算两个整数a,b的最大公约数. 简单点说一下算法原理:两个整数的最大公约数等于其中小 ...

  9. 构建一阶谓词逻辑和有限域上多项式方程的同构

    构建一阶谓词逻辑和有限域上多项式方程的同构 基于命题逻辑的布尔可满足SAT存在描述能力弱.抽象层次低.求解复杂度高等问题,而基于一阶逻辑的可满足性模理论SMT(或称之为FOLMS问题:一阶逻辑的可满足 ...

最新文章

  1. PHP大数组过滤元素、修改元素性能分析
  2. WM_CHAR、WM_KEYDOWN和WM_SYSKEYDOWN消息
  3. Spring Batch可重启性
  4. C++学习之路 | PTA乙级—— 1070 结绳 (25 分)(精简)
  5. java通过桥访问excel_通过jdbc-odbc桥来访问excel文件
  6. Delphi unit单元文件结构
  7. 1000道Python题库系列分享23(61个填空题)
  8. 大学生职业发展与就业指导 中国大学mooc 福州大学 测验题目和答案
  9. 【转】win10安装caffe教程
  10. 七号信令:信令网基本概念
  11. Flutter初步-第一个电视直播APP
  12. 《亲密关系》读书笔记
  13. tidb分布式数据库_TiDB如何在分布式数据库中结合OLTP和OLAP
  14. html 自动字体大小,根据屏幕大小自动修改字体大小的代码
  15. 几种常用的服务器认证机制
  16. 人工智能研究中心快递柜——代码分析十
  17. 女人喝酸奶要注意什么
  18. 宝元系统通讯软件recon_优软科技会场式电话录音系统
  19. 舒适区、学习区、恐慌区
  20. matplotlib入门基础(五)轴坐标范围 轴刻度比例 轴刻度

热门文章

  1. 华为模拟器ensp VLAN与三层交换机实验
  2. 三种设计师常用的字体设计手法
  3. p图你还在用ps么 程序员该怎么P图
  4. 软件项目开发计划【列文】2022.5.11
  5. javaWeb项目不报错但网页报500错误
  6. 深度学习模型模拟大脑地形图,有助于回答大脑不同部分如何协同工作
  7. js 实现上拉加载和下拉刷新
  8. APN:使用AT+CGDCONT命令设置modem默认APN
  9. boss自动化投递简历
  10. 高德地图WebAPI:行驶距离测量