Python在GF(2⁸)有限域上求解多项式的乘法逆元——基于扩展欧几里得算法
文章目錄
- 一、前言
- 二、數(shù)學(xué)基礎(chǔ)
- 1、GF(2?)有限域內(nèi)的多項(xiàng)式
- 2、不可約多項(xiàng)式
- 3、多項(xiàng)式模運(yùn)算
- 3、乘法逆元
- 三、算法步驟
- 1、擴(kuò)展歐幾里得算法
- 2、多項(xiàng)式除法
- 3、多項(xiàng)式乘法
- 四、代碼實(shí)現(xiàn)
- 1、多項(xiàng)式除法
- 2、多項(xiàng)式乘法
- 3、歐幾里得算法
- 4、配上一個(gè)主程序
- 五、心得
一、前言
在寫這篇博客前,筆者剛趕完密碼學(xué)與信息安全的實(shí)驗(yàn)報(bào)告,用了一天把這個(gè)問(wèn)題涉及的算法仔仔細(xì)細(xì)啃了一遍,忍不住想寫一篇博客。為什么呢?因?yàn)楣P者昨天在查找資料時(shí)真的吐槽到無(wú)力!!各大博客網(wǎng)站的博文基本就那幾篇,搬來(lái)搬去也不加自己的理解,甚至代碼都沒自己調(diào)通一遍。。。另外S_box相關(guān)問(wèn)題的博文倒有幾篇不錯(cuò)的,可惜基本都是C或者Java寫的,終于看到一個(gè)Python的了,那代碼冗雜得完全就是C直接翻譯過(guò)來(lái)的,重點(diǎn)還是錯(cuò)的。。。最后,聲明一下,筆者上課基本睡覺,涉及的知識(shí)基本就這兩天看的William Stallings的那本密碼編碼學(xué)P86頁(yè),所以知識(shí)水平不高,以下寫的內(nèi)容,目標(biāo)都是編出能用且優(yōu)雅的代碼,Heavy Math只說(shuō)明不解釋。
筆者期望好好寫篇關(guān)于AES乘法逆元的博文,力求講清楚每個(gè)算法,以免后來(lái)人爬我爬過(guò)的坑,如果你在這篇文章找到了解決方案,點(diǎn)個(gè)贊再走唄(づ ̄3 ̄)づ╭?~
二、數(shù)學(xué)基礎(chǔ)
1、GF(2?)有限域內(nèi)的多項(xiàng)式
規(guī)定GF(2?)中的多項(xiàng)式
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
其系數(shù) aia_iai? 只能為1或者0,則該多項(xiàng)式可以由組成它的二進(jìn)制系數(shù) (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?) 組成。將這些數(shù)字按高位到低位排列,則可以形成一個(gè)二進(jìn)制整數(shù),整數(shù)的范圍為0~256,代表了有限域中的256個(gè)多項(xiàng)式。
2、不可約多項(xiàng)式
大部分場(chǎng)景,包括S_box問(wèn)題中,都遇到一個(gè)特殊的多項(xiàng)式 m(x)=x8+x4+x3+x+1m(x)=x^8+x^4+x^3+x+1m(x)=x8+x4+x3+x+1 ,稱之為不可約多項(xiàng)式。
簡(jiǎn)單來(lái)說(shuō),相當(dāng)于自然數(shù)中的質(zhì)數(shù),也就是它的的因式只有1和它本身,所以稱為不可約多項(xiàng)式。
3、多項(xiàng)式模運(yùn)算
到了這里,筆者開始飛炸,覺得自己15年讀了個(gè)假數(shù)學(xué)。。。認(rèn)真看了會(huì)書,筆者才看懂,原來(lái)多項(xiàng)式運(yùn)算分為3種:
- 使用代數(shù)基本規(guī)則的普通多項(xiàng)式運(yùn)算
- 系數(shù)運(yùn)算是模 ppp 運(yùn)算的多項(xiàng)式運(yùn)算,即系數(shù)在 GF(p)GF(p)GF(p) 中
- 系數(shù)在 GF(p)GF(p)GF(p) 中,且多項(xiàng)式被定義為模一個(gè) nnn 次多項(xiàng)式 m(x)m(x)m(x) 的多項(xiàng)式運(yùn)算
所以,我們的乘法逆元要用到的就是第三種,也就是按正常運(yùn)算完后再對(duì)一個(gè) m(x)m(x)m(x) 取余數(shù),才是最終運(yùn)算結(jié)果。驚了吧,15年就只學(xué)了個(gè)普通數(shù)學(xué)!!!
接下來(lái)筆者就舉一個(gè)例子,各位讀者。。愛看不看。。
現(xiàn)在假設(shè)這個(gè)m(x)m(x)m(x) 就是我們剛才說(shuō)的不可約多項(xiàng)式 m(x)=x8+x4+x3+x+1m(x)=x^8+x^4+x^3+x+1m(x)=x8+x4+x3+x+1,對(duì)于多項(xiàng)式 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 ,做它們的加法和乘法。
坐穩(wěn)了,這車我也不知道往哪開了。。。
慘不忍睹的加法:
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
總而言之,在這種運(yùn)算規(guī)則中,做加法時(shí),兩邊都有的冪次項(xiàng)會(huì)消失,只有一邊有的冪次項(xiàng)會(huì)保留,也就是異或,具體原因請(qǐng)查模運(yùn)算法則。
至于乘法和除法的就相當(dāng)復(fù)雜了,我們?cè)谒惴ú襟E中再仔細(xì)說(shuō)明,要詳細(xì)解釋的話就成數(shù)論博文了,當(dāng)筆者只是個(gè)碼農(nóng)啊啊啊。
3、乘法逆元
在有限域中我們來(lái)定義:
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
滿足這個(gè)條件的 b?1(x)b^{-1}(x)b?1(x) 則稱為 b(x)b(x)b(x) 模 a(x)a(x)a(x) 的乘法逆元。上述條件等價(jià)于下面這個(gè)條件:
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) 就是要求的乘法逆元。所以這就是我們最終要解決的問(wèn)題啦,解出這個(gè)多項(xiàng)式等式就可以了。做過(guò)自然數(shù)乘法逆元的應(yīng)該就很熟悉,用擴(kuò)展歐幾里得算法可以解決這個(gè)問(wèn)題。
三、算法步驟
1、擴(kuò)展歐幾里得算法
關(guān)于擴(kuò)展歐幾里得算法,筆者不想重復(fù)書上的內(nèi)容去解釋這個(gè)內(nèi)容,我們只看算法步驟,因?yàn)楣P者對(duì)歐幾里得算法的體驗(yàn)也只是到輾轉(zhuǎn)相除法,再后面變化出來(lái)的妖魔鬼怪算法一律很務(wù)實(shí)地沒看了。
我們先做一些符號(hào)的約定
| a(x)a(x)a(x) | 不可約多項(xiàng)式 |
| b(x)b(x)b(x) | 求乘法逆元的多項(xiàng)式 |
| q(x)q(x)q(x) | 整除的商多項(xiàng)式 |
| r(x)r(x)r(x) | 除法產(chǎn)生的余數(shù)多項(xiàng)式 |
| v(x)v(x)v(x) | 系數(shù)多項(xiàng)式 |
| w(x)w(x)w(x) | 所求的乘法逆元 |
接下來(lái)用最簡(jiǎn)單的方式來(lái)看這個(gè)算法的過(guò)程,筆者也是只看了書上那一頁(yè)的內(nèi)容寫出來(lái)的代碼:
第一步
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)
……
……
……
直到出現(xiàn) rn(x)=0r_n(x)=0rn?(x)=0 時(shí),此時(shí)得到逆元為 wn?1(n)w_{n-1}(n)wn?1?(n)。
那么有了算法步驟,構(gòu)造一個(gè)遞歸函數(shù)就不難了
def poly_gcd(r1, r2, v1=1, v2=0, w1=0, w2=1):# 從第三步開始呈現(xiàn)遞歸規(guī)律,所以初值默認(rèn)為第三步開始時(shí)if r2 == 0 or r2 == 1: return w2# 做多項(xiàng)式除法 r1 ÷ r2 = q3 …… r3q3, r3 = ...# 計(jì)算v3 = v1 - q3 * v2# 計(jì)算w3 = w1 - q3 * w2v3, w3 = ...# 將幾個(gè)值按位依次賦值,作為下一次的參數(shù),就可以實(shí)現(xiàn)遞歸了return poly_gcd(r2, r3, v2, v3, w2, w3)上面的算法思路與自然數(shù)求逆元的思路完全一模一樣,而且,我們已經(jīng)定義了多項(xiàng)式可以和有限域內(nèi)的二進(jìn)制整數(shù)一一對(duì)應(yīng)起來(lái),這就意味著,唯一的區(qū)別只是多項(xiàng)式的乘法和除法與代數(shù)的計(jì)算規(guī)則不太一樣,那我們只需要自己定義好多項(xiàng)式乘法和除法,就可以解決問(wèn)題了!
2、多項(xiàng)式除法
我們已經(jīng)知道了,多項(xiàng)式的除法其實(shí)就是在二進(jìn)制的除法的基礎(chǔ)上加了一點(diǎn)東西而已,那么仔細(xì)觀察有理多項(xiàng)式的長(zhǎng)除法,將冪次項(xiàng)變?yōu)橐粋€(gè)個(gè)1和0,很快我們就可以找到計(jì)算規(guī)律。
先回憶一下10進(jìn)制怎么做的除法,例如 4890÷164890\div 164890÷16
第一步,拿48除以16,商值為3,而4890比16多了兩個(gè)數(shù)量級(jí),所以商的數(shù)量級(jí)為102(左移兩位)。余數(shù)為4890-300×16,進(jìn)入第二次除法。
第二步,拿09除以16,商值為0,被除數(shù)數(shù)量級(jí)比除數(shù)大1,商的數(shù)量級(jí)為10。余數(shù)為被除數(shù),進(jìn)入第三次除法。
第三步,拿90除以16,商值為5,90和16同數(shù)量級(jí),商數(shù)量級(jí)為1。余數(shù)90-5*16,進(jìn)入第四次除法。
第四步,拿10除以16,本位得0,余數(shù)為被除數(shù),已經(jīng)小于除數(shù)且是最低位了,計(jì)算結(jié)束。
第五步,將前面的商加起來(lái)3×100+0×10+5×1為最終的商,余數(shù)為最后一步的余數(shù)。
同樣的道理,計(jì)算二進(jìn)制的除法,例如 (11101)2÷(10)2(11101)_2\div(10)_2(11101)2?÷(10)2?,區(qū)別在于二進(jìn)制只有0和1,這就出現(xiàn)了一些很有趣的現(xiàn)象,比如判斷被除數(shù)能否除除數(shù)的時(shí)候只要比較最高非零位數(shù)就可以,被除數(shù)減去除數(shù)乘以商得到余數(shù)的時(shí)候,因?yàn)槊恳淮纬ǖ纳淌冀K是商值為1數(shù)量級(jí)為n,所以商去乘除數(shù)的時(shí)候就相當(dāng)于將除數(shù)左移n位,然后與被除數(shù)做異或運(yùn)算(即模2加法)。
第一步,11101比10大3個(gè)數(shù)量級(jí),商為1,數(shù)量級(jí)為3。余數(shù)為11101-10<<3=11101-10000=01101,進(jìn)入第二次除法。
第二步,01101比10大2個(gè)數(shù)量級(jí),商為1,數(shù)量級(jí)為2。余數(shù)為01101-10<<2=01101-1000=00101,進(jìn)入第三次除法。
第三步,00101比10大1個(gè)數(shù)量級(jí),商為1,數(shù)量級(jí)為1。余數(shù)為00101-10<<1=00101-100=00001,進(jìn)入第四次除法。
第四步,00001比10小,商為0,余數(shù)為1.
第五步,將所有商加起來(lái),1<<3 + 1<<2 + 1<<1 + 0 = 1110。余數(shù)為1。
所以結(jié)果就是 (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? ,還原成多項(xiàng)式形式就是:
(x4+x3+x2+1)÷(x)=(x3+x2+x)mod  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
不可思議對(duì)吧,你我都不知道這是什么鬼,可是按運(yùn)算規(guī)則這就是對(duì)的。。。
3、多項(xiàng)式乘法
乘法的思路也一樣,是從十進(jìn)制的方法到二進(jìn)制的,只是在模2運(yùn)算也就是做加法的時(shí)候遵循了另一套計(jì)算規(guī)則。舉個(gè)例子,計(jì)算 (11011)2×(1110)2(11011)_2\times(1110)_2(11011)2?×(1110)2? ,乘法比除法簡(jiǎn)單太多了。
我們可以把這個(gè)計(jì)算拆開成為:
(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?
而且我們知道對(duì)于每一個(gè)乘式,都是對(duì)左數(shù)移位,也就是:
(11011)2<<3+(11011)2<<2+(11011)2<<1(11011)_2<<3+(11011)_2<<2+(11011)_2<<1(11011)2?<<3+(11011)2?<<2+(11011)2?<<1
也就是當(dāng)?shù)趎位非零是,左數(shù)便左移相應(yīng)的n位,最后相加就是最終的結(jié)果了:
(11011)2×(1110)2=(10000010)2(11011)_2\times(1110)_2=(10000010)_2(11011)2?×(1110)2?=(10000010)2?
四、代碼實(shí)現(xiàn)
1、多項(xiàng)式除法
# 求最高冪次數(shù) def Nonzero_MSB(value):v2str = '{:09b}'.format(value)for i in range(9):if int(v2str[i]):return 9-i# 模2除法:m為被除數(shù)。b為除數(shù),q為商,r為余數(shù) 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、多項(xiàng)式乘法
# 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^value3、歐幾里得算法
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、配上一個(gè)主程序
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('請(qǐng)輸入一個(gè)多項(xiàng)式(注意以x為變量,冪次以^表示):')# xstr = 'x^7+x+1'print('---- 多項(xiàng)式乘法逆元求解完成 ----')print('>>你輸入的多項(xiàng)式 :', xstr)print('>>默認(rèn)既約多項(xiàng)式 :', int2sym(283))print('>>輸出的乘法逆元 :', int2sym(poly_gcd(283, sym2int(xstr))放一張運(yùn)行結(jié)果圖,可以當(dāng)標(biāo)準(zhǔn)數(shù)據(jù)來(lái)調(diào)試:
五、心得
一直以來(lái)認(rèn)為這一點(diǎn):不要死嗑數(shù)學(xué),理論歸理論,工程歸工程。記得用Matlab寫高斯消元法解線性方程組的時(shí)候,書上已經(jīng)歸納出了一個(gè)遞歸迭代的求求和式了,所以應(yīng)該想的是如何更優(yōu)雅地利用這個(gè)數(shù)學(xué)結(jié)論去完成這個(gè)函數(shù)的功能,而不是死磕為什么,那是課堂上該做的(當(dāng)然,筆者上課都是睡覺度過(guò),所以也當(dāng)筆者在找個(gè)合適的借口吧哈哈哈哈哈)!
總結(jié)
以上是生活随笔為你收集整理的Python在GF(2⁸)有限域上求解多项式的乘法逆元——基于扩展欧几里得算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【5G系列】5G新参数SUCI介绍
- 下一篇: python机器学习 | SVM算法介绍