非對稱加密演算法RSA中的公鑰和私鑰

我妻禮彌發表於2018-06-03

*本文只討論一個問題,在非對稱加密演算法RSA中,什麼是公鑰什麼是私鑰

非對稱加密演算法

非對稱加密演算法有很多,例如RSA、Elgamal、揹包演算法、Rabin、D-H、ECC(橢圓曲線加密演算法)。

在在這些演算法中,RSA最為常用,因此,在沒有特殊說明的情況下,常說的公鑰、私鑰都指的的RAS的公鑰、私鑰。

這裡也是以RSA演算法為例,來討論非對稱加密中的公鑰和私鑰

RSA加密演算法

要想了解公鑰和私鑰的區別,就要從它們的產生開始。
這裡我預設讀者已經瞭解了RSA演算法。如果還不瞭解,請先去看這兩篇文章。
RSA演算法原理(一)
RSA演算法原理(二)
特別是 RSA演算法原理(二)一定要仔細看一遍,不然下面的內容你將看不懂。

RSA加密演算法中的公鑰和私鑰

看過上面兩篇文章的人應該已經知道了,在RSA加密演算法中有6個非常關鍵數字,他們是演算法的核心。
這6個數字分別是

  • 大質數p
  • 另一個大質數q
  • p和q的乘積n
  • n的尤拉函式φ(n)  注:φ(n) = (p-1)(q-1)
  • 一個隨機整數e,1< e < φ(n),且e與φ(n) 互質
  • e對於φ(n)的模反元素d  注:所謂"模反元素"就是指有一個整數d,可以使得ed被φ(n)除的餘數為1。

其中(n,e)在一起組成了公鑰,(n,d)在一起組成了私鑰。

現在讓我們來回答最開始提出是問題,什麼是公鑰,什麼是私鑰。
答:公鑰為(n,e) 私鑰為(n,d)

文章到此結束,謝謝大家的閱讀!

番外1

其實我們仔細想想就會發現,(n,e) 和 (n,d) 根本沒什麼區別。為什麼一個叫公鑰一個叫私鑰呢?反過來行不行?

答案是可以的,根據演算法原理我們知道,只有 (n,e) 是算不出 (n,d) 的,反過來只有 (n,d) 也是算不出 (n,e) 的。所以反過來也是安全的。

那我們就不經思考了,既然反過來也可以,那公鑰私鑰還有什麼區別,為什麼一個叫公鑰,一個叫私鑰呢。

我想了很久,最終想到了一個合理的解釋,被公開的祕鑰就叫公鑰,沒有被公開的祕鑰就叫私鑰。網上多數的回答也證實了我的想法。

原來 公鑰和私鑰並不是根據 (n,e) 和 (n,d) 區分的,而是根據使用上的不同來區分的

番外2

讓我們再思考一個問題。
在工作中,我們經常會用到各種生成祕鑰的工具。這些工具一般會為我們生成兩個檔案。一個公鑰檔案,假設叫public.key。一個私鑰檔案,假設叫private.key。

根據上文的結論,我們是否能將private.key當做公鑰公開,將public.key當做私鑰,保留呢?

答案是 不可以!!!大家千萬別去這麼做!

為什麼,按照上文的結論 “被公開的祕鑰就叫公鑰,未被公開的祕鑰就叫私鑰”,不應該是可以嗎?為什麼不可以?

除非,上面的結論是錯的!!!

是的,上面的結論是錯的,公鑰和私鑰並不是根據使用上的不同來區分的,也不是根據(n,e) 和 (n,d) 來區分的。

那公鑰和私鑰是通過什麼來區分的,到底有沒有區別。
彆著急,讓我們先來看一個有趣的現象

根據私鑰推匯出公鑰

在一些祕鑰生成工具中,有一個功能叫做 根據私鑰推匯出公鑰 ,這個功能可以根據私鑰檔案,推匯出公鑰檔案來。 比如螞蟻金服的祕鑰生成工具

非對稱加密演算法RSA中的公鑰和私鑰

學習了RSA演算法原理的人肯定想說,這不可能,不管私鑰是(n,d)還是(n,e) ,只有 (n,e) 是算不出 (n,d) 的,只有 (n,d) 也是算不出 (n,e) 的。

難道是阿里的人太nb了,可以算出來嗎?

當然不是!要真是這樣,這種加密演算法就不安全了。

那這個功能是怎麼實現的了!
答案是私鑰中包含了公鑰資訊!!!

私鑰中包含公鑰資訊

讓我們做個實驗,隨便用什麼祕鑰生成工具,生成一對祕鑰,然後以文字的方式開啟,你會發現,私鑰的內容總是比公鑰的多! 再仔細觀察你會發現 公鑰中的部分內容在私鑰中也存在!

這裡最好用文字對比工具,這樣看的比較清楚,我知道你們懶得去動手,所以我幫你們做好了!

