1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | // 這是展現 RSA 原理的簡易實作 // 請參考 // https://zh.wikipedia.org/wiki/RSA%E5%8A%A0%E5%AF%86%E6%BC%94%E7%AE%97%E6%B3%95 //隨意選擇兩個質數p和q,p不等於 q var p=13; var q=73; console.log(`p=${p} q=${q}`); //計算 N=pq。 var N=p*q; console.log(`N=${N}`); //根據歐拉函數,求得r=f(N)=f(p)f(q)=(p-1)(q-1) var r= (p-1)*(q-1); console.log(`r=${r}`); //擇一個小於r的整數e,使e與r互質。 function isInterprime(a,b) { //求互質 for(var i=2;i<=a&&i<=b;i++){ //因為a,b的數字很小,直接算 if(a%i==0&&b%i==0) return false; } return true; } var e_list=[]; for(var i=2;i<r;i++){ if(isInterprime(i,r)) e_list.push(i); } console.log(`e_list=[${e_list}]`); //隨機選一個 e var e=e_list[Math.floor(Math.random() * e_list.length)]; console.log(`e=${e}`); //並求得e關於r的模反元素,命名為d(求d令ed ≡ 1 (mod r)) //等同於,求d 使得 (e*d)%r=1 var d=-1; for(var i=2;i<=r;i++){ if((e*i)%r==1){ d=i; break; } } //避免公鑰等於私鑰,當 (e*d)%r=1 成立時,(e*(d+r))%r=1 也會成立 if(d==e)d+=r; console.log(`d=${d}`); //第二組私鑰 var d2=d+r; console.log(`d2=${d2}`); console.log(`(N)=${N} 公鑰(e)=${e} 私鑰(d)=${d} 私鑰(d2)=${d2}`); //加密 //將需要加密的訊息轉為N範圍內的數字,舉例來說,令a=1,b=2等等,這部分略過 //轉為數字後的明文為 n,轉出來的密文為 c // c ≡ n^d (mod N) var n=5; //假設要加密的密文 // 依照公式寫出程式碼 // var c=Math.pow(n,e)%N; // 當數字太大時,javascript 會把數字轉為浮點數,導致計算餘數出錯,因此要使用模算術的特性去做運算 // https://ithelp.ithome.com.tw/articles/10205727 function mod_pow(n,key,N){ var result=1; for(var i=0;i<key;i++){ result*=n; result%=N; } return result; } var c=mod_pow(n,e,N); console.log(`加密: ${n} => ${c}`); //解密 //var nd=Math.pow(c,d)%N; var nd=mod_pow(c,d,N); console.log(`解密(第一組私鑰): ${c} => ${nd}`); var nd2=mod_pow(c,d2,N); console.log(`解密(第二組私鑰): ${c} => ${nd2}`); |
Direct link: https://paste.plurk.com/show/Zyngyh2wx5F7UGaJM8na