文:RSA算法是一種非對稱加密算法,用于加密、解密和數字簽名等場景。本文將介紹如何在JavaScript中使用RSA算法,并提供一個實際的案例,同時也會說明如何生成公鑰和私鑰。
首先,確保您已經引入了jsencrypt庫。以下是一個使用RSA算法進行加密和解密的示例,同時也包含了公鑰和私鑰的生成方法:
// 引入jsencrypt庫
const JSEncrypt = require("jsencrypt");
// 生成RSA密鑰對
const rsa = new JSEncrypt();
const keypair = rsa.getKey();
// 獲取公鑰和私鑰
const publicKey = keypair.getPublicKey();
const privateKey = keypair.getPrivateKey();
console.log("公鑰:", publicKey);
console.log("私鑰:", privateKey);
// 實例化一個RSA對象
const rsaInstance = new JSEncrypt();
// 設置公鑰和私鑰
rsaInstance.setPublicKey(publicKey);
rsaInstance.setPrivateKey(privateKey);
// 定義待加密的字符串
const plaintext = "Hello, World!";
// 加密字符串
const encrypted = rsaInstance.encrypt(plaintext);
console.log("加密后的密文:", encrypted);
// 解密密文
const decrypted = rsaInstance.decrypt(encrypted);
console.log("解密后的明文:", decrypted);
在上述代碼中,我們首先引入了jsencrypt庫,并實例化了一個JSEncrypt對象。通過調用getKey()方法,我們生成了一個RSA密鑰對。然后,我們使用getPublicKey()和getPrivateKey()方法獲取公鑰和私鑰。生成的公鑰和私鑰可以用于后續的加密和解密操作。
接下來,我們實例化另一個JSEncrypt對象,并使用setPublicKey()和setPrivateKey()方法設置公鑰和私鑰。之后,我們定義了待加密的字符串,并使用encrypt()方法對字符串進行加密。最后,通過調用decrypt()方法對密文進行解密,并將解密后的明文輸出。
通過以上示例,您可以在JavaScript中使用RSA算法進行加密和解密操作,并自動生成公鑰和私鑰。需要注意的是,生成的公鑰和私鑰應妥善保管,確保其安全性和保密性,以防止數據泄露和非法使用。
總結:通過jsencrypt庫,我們可以在JavaScript中輕松實現RSA算法的加密和解密功能。本文提供了一個實際的案例,并詳細說明了如何生成公鑰和私鑰。通過生成的密鑰對,我們可以進行數據加密和解密操作,確保數據的安全性和保密性。在實際應用中,請妥善保存生成的公鑰和私鑰,以保證數據的安全。
題:#科學# #數學# #密碼學# #算法#
小石頭/編
RSA(Rivest-Shamir-Adleman)是一種非對稱加密算法,密鑰 分為 公鑰 PK=(e, n) 和 私鑰 SK=(d, n) ,其中 e, d, n 都是 正整數。
PK是公開的,任何人都可以通過下面的加密公式,用 PK 對 明文 M (為整數),進行加密 ,得到 密文 C (為整數),并發送給 接收者。
M? mod n = C
SK不公開,只有接收者知道,收到C后,可以通過下面的解密公式,得到M。
C? mod n = M
這里的 mod 稱為 模運算,對于 任意整數 a,b(≠0),做帶余除法,有,
a = qb + r,0 ≤ r < |b|
定義,
a mod b = r (a ≥ 0) 或 -r (a < 0)
RSA 密鑰 的構造方法如下:
1 任意選取 兩個 奇素數 p 和 q,令 n = pq;
2 計算 ψ(n)=(p-1)(q-1);
ψ(n) 稱為 歐拉函數, 表示:小于 n 并且 與 n 互素 的 正整數 個數。若 整數 a 和 b 的最大公約數 (a, b) = 1,則稱 a 與 b 互素。
對于 素數 p 而言,任何 小于 p的 正整數 顯然 和 p 互素,小于p 的正整數 個數 是 p-1,因此 ψ(p) = p-1,同理 ψ(q) = q-1。
又顯然 (p,q) = 1,根據,
立即得到:
ψ(n)=(p-1)(q-1)
3 選取 正整數 1 < e < ψ(n) ,使得 (e, ψ(n)) = 1 ①;
由于,ψ(n)=(p-1)(q-1) > 1,故 一定存在 小于 ψ(n) 與 ψ(n) 互素 的 非1 正整數 e。
4 求 e 的 模 ψ(n) 逆 d,即,求 正整數 1 < d < ψ(n),使得 ed mod ψ(n) = 1 ②;
根據,
由①有,
1 = (e, ψ(n)) = (ψ(n), e) = cψ(n) + de
再利用 模運算法則:
于是有,
1 = 1 mod ψ(n) = (cψ(n) + de) mod ψ(n) = (cψ(n) mod ψ(n) + de) mod ψ(n) = (0 + de) mod ψ(n) = de mod ψ(n)
這樣我們就證明了 d 的存在性。
5 銷毀 p,q,ψ(n),只保留 e, d, n 分別組成 PK=(e, n) 和 SK=(d, n)。
我們需要證明,用上面方法構造的 PK 和 SK,對于 加密公式 和 解密公式 有效,為此我們僅需要驗證,
(M? mod n)? mod n = M
即可。
根據 模運算 法則:
上面等式,
左邊 = (M?)? mod n = M?? mod n
而由 ② 有,
ed = kψ(n) +1, k 是某個正整數
于是,
左邊 = M??????1 mod n = (M?)????M mod n
再根據 模運算 法則:
有,
左邊 = ((M?)???? mod n)M mod n
又有,
這里恒等式的意義是:若 a mod m = b mod m,則稱 a 和 b 模 m 同余,記為 a ≡ b (mod m)。
因為 n = pq,p和q都是素數,所以 我們只要保證,
☆ M ≠ p,q
則一定有 (M?, n) = 1,這樣利用 費馬小定理,有,
左邊 = 1M mod n = M mod n
如果再保證,
★ |M| < n
則,
左邊 = M = 右邊
這樣就證明了前面的等式。
類似地,我們還能證明:(M? mod n)? mod n = M,這說明:用SK加密,用PK解密,也行。
一個栗子:
小明 和 貝貝 的交往,遭到雙方家人的反對,這天 小明 想要 貝貝告訴他 約會地點,但又不想監控他們通信的家人知道,于是 小明 選取 p = 3, q = 11 兩個 奇素數,得到,
n = 3×11 = 33
并計算出,
ψ(n) = (3-1)×(11-1) = 20
由 (3, 20) = 1, 選 e = 3,又,
3×7 = 21 = 20 + 1 ? 3×7 mod 20 = 1
故 d = 7,然后,小明 構造 PK=(3, 33), SK=(7, 33),并將 PK 以明文的方式發送個 給貝貝。
貝貝選擇的約會地點是:漠河舞廳,寫成拼音就是 mo he wu ting。
貝貝和小明約定:
這使得 ☆ 和 ★ 得到保證。
于是 m = 14 是m的明文,根據加密公式,得到 m 的密文 143 mod 33 = 5,然后發送個小明,小明受到 5 后,使用解密公式,得到明文 5? mod 33 = 14,再根據約定,就知道 14 = m。
對于 后續的 o he wu ting,依此重復以上的操作,最終,小明就知道了 約會地點。
當然,手動算畢竟很麻煩,于是小明 寫了一個 簡單的 JavaScript 代碼如下:
function is_prime(n) {
for(let k = 2; k <= Math.sqrt(n); k++)
if (!(n % k)) return false;
return true;
}
function gen_key(p, q) {
let n = p*q, y = (p-1)*(q-1);
let e = 3;
while (is_prime(e) && !(y % e))
e += 2;
let d = 2;
while (!(d*e % y === 1))
d++;
return [e, d, n]
}
let encrypt = (M, e, n) => Math.pow(M, e) % n;
let decrypt = (C, d, n) => Math.pow(C, d) % n;
RSA 在實際應用時,會選取 很大的 兩個 奇素數 p, q,這樣不僅使得 n非常大,監聽者 很難 通過因子分解 n 得到 p 和 q,而且可以讓 任何 M < p,q,于是 ☆ 和 ★ 也就得到了保證。
另外,還需要注意:
不妨設 p ≤ q,令 ε=q-p 則有,
n = pq = (q-ε)q = q2-εq
于是,
q = (ε + √ (ε2 + 4n)) / 2
若 p 和 q 離得很近,則 ε 就很小,于是我們可以從 0 開始 通過不斷 嘗試 得到 q。
由于,e 和 ψ(n) 都很大,我們很難通過 嘗試的方法 求的 d,這時就需要 使用 秦九韶的 大衍求一術,具體方法如下:
對 ψ=ψ(n) 和 e 進行輾轉相除(帶余除法),有,
ψ = q?e + r?
e = q?r? + r?
r? = q?r? + r?
...
r??? = q?r??? + r?,(r?=1)
構造兩個數列,
c?=0,c?=1, c?=q?c???+c???
d?=1,d?=q?, d?=q?d???+d???
我們斷定有,
命題:c?ψ - d?e = (-1)??1r? ③
證明:
c?ψ - d?e = (q?c?+c?)ψ - (q?d?+d?)e = q?ψ - (q?q?+1)e = q?(q?e + r?) - (q?q?+1)e = q?r? - e = -r? = (-1)2?1r?
命題 成立。
c???ψ - d???e = (q???c?+c???)ψ - (q???d?+d???)e = q???c?ψ + c???ψ - q???d?e - d???e = q???(c?ψ - d?e) + (c???ψ - d???e) = q??? (-1)??1r? + (-1)??1?1r??? = (-1)??1(q??? r? - r???) = (-1)??1(-r???) = (-1)??1?1r???
命題 成立,于是 歸納得證!▌
c?ψ - d?e = (-1)??1r? = -1
于是,
d?e mod ψ = (c?ψ + 1) mod ψ = 1
故 d? 就是所求的 d。
r??? = q???r? + r???, (q??? = r??? - 1, r??? = 1)
u+1就是偶數,于是這樣根據③ 有,
c???ψ - d???e = (-1)??1?1r??? = -1
于是,
d???e mod ψ = (c???ψ + 1) mod ψ = 1
故 d??? 就是所求的 d。
大衍求一術 寫成 JavaScript代碼 如下:
function dyqysh(y, e) {
let d, d1 = 0, d2 = 1
let r1 = y, r2 = e;
let isodd = false;
do {
isodd = !isodd;
let r = r1 % r2, q = (r1 - r) / r2;
// console.log(`${r1} = ${q}*${r2}+${r}`);
d = q*d2 + d1;
d1 = d2, d2 = d;
r1 = r2, r2 = r;
} while(!(r2 === 1))
if (isodd)
d = (r1-1)*d2 + d1;
return d;
}
好了,關于 RSA,小石頭目前能想到的就這么多內容了,希望對大家有所幫助。
附錄: 推導模運算法則。
有帶余除法 a = km + r,于是有,
a + b = km + r + b
于是,
(a + b) mod m = (r + b) mod m
而根據模運算定義有,
a mod m = r
帶入前式,立即得證。
令 a mod m = k,于是有, a ≡ k (mod m) ,根據同余性質,有,
a? ≡ k? (mod m)
也就是說,
a? mod m = k? mod m = (a mod m)? mod m
與法則1推導類似,由帶余除法 a = km + r,有,
ab = bkm + rb
于是,
ab mod m = rb mod m = (a mod m)b mod m
(關于,本文使用的定理的證明,見小石頭首頁中的相關文章。)
們通過一個例子,來理解RSA算法。假設愛麗絲要與鮑勃進行加密通信,她該怎么生成公鑰和私鑰呢?
第一步,隨機選擇兩個不相等的質數p和q。
愛麗絲選擇了61和53。(實際應用中,這兩個質數越大,就越難破解。)
第二步,計算p和q的乘積n。
愛麗絲就把61和53相乘。
n = 61×53 = 3233
n的長度就是密鑰長度。3233寫成二進制是110010100001,一共有12位,所以這個密鑰就是12位。實際應用中,RSA密鑰一般是1024位,重要場合則為2048位。
第三步,計算n的歐拉函數φ(n)。
根據公式:
φ(n) = (p-1)(q-1)
愛麗絲算出φ(3233)等于60×52,即3120。
第四步,隨機選擇一個整數e,條件是1< e < φ(n),且e與φ(n) 互質。
愛麗絲就在1到3120之間,隨機選擇了17。(實際應用中,常常選擇65537。)
第五步,計算e對于φ(n)的模反元素d。
所謂"模反元素"就是指有一個整數d,可以使得ed被φ(n)除的余數為1。
ed ≡ 1 (mod φ(n))
這個式子等價于
ed - 1 = kφ(n)
于是,找到模反元素d,實質上就是對下面這個二元一次方程求解。
ex + φ(n)y = 1
已知 e=17, φ(n)=3120,
17x + 3120y = 1
這個方程可以用"擴展歐幾里得算法"求解,此處省略具體過程。總之,愛麗絲算出一組整數解為 (x,y)=(2753,-15),即 d=2753。
至此所有計算完成。
第六步,將n和e封裝成公鑰,n和d封裝成私鑰。
在愛麗絲的例子中,n=3233,e=17,d=2753,所以公鑰就是 (3233,17),私鑰就是(3233, 2753)。
實際應用中,公鑰和私鑰的數據都采用ASN.1格式表達(實例)。
回顧上面的密鑰生成步驟,一共出現六個數字:
p
q
n
φ(n)
e
d
這六個數字之中,公鑰用到了兩個(n和e),其余四個數字都是不公開的。其中最關鍵的是d,因為n和d組成了私鑰,一旦d泄漏,就等于私鑰泄漏。
那么,有無可能在已知n和e的情況下,推導出d?
(1)ed≡1 (mod φ(n))。只有知道e和φ(n),才能算出d。
(2)φ(n)=(p-1)(q-1)。只有知道p和q,才能算出φ(n)。
(3)n=pq。只有將n因數分解,才能算出p和q。
結論:如果n可以被因數分解,d就可以算出,也就意味著私鑰被破解。
可是,大整數的因數分解,是一件非常困難的事情。目前,除了暴力破解,還沒有發現別的有效方法。維基百科這樣寫道:
"對極大整數做因數分解的難度決定了RSA算法的可靠性。換言之,對一極大整數做因數分解愈困難,RSA算法愈可靠。
假如有人找到一種快速因數分解的算法,那么RSA的可靠性就會極度下降。但找到這樣的算法的可能性是非常小的。今天只有短的RSA密鑰才可能被暴力破解。到2008年為止,世界上還沒有任何可靠的攻擊RSA算法的方式。
只要密鑰長度足夠長,用RSA加密的信息實際上是不能被解破的。"
舉例來說,你可以對3233進行因數分解(61×53),但是你沒法對下面這個整數進行因數分解。
12301866845301177551304949
58384962720772853569595334
79219732245215172640050726
36575187452021997864693899
56474942774063845925192557
32630345373154826850791702
61221429134616704292143116
02221240479274737794080665
351419597459856902143413
它等于這樣兩個質數的乘積:
33478071698956898786044169
84821269081770479498371376
85689124313889828837938780
02287614711652531743087737
814467999489
×
36746043666799590428244633
79962795263227915816434308
76426760322838157396665112
79233373417143396810270092
798736308917
事實上,這大概是人類已經分解的最大整數(232個十進制位,768個二進制位)。比它更大的因數分解,還沒有被報道過,因此目前被破解的最長RSA密鑰就是768位。
有了公鑰和密鑰,就能進行加密和解密了。
(1)加密要用公鑰 (n,e)
假設鮑勃要向愛麗絲發送加密信息m,他就要用愛麗絲的公鑰 (n,e) 對m進行加密。這里需要注意,m必須是整數(字符串可以取ascii值或unicode值),且m必須小于n。
所謂"加密",就是算出下式的c:
me ≡ c (mod n)
愛麗絲的公鑰是 (3233, 17),鮑勃的m假設是65,那么可以算出下面的等式:
6517 ≡ 2790 (mod 3233)
于是,c等于2790,鮑勃就把2790發給了愛麗絲。
(2)解密要用私鑰(n,d)
愛麗絲拿到鮑勃發來的2790以后,就用自己的私鑰(3233, 2753) 進行解密。可以證明,下面的等式一定成立:
cd ≡ m (mod n)
也就是說,c的d次方除以n的余數為m。現在,c等于2790,私鑰是(3233, 2753),那么,愛麗絲算出
27902753 ≡ 65 (mod 3233)
因此,愛麗絲知道了鮑勃加密前的原文就是65。
至此,"加密--解密"的整個過程全部完成。
我們可以看到,如果不知道d,就沒有辦法從c求出m。而前面已經說過,要知道d就必須分解n,這是極難做到的,所以RSA算法保證了通信安全。
你可能會問,公鑰(n,e) 只能加密小于n的整數m,那么如果要加密大于n的整數,該怎么辦?有兩種解決方法:一種是把長信息分割成若干段短消息,每段分別加密;另一種是先選擇一種"對稱性加密算法"(比如DES),用這種算法的密鑰加密信息,再用RSA公鑰加密DES密鑰。
最后,我們來證明,為什么用私鑰解密,一定可以正確地得到m。也就是證明下面這個式子:
cd ≡ m (mod n)
因為,根據加密規則
me ≡ c (mod n)
于是,c可以寫成下面的形式:
c = me - kn
將c代入要我們要證明的那個解密規則:
(me - kn)d ≡ m (mod n)
它等同于求證
med ≡ m (mod n)
由于
ed ≡ 1 (mod φ(n))
所以
ed = hφ(n)+1
將ed代入:
mhφ(n)+1 ≡ m (mod n)
接下來,分成兩種情況證明上面這個式子。
(1)m與n互質。
根據歐拉定理,此時
mφ(n) ≡ 1 (mod n)
得到
(mφ(n))h × m ≡ m (mod n)
原式得到證明。
(2)m與n不是互質關系。
此時,由于n等于質數p和q的乘積,所以m必然等于kp或kq。
以 m = kp為例,考慮到這時k與q必然互質,則根據歐拉定理,下面的式子成立:
(kp)q-1 ≡ 1 (mod q)
進一步得到
[(kp)q-1]h(p-1) × kp ≡ kp (mod q)
即
(kp)ed ≡ kp (mod q)
將它改寫成下面的等式
(kp)ed = tq + kp
這時t必然能被p整除,即 t=t'p
(kp)ed = t'pq + kp
因為 m=kp,n=pq,所以
med ≡ m (mod n)
原式得到證明。
鏈接文章:
http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html
https://zh.wikipedia.org/wiki/RSA%E5%8A%A0%E5%AF%86%E6%BC%94%E7%AE%97%E6%B3%95
*請認真填寫需求信息,我們會在24小時內與您取得聯系。