1. 程式人生 > >RSA加密演算法驗證(C#實現)

RSA加密演算法驗證(C#實現)

RSA演算法簡單原理介紹(節選於網路)

假設Alice想要通過一個不可靠的媒體接收Bob的一條私人訊息。她可以用以下的方式來產生一個公鑰和一個私鑰

  1. 隨意選擇兩個大的質數pqp不等於q,計算N=pq
  2. 根據尤拉函式,求得r = (p-1)(q-1)
  3. 選擇一個小於 r 的整數 e,求得 e 關於模 r 的模反元素,命名為d。(模反元素存在,當且僅當e與r互質)
  4.  p  q 的記錄銷燬。

(N,e)是公鑰,(N,d)是私鑰。Alice將她的公鑰(N,e)傳給Bob,而將她的私鑰(N,d)藏起來。

加密訊息

  假設Bob想給Alice送一個訊息m

,他知道Alice產生的Ne。他使用起先與Alice約好的格式將m轉換為一個小於N的整數n,比如他可以將每一個字轉換為這個字的Unicode碼,然後將這些數字連在一起組成一個數字。假如他的資訊非常長的話,他可以將這個資訊分為幾段,然後將每一段轉換為n。用下面這個公式他可以將n加密為c

  ne ≡ c (mod N)

計算c並不複雜。Bob算出c後就可以將它傳遞給Alice。

解密訊息

Alice得到Bob的訊息c後就可以利用她的金鑰d來解碼。她可以用以下這個公式來將c轉換為n

  cd ≡ n (mod N)

得到n後,她可以將原來的資訊m重新復原。

解碼的原理是:

  cd ≡ n e·d(mod N)

以及ed ≡ 1 (mod p-1)和ed ≡ 1 (mod q-1)。由費馬小定理可證明(因為pq是質數)

  n e·d ≡ n (mod p)   和  n e·d ≡ n (mod q)

這說明(因為pq不同的質數,所以pq互質)

  n e·d ≡ n (mod pq)

  1 using System;
  2 using System.Collections.Generic;
3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 11 namespace RSA 12 { 13 public partial class Form1 : Form 14 { 15 public Form1() 16 { 17 InitializeComponent(); 18 } 19 20 //**************************************** 21 //驗證輸入的p,q是否為素數,並計算n與m 22 //**************************************** 23 private void button1_Click(object sender, EventArgs e) 24 { 25 long p, q; 26 //獲取p,q的值 27 p = long.Parse(textBox1.Text); 28 q = long.Parse(textBox2.Text); 29 30 //判斷p,q是否為素數,若為真進行計算,則否彈出提示 31 if (isPrim(p) && isPrim(q)) 32 { 33 long n = p * q; 34 long m = (p - 1) * (q - 1); 35 textBox3.Text = n.ToString(); 36 textBox4.Text = m.ToString(); 37 } 38 else 39 { 40 MessageBox.Show("請按要求,重新輸入p,q"); 41 textBox1.Clear(); 42 textBox2.Clear(); 43 textBox3.Clear(); 44 textBox1.Focus(); 45 } 46 47 48 } 49 50 //**************************************** 51 //用隨機數生成素數pq,並計算n與m 52 //**************************************** 53 54 private void button5_Click(object sender, EventArgs e) 55 { 56 //生成隨機數工具 57 Random random = new Random(); 58 long p, q; 59 60 //設定判斷標誌 61 Boolean flag = false; 62 while (!flag) 63 { 64 p = random.Next(595530); 65 q = random.Next(585530); 66 67 //若生成的兩個隨機數都為素數,設定更新標誌,並進行顯示 68 if (isPrim(p) && isPrim(q)) 69 { 70 flag = true; 71 textBox1.Text = p.ToString(); 72 textBox2.Text = q.ToString(); 73 textBox3.Clear(); 74 textBox4.Clear(); 75 } 76 77 } 78 } 79 80 //**************************************** 81 //驗證輸入的d是否為素數, 並計算公鑰d 82 //**************************************** 83 private void button2_Click(object sender, EventArgs e) 84 { 85 //獲取d,m的值 86 long d = long.Parse(textBox5.Text); 87 long m = long.Parse(textBox4.Text); 88 89 //判斷輸入的d是否符合條件 90 if (d > 1 && d < m && gcd(d, m) == 1 && isPrim(d)) 91 { 92 //使用逆元函式,計算d,m的逆元 93 long result = niyuan(d, m); 94 textBox6.Text = result.ToString(); 95 } 96 else 97 { 98 MessageBox.Show("輸入的 e 不符合要求,請按要求,重新輸入公鑰 e !"); 99 textBox5.Clear(); 100 textBox5.Focus(); 101 102 } 103 } 104 105 //**************************************** 106 //隨機生成私鑰d,並計算出公鑰e 107 //**************************************** 108 private void button6_Click(object sender, EventArgs e) 109 { 110 long d = 0; 111 112 //獲取m的值,用以計算e 113 long m = long.Parse(textBox4.Text); 114 115 //生成隨機數工具,並設定隨機是否完成標誌 116 Random radom = new Random(); 117 Boolean flag = false; 118 while(!flag) 119 { 120 d = radom.Next(655300); 121 if (d > 1 && d < m && gcd(d, m) == 1 && isPrim(d)) 122 { 123 flag = true; 124 } 125 } 126 127 //利用逆元函式計算公鑰 128 long result = niyuan(d, m); 129 130 textBox5.Text = d.ToString(); 131 textBox6.Text = result.ToString(); 132 133 } 134 135 //**************************************** 136 //利用公鑰n和私鑰e,加密明文 137 //**************************************** 138 private void button4_Click(object sender, EventArgs e) 139 { 140 //設定標誌,判斷是否已經輸入明文 141 Boolean flag = false; 142 if (!string.IsNullOrWhiteSpace(textBox7.Text)) 143 flag = true; 144 145 if(flag == false) 146 { 147 MessageBox.Show("加密前,請先輸入明文!"); 148 textBox7.Focus(); 149 } 150 else 151 { 152 long n = long.Parse(textBox3.Text); 153 long m = long.Parse(textBox7.Text); 154 long E = long.Parse(textBox5.Text); 155 156 //利用快速指數模運算函式生成密文 157 long C = getMod(E, m, n); 158 textBox8.Text = C.ToString(); 159 } 160 161 } 162 163 //**************************************** 164 //利用公鑰n和公鑰d,解密密文 165 //**************************************** 166 private void button3_Click(object sender, EventArgs e) 167 { 168 //設定標誌,判斷是否已經輸入密文 169 Boolean flag = false; 170 if (!string.IsNullOrWhiteSpace(textBox9.Text)) 171 flag = true; 172 if(flag == false) 173 { 174 MessageBox.Show("解密前,請先輸入密文!"); 175 textBox9.Focus(); 176 } 177 else 178 { 179 long C = long.Parse(textBox9.Text); 180 long n = long.Parse(textBox3.Text); 181 long d = long.Parse(textBox6.Text); 182 183 //利用快速指數模運算函式解密密文 184 long M = getMod(d, C, n); 185 textBox10.Text = M.ToString(); 186 } 187 188 } 189 190 //**************************************** 191 //輸入一個數,以6為步進單元判斷其是否為素數 192 //**************************************** 193 private bool isPrim(long num) 194 { 195 //兩個較小數另外處理 196 if (num == 2 || num == 3) 197 return true; 198 //不在6的倍數兩側的一定不是質數 199 if (num % 6 != 1 && num % 6 != 5) 200 return false; 201 long tmp = (long)Math.Sqrt(num); 202 //在6的倍數兩側的也可能不是質數 203 for (long i = 5; i <= tmp; i += 6) 204 if (num % i == 0 || num % (i + 2) == 0) 205 return false; 206 //排除所有,剩餘的是質數 207 return true; 208 } 209 210 //**************************************** 211 //採用遞迴的形式,判斷兩個數是否互質 212 //**************************************** 213 private long gcd(long x, long y) 214 { 215 return y != 0 ? gcd(y, x % y) : x; 216 } 217 218 //**************************************** 219 //利用歐幾里得演算法計算m,d的逆元 220 //**************************************** 221 private long niyuan(long number1, long number3) 222 { 223 long x1 = 1, x2 = 0, x3 = number3, y1 = 0, y2 = 1, y3 = number1; 224 long q; 225 long number4 = 0; 226 long t1, t2, t3; 227 while (y3 != 0) 228 { 229 if (y3 == 1) 230 { 231 number4 = y2; 232 break; 233 } 234 else 235 { 236 q = (x3 / y3); 237 t1 = x1 - q * y1; 238 t2 = x2 - q * y2; 239 t3 = x3 - q * y3; 240 x1 = y1; x2 = y2; x3 = y3; 241 y1 = t1; y2 = t2; y3 = t3; 242 } 243 } 244 if (number4 < 0) 245 number4 = number4 + number3; 246 return number4; 247 } 248 249 //**************************************** 250 //利用快速指數模運算,計算m^e mod n 251 //**************************************** 252 private long getMod(long a, long b, long c) 253 { 254 //指數 e --> a 底數 m --> b 模數 n --> c 255 long number3 = 1; 256 while (a != 0) 257 { 258 if (a % 2 == 1) 259 { 260 a = a - 1; 261 number3 = (number3 * b) % c; 262 } 263 else 264 { 265 a = (a / 2); 266 b = (b * b) % c; 267 } 268 } 269 return number3; 270 271 } 272 } 273 }