非對稱加密演算法RSA中的公鑰和私鑰
左邊是公鑰的內容,右邊是私鑰的內容,可以看到中間有一行內容是一樣的!

為什麼會這樣, 公鑰難道不是(n,e) 私鑰難道不是(n,d) 嗎!


按照RSA演算法的定義,公鑰確實是(n,e) 私鑰也確實的(n,d)。

但是,實際應用中,人們發現,這樣做的話,公鑰和私鑰的重要性和地位就一樣了,但其實我們最關心的是私鑰,私鑰才是最重要的。

於是
在pkcs標準中,pkcs#1規定,私鑰包含(n,e,d,p,q),公鑰包含(n,e)
在pkcs標準中,pkcs#1規定,私鑰包含(n,e,d,p,q),公鑰包含(n,e)
在pkcs標準中,pkcs#1規定,私鑰包含(n,e,d,p,q),公鑰包含(n,e)

重要的話說三遍

(pkcs全稱Public-Key Cryptography Standards (公開祕鑰加密標準),旗下包含十幾個子標準,每個子標準負責一個領域。)

這樣做有兩個好處

  1. 公鑰和私鑰的重要性和地位不再一樣,私鑰的重要性和地位遠高於公鑰,這有利於私鑰的持有者。
  2. 擁有了私鑰,就相當於擁有了公鑰,使用起來特別方便,就算公鑰弄丟了,還可以通過私鑰生成出來。

(從上文我們瞭解到,理論和實現還是有區別的,理論跟偏向原理,而實現更偏向使用,所以實際中的私鑰會比理論中的私鑰多幾個引數。)


現在我們可以回答最開始提出的問題了,在非對稱加密演算法RSA中,什麼是公鑰什麼是私鑰。

  1. 公鑰首先是一種祕鑰,它包含(n,e),可以被公開,不能推匯出私鑰
  2. 私鑰首先也是一種祕鑰,他有兩種語法格式,pkcs#8標準語法格式的和pkcs#1標準語法格式,其中pkcs#1規定,私鑰包含(n,e,d,p,q),不可以被公開,可以推匯出公鑰。

在實際應用中,絕大多數對RSA的實現,都遵循pkcs的標準,即私鑰能推出公鑰,但公鑰不能推出私鑰

總結

通過上面的文章我們至少要知道以下幾點

  • 公鑰和私鑰不一樣
  • 私鑰可以推匯出公鑰,但公鑰無法推匯出私鑰(私鑰包含公鑰)
  • 理論和實現 是有出入的,所以只學習理論是無法為我們解惑的,必須聯絡實際進行思考才能解答我們的疑問。

番外3

祕鑰格式

生成的祕鑰一般會通過PEM編碼成文字來儲存。具體如下:

非對稱加密演算法RSA中的公鑰和私鑰

  • PKCS1語法格式私鑰:傳統格式,PHP、.NET一般使用此格式
  • PKCS8語法格式私鑰:java一般使用此格式
  • PKCS1格式和PKCS8格式的私鑰,匯出的公鑰內容是一摸一樣的

公鑰是不分 pkcs1 格式和 pkcs8格式的,因為公鑰就只有一種語法格式。

RSA金鑰語法

RSA公鑰在PKCS#1標準中定義的語法

RSAPublicKey ::= SEQUENCE {
    modulus           INTEGER,  -- n
    publicExponent    INTEGER   -- e
}
(n,e)
複製程式碼

RSA私鑰在PKCS#1標準中定義的語法

RSAPrivateKey ::= SEQUENCE { 
version	Version,	//版本 
modulus	INTEGER,	// RSA合數模 n 
publicExponent	INTEGER,	//RSA公開冪 e 
privateExponent	INTEGER,	//RSA私有冪 d 
prime1	INTEGER,	//n的素數因子p 
prime2	INTEGER,	//n的素數因子q 
exponent1	INTEGER,	//值 d mod (p-1) 
exponent2	INTEGER,	//值 d mod (q-1) 
coefficient	INTEGER,	//CRT係數 (inverse of q) mod p 
otherPrimeInfos	OtherPrimeInfos OPTIONAL 
}
(n,e,d,p,q)
複製程式碼

RSA私鑰在PKCS#8標準中定義的語法

pkcs#8 全稱 Private-Key Information Syntax Standard 私鑰資訊語法標準,是專門為私鑰而設計的規範,所以是不存在PKCS#8格式的公鑰這一說

PrivateKeyInfo ::= SEQUENCE {  
version	Version,	//版本 
privateKeyAlgorithm	PrivateKeyAlgorithmIdentifier, 	//演算法標示符 
privateKey	PrivateKey,  //私鑰
attributes		[0]  IMPLICIT Attributes OPTIONAL 
} 
複製程式碼

相關文章