20190811 加解密知識之——通過openssl工具生成公私鑰

這篇文章,與其說是在分享知識,倒不如說是自己在總結以及做反思。

openssl

openssl工具很強大,我們可以通過它來生成公私鑰,以及使用openssl指令來實現密鑰文件格式的轉換。

反思

我的博客裏閱讀量最高的一篇文章,是在2018-07-02這天寫的,一篇名爲——《pem文件的生成》的文章。現在回過頭來看,簡直是不知所謂的一篇,誤人子弟。

可是我在思考,爲什麼這篇閱讀量是最高?可能因爲和標題名有關吧。當時爲什麼起這個名字?因爲當時是對接銀聯接口,銀聯提供了加解密的工具包,然後其中使用的公私鑰是以pem爲後綴的。然後我需要自己生成一對公私鑰pem文件,因此就這麼命名了。也許像我當時那樣對密碼學知識知之甚少又需要快速解決問題的人而言,最懶最快的方法就是直接百度pem文件如何生成吧。所以就導致這篇文章的閱讀量比其他的高吧。畢竟大家看別人博客,都是在遇到問題時纔去搜索找答案。

其實,真的對openssl、linux以及祕鑰算法有一些瞭解的人,都會覺得《pem文件的生成》這個標題莫名其妙,或者說很不恰當吧。

感覺自己寫文字很多廢話,一直不入主題。

疑惑之——文件後綴?

網上有許許多多的關於通過openssl生成rsa公私鑰的文章,有的給rsa私鑰命名爲server.key,有的命名爲prikey.pem,他們有什麼區別呢?我以前一直被這個問題困擾。

其實沒區別。因爲在linux中,萬物皆文件,文件後綴只是有助於直接表示文件的類型,並沒有實際意義。也就是說你起什麼後綴名都一樣。以及文件名,想怎麼命名都可以,只要自己能理解。

疑惑之——同一作用有不同的指令?

其次有的文章生成rsa私鑰用的是genrsa指令,有的文章裏寫的是genpkey指令?
其實都可以,只不過genrsa是過時的,而官方建議用genpkey來代替genrsa。兩種指令生成rsa私鑰的寫法還是有點區別的:

openssl genrsa -out pri1.pem 2048
openssl genpkey -algorithm RSA -out pri1_pkcs8.pem -pkeyopt rsa_keygen_bits:2048 

默認的,openssl genpkey指令默認輸出的是pem格式的文件,即默認帶上-outform PEM,因此如果需要生成DER文件,則需要顯式的設置-outform DER
另外,openssl openrsa生成的rsa私鑰內容是pkcs1格式的,而openssl genpkey生成的rsa私鑰內容是pkcs8格式的。

疑惑之——pkcs1、pcks8的轉換

對於genrsa指令,生成的rsa私鑰內容是pkcs1格式的,對於genpkey指令,生成的rsa私鑰內容是pkcs8的。當你用Java語言的工具去加載genrsa生成的私鑰的時候,是無法加載的。

當我們用vim、cat指令分別查看pkcs1和pkcs8的私鑰的內容時:

pkcs1私鑰的標誌行是:
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----
pkcs8私鑰的標誌行是:
-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----

就能看出他們是有區別的。

不同的開發語言對私鑰證書的加載處理不同,像使用Java工具類加載私鑰文件的話,需要的是pkcs8格式,而PHP好像是pkcs1。總之可以通過這兩個指令進行相互轉化。

## pcks1與pkcs8的相互轉換指令爲:
1、pkcs1轉pcks8(使用openssl pkcs8指令)
openssl pkcs8 -topk8 -in pri_pkcs1.pem -out pri_pkcs8.pem -nocrypt
2、pkcs8轉pkcs1(使用openssl rsa指令)
openssl rsa -in pri_pkcs8.pem -out pri_pkcs1.pem

疑惑之——pem/der?pkcs1/pkcs8?

還有個很困擾我的地方——爲什麼一個rsa私鑰既有pem/der之分,又有pkcs1/pkcs8之分。
我的理解是pkcs1和pkcs8只是內容上排列順序的問題不同,而pem/der是整個文件的保存形式不同,pem是Base64編碼字符串,而der是保存的二進制格式。因此他們並不衝突。

至於pkcs1和pkcs8的內容區別,可以參考這篇文章:https://blog.csdn.net/superwfei/article/details/83782678

