c++折线平移算法_RSA笔记-蒙哥马利算法(1)
有些想補充的內容,但不好直接在初始的那一篇里改。因為那里講得太細致了,是一步步講得,要想再塞點別的東西進去就雜亂無章或喧賓奪主了。。所以重開一篇,后續有什么問題,都在這里更新。不是說細節我都明白透了(畢竟我也沒實際寫過RSA,只看過別人寫的...看的還不仔細),只是自己懂一點也可以記錄一點,順便和大家分享。
背景就說到這,下面是我自己想補充的內容!
=================================
在第一篇中,從問題的起因,到尋求解決的步驟,是一步步沿著設計者的足跡,得到了算法的實現。每一步都尋求解決一個問題,很自然地到達最終的結果。這樣順水推舟地走,也許比較輕松,但可能走到最后,便忘記了開始,沒辦法一覽順流而下的整條河的概貌。
這里,我想僅就算法實現,再梳理一下步驟。
前一篇文章中,我粗略描述了蒙哥馬利乘的接口(稍微改一下傳參,BIGNUM還是不好作為返回值...得作為參數傳進去再輸出來):
[1] int bn_mont_Mult (BIGNUM Result, BIGNUM A, BIGNUM B, BIGNUM X); 名稱:蒙哥馬利乘 功能:輸出 Result = A * B [* R^(-1) mod X ]并且在前一篇文章里,實現 A^E mod X 大數模冪運算,寫的是如下(半吊子)代碼:
(在此僅改了傳參規范)
這段代碼里,有幾個問題:
那么我們試著改一下,首先不妨(暫時)假設我們相應地修改好了接口,并且方便起見,將bn_mont_Mult 相同兩個大數相乘的情況封裝為 bn_mont_Square 平方接口,即:
[2.a] int bn_mont_Mult (BIGNUM Result, BIGNUM A, BIGNUM B, uint32_t alen, BIGNUM X); 名稱:蒙哥馬利乘 功能:輸出 Result = A * B [* R^(-1) mod X ], R = 2^(-alen) 備注:在此假設 alen 是 A 的比特長度[3.b] int bn_set_mont(BIGNUM R, uint32_t alen, BIGNUM X) 名稱:獲取蒙哥馬利參數 R 功能:輸出大數 R = 10000...(alen 個 0) mod X[2.c] int bn_mont_trans(BIGNUM Result, BIGNUM A, uint32_t alen, BIGNUM X) 名稱:蒙哥馬利變換 功能:輸出 Result = A [* R mod X ][2.d] int bn_mont_inv(BIGNUM Result, BIGNUM A, uint32_t alen, BIGNUM X) 名稱:蒙哥馬利逆變換 功能:輸出 Result = A [* R^(-1) mod X ][2.e] int bn_mont_Square (BIGNUM Result, BIGNUM A, uint32_t alen, BIGNUM X); 名稱:蒙哥馬利平方 功能:輸出 Result = A * A [* R^(-1) mod X ], R = 2^(-alen) 實現: int bn_mont_Square (BIGNUM Result, BIGNUM A, uint32_t alen, BIGNUM X) {return bn_mont_Mult(Result, A, A, alen, X); }Ret 的初值應該是什么呢?感覺應該是1...但考慮到我們用的是蒙哥馬利乘,也就意味著我們乘任何兩個數,進了 bn_mont_Mult 接口都會先除以一個 R;至于普通乘法里乘1,意味著被乘數的值不變,那么作為輸入蒙哥馬利域的數,怎樣的數才滿足:任意一個數和它做 bn_mont_Mult 后值不變呢?顯然,R是(唯一)一個這樣的角色;想起來也很自然,因為蒙哥馬利乘相當于我們把做乘法的位數“向右平移”了 R 嘛...那1可不是得“向左平移”個R,來把它抵消掉。。廢話不多說了,模冪的代碼相應可修改為:
(A0 改成 AR 吧...代表A*R)
這樣好一些了,至少完整了。。但實際上還可以精簡。事實上 bn_mont_trans 這個大數乘法可以也用蒙哥馬利乘代替,好比說,我們實現了如下3.幾的一組接口,而不是2.幾的:
[3.a] int bn_mont_Mult (BIGNUM Result, BIGNUM A, BIGNUM B, uint32_t alen, BIGNUM X); 名稱:蒙哥馬利乘;雙因數 功能:輸出 Result = A * B [* R^(-1) mod X ], R = 2^(-alen) 備注:在此假設 alen 是 A 的比特長度[3.b] int bn_set_mont(BIGNUM R, uint32_t alen, BIGNUM X) 名稱:獲取蒙哥馬利參數 R 功能:輸出大數 R = 10000...(alen 個 0) mod X[3.c] int bn_mont_inv(BIGNUM Result, BIGNUM A, uint32_t alen, BIGNUM X) 名稱:蒙哥馬利逆變換;單因數,相當于 B = 1 功能:輸出 Result = A [* R^(-1) mod X ] 實現: int bn_mont_inv(BIGNUM Result, BIGNUM A, uint32_t alen, BIGNUM X) {BIGNUM one = 1; // 反正就是個賦值...領會就好return bn_mont_Mult(Result, A, one, alen, X); }[3.d] int bn_mont_Square (BIGNUM Result, BIGNUM A, uint32_t alen, BIGNUM X); 名稱:蒙哥馬利平方 功能:輸出 Result = A * A [* R^(-1) mod X ], R = 2^(-alen) 實現: int bn_mont_Square (BIGNUM Result, BIGNUM A, uint32_t alen, BIGNUM X) {return bn_mont_Mult(Result, A, A, alen, X); }正如前文所述,若調用蒙哥馬利乘來實現使 A 賦值變到蒙哥馬利域上,也就是使 AR = A*R mod X,則除 A 之外的另一個因數需為 R^2,即:
bn_mont_Mult (AR, A, R^2, alen, X)
才能使得:
AR = A*R^2 [*R^(-1) mod X]
于是代碼修改為:
int bn_PowMod (BIGNUM Result, BIGNUM A, BIGNUM E, BIGNUM X){ // Result = pow(A^E) mod XBIGNUM AR, Ret, R2;int K, L;int *a = NULL, *e = NULL;K = bn_Expand(A, 2, a);bn_set_mont(R2, 2*K, X); // R2 = 10000...(2*K個0) mod Xbn_MultMod(AR, A, R2, alen, X); // A0 = A*R^2 [*R^(-1) mod X] = A*R mod Xbn_mont_inv(Ret, R2, K); // Ret = R = R2*R^(-1) mod XL = bn_Expand(E, 2, e);for(int i = L; i >= 0; i--){ // 利用了簡化冪運算的“平方-乘算法”,從高位開始bn_mont_Square(Ret, Ret, X);if(e[i]==1){bn_MultMod(Ret, Ret, AR, X);}}bn_mont_inv(Ret, Ret, K); // Ret = Ret*R^(-1) mod X, 由蒙哥馬利域變回return Ret; }這樣應該就比較接近真實的 RSA 蒙哥馬利模冪的接口實現了。。至少看那些開源代碼應該能明白哪一步大體在干啥了。
至于剩下的細節,比如說,如何保證模乘的因數比模數小,具體在哪一步取模,等這些細節問題日后有機會再談吧(其實目前我也搞不清...主要沒有需求讓我寫 RSA ...國際上那么多優秀的人優化了那么多年,怎么也輪不著自己實現(哈哈哈...)不過確實還是挺有意思的算法,不是嗎?
總結
以上是生活随笔為你收集整理的c++折线平移算法_RSA笔记-蒙哥马利算法(1)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: es对已有的索引给主键_ES中对索引的相
- 下一篇: java组合框的事件有哪些_博为峰Jav