RSA詳解(Java實現)

来源:https://www.cnblogs.com/mx-lqk/archive/2019/01/19/10293333.html
-Advertisement-
Play Games

GitHub RSA密碼 RSA密碼是1978年美國麻省理工學院三位密碼學者R.L.Rivest、A.Shamir和L.Adleman提出的一種基於大合數因數分解困難性的公開密鑰密碼。由於RSA密碼既可用於加密,又可用於數字簽名,通俗易懂,因此RSA密碼已成為目前應用最廣泛的公開密鑰密碼。 RSA加 ...


GitHub


RSA密碼

  RSA密碼是1978年美國麻省理工學院三位密碼學者R.L.Rivest、A.Shamir和L.Adleman提出的一種基於大合數因數分解困難性的公開密鑰密碼。由於RSA密碼既可用於加密,又可用於數字簽名,通俗易懂,因此RSA密碼已成為目前應用最廣泛的公開密鑰密碼。


RSA加解密演算法

  1.隨機地選擇兩個大素數p和q,而且保密;

  2.計算n=pq,將n公開;

  3.計算φ(n)=(p-1)(q-1),對φ(n)保密;

  4.隨機地選取一個正整數e,1<e<φ(n)且(e,φ(n))=1,將e公開;

  5.根據ed=1(mod φ(n)),求出d,並對d保密;

  6.加密運算:C=Me(mod n);

  7.解密運算:M=Cd(mod n)。

  註意:在加密運算和解密運算中,M和C的值都必須小於n,也就是說,如果明文(或密文)太大,必須進行分組加密(或解密)。


RSA演算法細節

  實現RSA演算法,主要需要實現以下幾個部分:

  1.對大數的素數判定;

  2.模逆運算;

  3.模指運算。

對大數的素數判定

  一個較小的數是否為素數,可以用試除法來判定,而如果這個數很大的話,試除法的效率就會變得很低下。也就是說,試除法不適用於對大數進行素數判定,所以對大數的素數判定一般採用素數的概率性檢驗演算法,其中又以Miller演算法最為常見。

  使用素數的概率性檢驗演算法判定一個數是否為素數,雖然相比試除法而言效率非常之高,但是對該數的判定結果並不准確。該演算法通過迴圈使用Miller演算法來提高判定結果的正確性。

  素數的概率性檢驗演算法的流程:對於奇整數n,在2~n-2之間隨機地選取k個互不相同的整數,迴圈使用Miller演算法來檢驗n是否為素數。若結果為true,則認為n可能為素數,否則肯定n為合數。

  一輪Miller演算法判定大整數n不是素數的概率≤4-1,所以,素數的概率性檢驗演算法判定大整數n不是素數的概率≤4-k(k為Miller演算法的迴圈次數)。

Miller演算法

  若n為奇素數,則對∀a∈[2,n-2],由於a與n互素,根據歐拉定理可得aφ(n)=an-1=1(mod n)。

  若n是奇素數,則不存在1(mod n)的非平凡平方根,即對於x2=1(mod n)的解有且僅有±1。

  若n是奇素數,則n-1是偶數。不妨令n=2tm+1(t≥1),則m為n-1的最大奇因數。根據上述兩點,不難得出,對∀a∈[2,n-2],∃τ∈[1,t]使得

  Miller演算法正是通過上述的逆否命題而設計出來的,其原理是:對∀a∈[2,n-2],n是一個合數的充要條件是對∀τ∈[1,t]使得

  Miller演算法的設計思路:令b=am(mod n),如果b=±1(mod n)則n可能是一個素數;否則,b=b2(mod n),並判斷是否滿足b=-1(mod n)(滿足則n可能是一個素數),由此迴圈t-1次。如果都滿足b≠-1(mod n),則n一定是一個合數。

  e.m.判定221是否為素數

n=221=22*55+1

         所以m=55,t=2

         取a=174,則

17455(mod 221)=47

174110(mod 221)=220

         所以n要麼是一個素數,要麼a=174是一個“強偽證”。

         再取a=137,則

13755(mod 221)=188

137110(mod 221)=205

         所以n是一個合數。

模逆運算

  模逆運算就是求滿足方程ax=1(mod m)的解x,而ab=1(mod m)有解的前提條件是(a,m)=1,即a和m互素。

  對方程ax=1(mod m)的求解可以轉換為求解ax+my=1=(a,m),即轉換為擴展歐幾里德演算法。

  e.m.求243-1(mod 325)

325=1*325+0*243

243=0*325+1*243

82=325-243=1*325+(-1)*243

79=243-2*82=(-2)*325+3*243