我之前的那篇文章,其實只需要這兩個指令就能夠生成我想要的公私鑰。但由於當時什麼都不懂,連公鑰和證書的區別都不知道,最後也是誤打誤撞把問題給生成了公私鑰,可其實什麼都沒有搞懂。那篇文章,真的太糟糕了。
其實,通過下面的兩個指令,就可以生成滿足Java要求的pkcs8格式的公私鑰,且是PEM格式的。

1、生成pem格式的pcks8的rsa私鑰,:
openssl genpkey -algorithm RSA -out pri_pkcs8.pem -pkeyopt rsa_keygen_bits:2048 -outform PEM
2、通過私鑰導出公鑰:
openssl pkey -in pri_pkcs8.pem -pubout -out pub.pem

openssl常用指令總結

最後對常用的指令做個總結:

1、生成格式爲pkcs8的rsa祕鑰:(默認是PEM格式,如要生成DER格式的,要顯式加上-outform DER)
	1.1、使用openssl genpkey指令
		openssl genpkey -algorithm RSA -out pri1_pkcs8.pem -pkeyopt rsa_keygen_bits:2048  -pkeyopt rsa_keygen_pubexp:3
	1.2、使用openssl genrsa指令
		1.2.1、生成pkcs1格式的rsa私鑰
			openssl genrsa -out pri2_pkcs1.pem 2048
		1.2.2、pkcs1轉pkcs8(通過openssl pkcs8指令)
			openssl pkcs8 -topk8 -in pri2_pkcs1.pem -out pri2_pkcs8.pem -nocrypt
		1.2.3、pkcs8轉pkcs1(通過openssl rsa指令)
			openssl rsa -in pri2_pkcs8.pem -out pri2_pkcs1.pem
2、通過私鑰生成公鑰(從私鑰文件中提取公鑰信息)
	2.1、使用openssl rsa指令(不論私鑰格式是pkcs1還是pkcs8都一樣)
		openssl rsa -pubout -in p1.pk8 -out pub1.pem
	2.2、使用openssl pkey(公鑰私鑰處理工具)
		openssl pkey -pubout -in p1.pk8 -out pub1.pem
3、查看私鑰公鑰內容(默認是PEM格式,如要查看DER格式文件,要顯式加上-inform DER)
	3.1、使用openssl pkey指令查看公私鑰信息
		3.1.1、查看私鑰文件二進制信息(私鑰文件包含公鑰信息)
			openssl pkey -in p1.pk8 -text
		3.1.2、查看公鑰二進制信息(加上:-pubin)
			openssl pkey -pubin -in pub1.pem -text
		3.1.3、openssl pkey默認使用PEM格式去讀取
			默認以pem格式去讀取,即默認是用了-inform PEM,如果文件是二進制的即DER格式的,則要顯式加上-inform DER。如果以PEM方式讀取DER文件,會有錯誤提示信息,如:
			openssl pkey -in p2.pk8.der -text
			unable to load key
			139653956810408:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:707:Expecting: ANY PRIVATE KEY
			正確做法是聲明讀取文件時指定對應的格式:
			openssl pkey -in p2.pk8.der -text -inform DER
4、公私鑰PEM、DER格式的轉換
	3.1、使用openssl pkey進行私鑰的PEM、DER格式的相互轉換,例子如:
		openssl pkey -in p2.pk8.der -inform DER -out p2.pk8.pem -outform PEM
	3.2、使用openssl pkey進行公鑰格式的轉換(公鑰得加上-pubin參數)
		openssl pkey -in pub.der -inform DER -out pub.pem -outform PEM -pubin
		

最後

到底要怎麼學習openssl指令?看別人的文章,可是文章那麼多,到底哪篇的質量高,哪篇寫的才準確?我也曾經問自己這個問題。或者說我這次看的是a寫的openssl指令用法,下次看的又是b的寫的openssl常用指令。這樣並不好。

所以爲什麼不去看官方文檔呢?

這個時候就得強烈推薦linux下的man指令了。man的全稱是manual,即手冊、操作手冊的意思。在linux下直接可以通過man指令去查看openssl指令的使用的官方手冊。

使用如:man openssl,可以查看openssl支持的命令有哪些。
再如通過man genpkey可以看到genpkey命令支持哪些參數,以及官網提供的指令demo。

這樣,每次對指令有所遺忘的時候,就可以通過官方手冊重新溫習了。官方文檔,總是最準確的吧~

當然了,如果不想看英文的官方文檔,這裏還有一篇很詳細很完整的文章可以參考:https://blog.csdn.net/liao20081228/article/details/77159039

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章