日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

c++折线平移算法_RSA笔记-蒙哥马利算法(1)

發布時間:2024/9/27 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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 大數模冪運算,寫的是如下(半吊子)代碼:
(在此僅改了傳參規范)

int bn_PowMod_old (BIGNUM Result, BIGNUM A, BIGNUM E, BIGNUM X){ // Result = pow(A^E) mod XBIGNUM A0, Ret;int K, L;int *a = NULL, *e = NULL;K = bn_Expand(A, 2, a);bn_LShift(A0, A, K); // A0 = A*R, *R 實現為移位運算Ret = A0;L = bn_Expand(E, 2, e);for(int i = L; i >= 0; i--){ // 利用了簡化冪運算的“平方-乘算法”,從高位開始bn_mont_Mult(Ret, Ret, Ret, X);if(e[i]==1){bn_mont_Mult(Ret, Ret, A0, X);}}bn_RShift(Ret, Ret, K); // Ret = Ret*R', 移回來return Ret; }

這段代碼里,有幾個問題:

  • 我寫了一個 bn_LShift 和 bn_RShift 用來表示“蒙哥馬利變換”和“蒙哥馬利逆變換”,實際上不會那么處理。。大數都是切割成一塊塊的,移位咋移啊。。
  • 可以看到,bn_mont_Mult 里的 R 的長度(或值),實際上是依賴于入參 A 的長度的,也就是說并不是一個寫死的值,所以實際上需要傳入 A 的長度。
  • 其實還有一個問題。。這個之前沒有知友看出來。那就是 Ret 沒有賦初值 = =。。。好嚴重的錯誤有木有....我的鍋
  • 那么我們試著改一下,首先不妨(暫時)假設我們相應地修改好了接口,并且方便起見,將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)

    int bn_PowMod (BIGNUM Result, BIGNUM A, BIGNUM E, BIGNUM X){ // Result = pow(A^E) mod XBIGNUM AR, Ret;int K, L;int *a = NULL, *e = NULL;K = bn_Expand(A, 2, a);bn_mont_trans(AR, A, K, X); // AR = A*R mod X, 變換至蒙哥馬利域bn_set_mont(Ret, K, X); // Ret = R = 10000...(K個0) 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; }

    這樣好一些了,至少完整了。。但實際上還可以精簡。事實上 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)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。