3=82-79=3*325+(-4)*243

1=79-26*3=(-80)*325+107*243

         所以

 

243-1(mod 325)=107

模指運算

  模指運算就是對an(mod m)的計算。當指數n的值較大時,如果先求出bn再去模m的話,效率會很低下。所以,對於指數n較大的情況一般採用反覆平方乘演算法。

反覆平方乘演算法

  所以,反覆平方乘演算法的原理是將指數n轉化為2的冪之和的形式,即n=2kek+2k-1ek-1+...+2e1+e0,然後根據l1=a2(mod m),l2=a4(mod m)=l12(mod m),...,

最後根據an(mod m)=e0a·e1l1·...·eklk(mod m)求解。

  e.m.求2335(mod 101)

35=32+2+1

231(mod 101)=23

232(mod 101)=24

234(mod 101)=242(mod 101)=71

238(mod 101)=712(mod 101)=92

2316(mod 101)=922(mod 101)=81

2332(mod 101)=812(mod 101)=97

         所以

2335(mod 101)=97×24×23(mod 101)=14 


RSA密碼的安全性

  密碼分析者攻擊RSA密碼的一種可能途徑是截獲密文C,通過M=Cd(mod n)求出M。其中,n是公開的,而d是保密的。因為e是公開的,所以可以通過ed=1(mod φ(n))求出d,而φ(n)是保密的。雖然n是公開的,但是φ(n)=(p-1)(q-1)=pq-p-q+1=n-p-q+1,其中p和q是保密的,也就是說欲求得φ(n)必須知道p和q,即必須將n進行因式分解。

  小合數的因數分解是容易的,然而大合數的因數分解卻是十分困難的。由此可以得出,破譯RSA密碼的困難性約為對n進行因數分解的困難性。

  RSA密碼的安全性除了與因數分解密切相關之外,還與其參數p、q、e、d的選取有密切關係。只要合理地選取參數,並正確使用,RSA密碼就是安全的。這就是目前RSA密碼仍然廣泛使用的重要原因。


Java實現

RSA

1 p = BigInteger.probablePrime(new Random().nextInt(100) + 100, new Random());
2 q = BigInteger.probablePrime(new Random().nextInt(100) + 100, new Random());
3 n = p.multiply(q);
4 phi_n = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
5 do {
6     e = new BigInteger(new Random().nextInt(phi_n.bitLength() - 1) + 1, new Random());
7 } while (e.compareTo(phi_n) != -1 || e.gcd(phi_n).intValue() != 1);
8 d = e.modPow(new BigInteger("-1"), phi_n);
 1 /**
 2  * 加密
 3  * <p> C=M^e(mod n)
 4  * @param M
 5  * @param n
 6  * @param e
 7  * @return
 8  */
 9 public static BigInteger encrypt(BigInteger M, BigInteger n, BigInteger e) {
10     return M.modPow(e, n);
11 }
 1 /**
 2  * 解密
 3  * <p> M=C^d(mod n)
 4  * @param C
 5  * @param n
 6  * @param d
 7  * @return
 8  */
 9 public static BigInteger decrypt(BigInteger C, BigInteger n, BigInteger d) {
10     return C.modPow(d, n);
11 }

對大數的素數判定

 1 /**
 2  * 素數的概率性檢驗演算法
 3  * @param k
 4  * @param n
 5  * @return
 6  */
 7 static boolean isPrime(int k, long n) {
 8     List<Long> a = new ArrayList<Long>();
 9     int t = n - 2 > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) (n - 2);
10     do {
11         long l = (long) (new Random().nextInt(t - 2) + 2);
12         if (-1 == a.indexOf(l)) 
13             a.add(l);
14     } while (a.size() < k);
15     for (int i = 0; i < k; i++)  
16         if (! Miller(n, a.get(i))) 
17             return false;
18     return true;
19 }
20 static boolean Miller(long n, long a) {
21     long m = n - 1;
22     int t = 0;
23     while (m % 2 == 0) {
24         m /= 2;
25         t++;
26     }
27     long b = modExp(a, m, n);
28     if (b == 1 || b == n - 1) 
29         return true;
30     for (int j = 1; j < t; j++) {
31         b = b * b % n;
32         if (b == n - 1) 
33             return true;
34     }
35     return false;
36 }

