PS:歡迎轉載,但請注明出處,謝謝配合。
前言:
PEM是OpenSSL和許多其他SSL工具的標准格式,OpenSSL 使用PEM 文件格式存儲證書和密鑰。這種格式被設計用來安全的包含在ascii甚至富文本文檔中,如電子郵件。這意味着您可以簡單的復制和粘貼pem文件的內容到另一個文檔中。
PEM文件是Base64編碼的證書。PEM證書通常用於web服務器,因為他們可以通過一個簡單的文本編輯器,很容易地轉換成可讀的數據。通常當一個PEM編碼在文本編輯器中打開文件,它會包含不同的頁眉和頁腳。
-----BEGIN CERTIFICATE REQUEST----- and -----END CERTIFICATEREQUEST-----
CSR(證書簽名請求)
-----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATEKEY-----
私鑰
-----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----
證書文件
PKCS #8: Private-Key Information Syntax(語法) Standard(標准)
OpenSSL:是一個強大的安全套接字層密碼庫,囊括主要的密碼算法、常用的密鑰和證書封裝管理功能及SSL協議,並提供豐富的應用程序供測試或其它目的使用。
OpenSSL整個軟件包大概可以分成三個主要的功能部分:密碼算法庫、SSL協議庫以及應用程序。OpenSSL的目錄結構自然也是圍繞這三個功能部分進行規划的。
一、OpenSSL生成pem格式公私鑰
1、生成RSA私鑰
openssl genrsa -out rsa_private_key.pem1024
該命令會生成1024位的私鑰,運行,如下圖:
生成私鑰文件rsa_private_key.pem,內容如下:
用記事本方式打開它,可以看到-----BEGIN RSA PRIVATE KEY-----開頭,-----END RSA PRIVATE KEY-----結尾的字符串,這個就是原始的私鑰。
備注:
若運行openssl.exe,會進入OpenSSL命令行界面,此時輸入命令時,則無需再寫openssl。(只是該命令行界面中,暫時無法拷貝,本人太懶,不太喜歡)
2、RSA私鑰轉換成PKCS8格式
openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem-outform PEM -nocrypt
可以看到,控制台打印出的內容,-----BEGIN PRIVATE KEY-----開頭,-----END PRIVATE KEY-----結尾的字符串,這個就是PKCS#8格式的私鑰。
備注:
使用該命令,將私鑰轉成PKCS#8格式,但原rsa_private_key.pem文件中的私鑰字符串並沒有任何變化。但控制台輸出的private key,跟rsa_private_key.pem文件中的private key,不一樣。若需使用PKCS8格式的私鑰,即控制台中顯示的私鑰,將其拷貝出來即可。
切記:
opensslpkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM –nocrypt
“-”書寫正確,上述–nocrypt,因為前面的“–”不是英文的,導致nocrypt失效,所以還需要輸入密碼。需要輸入兩次密碼,運行,如下圖:
可以看到,控制台打印出的內容,-----BEGIN ENCRYPTED PRIVATE KEY-----開頭,-----END ENCRYPTED PRIVATE KEY-----結尾的字符串,這個就是加了密的PKCS#8格式的私鑰。
因為輸入了密碼,轉換后的字符串不一樣,會比加了-nocrypt的長一些,所以原來的程序解析不了該私鑰字符串,會出錯。
3、生成RSA公鑰
openssl rsa -in rsa_private_key.pem-pubout -out rsa_public_key.pem
運行,如下圖:
生成公鑰文件rsa_public_key.pem,內容如下:
用記事本方式打開它,可以看到-----BEGIN PUBLIC KEY-----開頭,-----END PUBLIC KEY-----結尾的字符串,這個就是公鑰。
4、Java使用pem文件內容,示例代碼
1)私鑰簽名
a)獲取私鑰
//獲取KeyFactory,指定RSA算法
KeyFactorykeyFactory = KeyFactory.getInstance("RSA");
//將BASE64編碼的私鑰字符串進行解碼
BASE64Decoderdecoder = newBASE64Decoder();
byte[] encodeByte = decoder.decodeBuffer(priKey);
//將BASE64解碼后的字節數組,構造成PKCS8EncodedKeySpec對象,生成私鑰對象
PrivateKeyprivatekey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodeByte));
b)使用私鑰,對數據進行簽名
//獲取Signature實例,指定簽名算法(本例使用SHA1WithRSA)
Signaturesignature = Signature.getInstance("SHA1WithRSA");
//加載私鑰
signature.initSign(privatekey);
//更新待簽名的數據
signature.update(plain.getBytes("UTF-8"));
//進行簽名
byte[] signed = signature.sign();
//將加密后的字節數組,轉換成BASE64編碼的字符串,作為最終的簽名數據
BASE64Encoderencoder = newBASE64Encoder();
return encoder.encode(signed);
2)公鑰驗簽
a)獲取公鑰
//獲取KeyFactory,指定RSA算法
KeyFactorykeyFactory = KeyFactory.getInstance("RSA");
//將BASE64編碼的公鑰字符串進行解碼
BASE64Decoderdecoder = newBASE64Decoder();
byte[] encodeByte = decoder.decodeBuffer(pubKey);
//將BASE64解碼后的字節數組,構造成X509EncodedKeySpec對象,生成公鑰對象
PublicKeypublicKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodeByte));
b)使用公鑰,進行驗簽
//獲取Signature實例,指定簽名算法(與之前一致)
Signaturesignature = Signature.getInstance("SHA1WithRSA");
//加載公鑰
signature.initVerify(publicKey);
//更新原數據
signature.update(plain.getBytes("UTF-8"));
//公鑰驗簽(true-驗簽通過;false-驗簽失敗)
BASE64Decoderdecoder = newBASE64Decoder();
returnsignature.verify(decoder.decodeBuffer(sign));
備注:
驗簽時,簽名數據需要先BASE64解碼