模逆運算

 1 /**
 2  * 模逆運算
 3  * @param b
 4  * @param m
 5  * @return  b^-1(mod m)
 6  */
 7 static long modInv(long b, long m) {
 8     if (b >= m) b %= m;
 9     return exGcd(b, m)[1] < 0 ? exGcd(b, m)[1] + m : exGcd(b, m)[1];
10 }
11 /**
12  * 擴展歐幾里德演算法
13  * <p>(a,b)=ax+by
14  * @param a
15  * @param b
16  * @return  返回一個long數組result,result[0]=x,result[1]=y,result[2]=(a,b)
17  */
18 static long[] exGcd(long a, long b) {
19     if (a < b) {
20         long temp = a;
21         a = b;
22         b = temp;
23     }
24     long[] result = new long[3];
25     if (b == 0) {
26         result[0] = 1;
27         result[1] = 0;
28         result[2] = a;
29         return result;
30     }
31     long[] temp = exGcd(b, a % b);
32     result[0] = temp[1];
33     result[1] = temp[0] - a / b * temp[1];
34     result[2] = temp[2];
35     return result;
36 }

模指運算

 1 /**
 2  * 模指運算
 3  * @param b
 4  * @param n
 5  * @param m
 6  * @return   b^n(mod m)
 7  */
 8 static long modExp(long b, long n, long m) {
 9     long result = 1;
10     b = b % m;
11     do {
12         if ((n & 1) == 1) 
13             result=result*b%m;
14         b = b * b % m;
15         n = n >> 1;
16     } while (n != 0);
17     return result;
18 }

測試

測試數據

  p=e86c7f16fd24818ffc502409d33a83c2a2a07fdfe971eb52de97a3de092980279ea29e32f378f5e6b7ab1049bb9e8c5eae84dbf2847eb94ff14c1e84cf568415

  q=d7d9d94071fcc67ede82084bbedeae1aaf765917b6877f3193bbaeb5f9f36007127c9aa98d436a80b3cce3fcd56d57c4103fb18f1819d5c238a49b0985fe7b49

  e=10001

  M=b503be7137293906649e0ae436e29819ea2d06abf31e10091a7383349de84c5b

測試結果


參考文獻

  張煥國,唐明.密碼學引論(第三版).武漢大學出版社,2015年


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • SSM框架基礎配置文件包括:applicationContext.xml(Spring框架核心配置文件)、dispatcher-servlet.xml(SpringMVC框架核心配置文件)、mybatis-config.xml(Mybatis配置文件)、database.properties(數據源 ...
  • 迷宮問題 迷宮問題一直是電腦工作者感興趣的問題,因為它可以展現棧的巧妙應用, 這裡將利用棧開發一個走迷宮程式,雖然在發現正確路徑前,程式要嘗試許多 錯誤路徑,但是,一旦發現,就能夠重新走出迷宮,而不會再去嘗試任何錯誤路徑。 迷宮問題求解 電腦中可以用如圖所示的方塊圖表示迷宮。圖中空白方塊為通道, ...
  • 在項目中,很多地方需要根據時間獲取相應的數據,將時間格式化,或者時間比較等相關操作。一個良好的工具類不僅可以減少代碼冗餘,還能促進業務處理,加快進度。 輸出結果: ...
  • Java包是一個相關類的集合,Java標準類庫是一組支持基本編輯任務的包(即Java標準庫是按包分組的)。 下麵是Java標準類庫中的部分包: (https://www.oracle.com/technetwork/java/api-141528.html為線上Java API文檔的網頁,選擇適應的 ...
  • 題目鏈接 給出一個有N個數的序列,編號0 - N - 1。進行Q次查詢,查詢編號i至j的所有數中,最大的數是多少。 例如: 1 7 6 3 1。i = 1, j = 3,對應的數為7 6 3,最大的數為7。(該問題也被稱為RMQ問題) 輸入 輸出 輸入樣例 輸出樣例 Sparse Table解決Ra ...
  • 1、安裝matplotlib 在 cmd 中鍵入 python -m pip install matplotlib,系統將自動安裝,需要等一段時間,待完成後 python -m pip list ,顯示 敲黑板劃重點:一定通過 cdm 指定具體安裝文件夾。 cd 文件夾名 可進入指定文件夾。 2、簡 ...
  • beego 框架 cache 目錄是 Go 實現的一個緩存管理器,是beego框架自帶工具之一,當然,如果你只想使用 cache 而不是整個 beego 框架,可以選擇性安裝: go get github.com/astaxie/beego/cache 在我寫這篇博文時, beego 版本是 v1. ...
  • IDE進行Gradle操作,那麼還需要設置IDE的參數。例如在IDEA中,需要打開File->Other Settings->Default Settings->Gradle,在Gradle Vm Options中設置-Dfile.encoding=utf-8。這樣IDEA中的Gradle也可以正確 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...