2020年11月8日 星期日

OpenSSL筆記

How SSL/TLS works

SSL 加密步驟

SSL 讓瀏覽器(所謂的 client)要連到一個遠端網站(所謂的 server)之前,先要求這個網站提供身分認證,跟這個網站約定暗號(交換鑰匙),打好交情(建立加密的 session),才會心甘情願地跟這個網站連線。可以分成六個步驟:
1. 瀏覽器對想要連線的網站送出連線請求,同時要求網站驗證自己。
2. 網站將自己的 SSL 數位憑證 (SSL certificate) 回傳給 client,裡面包含了網站的 public key。
3. 瀏覽器驗證網站回傳的的 root certificate,透過 chain of trust 機制(請繼續看下去)確認這個證明文件是否可以被信認,同時也確認這個憑證是否過期。
4. 當認證通過,瀏覽器會用網站的 public key 建立一個 symmetric session key。
5. 網站用自己的 private key 解讀 session key,並且回傳一個確認訊息,開始一個被 SSL 保護的 session。
6. 這個 session key 會被用來加密所有之後瀏覽器與網站之間傳送的資料。

與 GnuTLS 相比,OpenSSL 後端具有以下潛在優勢(除了增加加密多樣性):
  • 更快
  • 已經是某些平台/應用程序的一部分
  • 公司通常更喜歡 OpenSSL 許可證,而不是 GnuTLS 帶來的所有許可證(包括 LGPLv3/GPLv2 gmp 庫)
  • FIPS 認證
  • 由於其更廣泛的用途而可能更安全

用openssl產生憑證的指令流程

產生CA 私鑰(CA角色)
openssl genrsa -out ./ca.key 2048


用這把私鑰產生一份自我簽署的憑證(CA角色)
openssl req -new -x509 -days 3650 -sha256 -subj "/C=TW/ST=Taipei/O=FOO/OU=BAR/CN=localhost/emailAddress=abc@gmail.com" -key ./ca.key -out ./ca.crt


產生 Server 的私鑰和 CSR(Server角色)
openssl genrsa -out ./server.key 2048

openssl req -new -sha256 -key ./server.key -subj "/C=TW/ST=Taipei/O=FOO/OU=BAR/CN=192.168.0.155/emailAddress=cde@gmail.com" -out ./server.csr


把剛剛產生的server CSR 丟給 CA 簽署,就可以拿憑證
openssl x509 -req -CAcreateserial -days 3560 -sha256 -CA ./ca.crt -CAkey ./ca.key -in ./server.csr -out ./server.crt 


驗證拿到的憑證
openssl verify -CAfile ./ca.crt ./server.crt


DER PEM cer crt key pfx等概念及區別

證書主要的文件類型和協議有: PEM、DER、PFX、JKS、KDB、CER、KEY、CSR、CRT、CRL 、OCSP、SCEP等。


一、編碼格式


X.509 - 這是一種證書標準,主要定義了證書中應該包含哪些內容.其詳情可以參考RFC5280,SSL使用的就是這種證書標準.


目前有以下兩種編碼格式.


1、PEM - Privacy Enhanced Mail,打開看文本格式,以"-----BEGIN..."開頭, "-----END..."結尾,內容是BASE64編碼.

查看PEM格式證書的信息:openssl x509 -in certificate.pem -text -noout

Apache和NGINX服務器偏向於使用這種編碼格式.


     PEM – Openssl使用 PEM(Privacy Enhanced Mail)格式來存放各種信息,它是 openssl 默認採用的信息存放方式。 Openssl 中的 PEM 文件一般包含如下信息:


內容類型:表明本文件存放的是什麼信息內容,它的形式為“——-BEGIN XXXX ——”,與結尾的“——END XXXX——”對應。


頭信息:表明數據是如果被處理後存放,openssl 中用的最多的是加密信息,比如加密算法以及初始化向量 iv。


信息體:為 BASE64 編碼的數據。可以包括所有私鑰(RSA 和 DSA)、公鑰(RSA 和 DSA)和 (x509) 證書。它存儲用 Base64 編碼的 DER 格式數據,用 ascii 報頭包圍,因此適合系統之間的文本模式傳輸。


使用PEM格式存儲的證書:

—–BEGIN CERTIFICATE—–

MIICJjCCAdCgAwIBAgIBITANBgkqhkiG9w0BAQQFADCBqTELMAkGA1UEBhMCVVMx

………

1p8h5vkHVbMu1frD1UgGnPlOO/K7Ig/KrsU=

—–END CERTIFICATE—–


使用PEM格式存儲的私鑰:

—–BEGIN RSA PRIVATE KEY—–

MIICJjCCAdCgAwIBAgIBITANBgkqhkiG9w0BAQQFADCBqTELMAkGA1UEBhMCVVMx

………

1p8h5vkHVbMu1frD1UgGnPlOO/K7Ig/KrsU=

—–END RSA PRIVATE KEY—–


使用PEM格式存儲的證書請求文件:

—–BEGIN CERTIFICATE REQUEST—–

MIICJjCCAdCgAwIBAgIBITANBgkqhkiG9w0BAQQFADCBqTELMAkGA1UEBhMCVVMx

………

1p8h5vkHVbMu1frD1UgGnPlOO/K7Ig/KrsU=

—–END CERTIFICATE REQUEST—–


2、DER – 辨別編碼規則 (DER) 可包含所有私鑰、公鑰和證書。它是大多數瀏覽器的缺省格式,並按 ASN1 DER 格式存儲。它是無報頭的 - PEM 是用文本報頭包圍的 DER。


DER - Distinguished Encoding Rules,打開看是二進制格式,不可讀.

查看DER格式證書的信息:openssl x509 -in certificate.der -inform der -text -noout

Java和Windows服務器偏向於使用這種編碼格式.


證書編碼的轉換

PEM轉為DER openssl x509 -in cert.crt -outform der -out cert.der


DER轉為PEM openssl x509 -in cert.crt -inform der -outform pem -out cert.pem


(提示:要轉換KEY文件也類似,只不過把x509換成rsa,要轉CSR的話,把x509換成req...)


二、相關的文件擴展名

這是比較誤導人的地方,雖然我們已經知道有PEM和DER這兩種編碼格式,但文件擴展名並不一定就叫"PEM"或者"DER",常見的擴展名除了PEM和DER還有以下這些,它們除了編碼格式可能不同之外,內容也有差別,但大多數都能相互轉換編碼格式.


CRT - CRT應該是certificate的三個字母,其實還是證書的意思,常見於*NIX系統,有可能是PEM編碼,也有可能是DER編碼,大多數應該是PEM編碼,相信你已經知道怎麼辨別.


CER - 還是certificate,還是證書,常見於Windows系統,同樣的,可能是PEM編碼,也可能是DER編碼,大多數應該是DER編碼.證書中沒有私鑰,DER 編碼二進制格式的證書文件


KEY - 通常用來存放一個公鑰或者私鑰,並非X.509證書,編碼同樣的,可能是PEM,也可能是DER.

查看KEY的辦法:openssl rsa -in mykey.key -text -noout

如果是DER格式的話,同理應該這樣了:openssl rsa -in mykey.key -text -noout -inform der


CSR - Certificate Signing Request,即證書籤名請求,這個並不是證書,而是向權威證書頒發機構獲得簽名證書的申請,其核心內容是一個公鑰(當然還附帶了一些別的信息),在生成這個申請的時候,同時也會生成一個私鑰,私鑰要自己保管好.做過iOS APP的朋友都應該知道是怎麼向蘋果申請開發者證書的吧.

查看的辦法:openssl req -noout -text -in my.csr (如果是DER格式的話照舊加上-inform der,這裡不寫了)


PFX/P12 - predecessor of PKCS#12,包含公鑰和私鑰的二進制格式證書


       對nginx服務器來說,一般CRT和KEY是分開存放在不同文件中的,但Windows的IIS則將它們存在一個PFX文件中,(因此這個文件包含了證書及私鑰)這樣會不會不安全?應該不會,PFX通常會有一個"提取密碼",你想把裡面的東西讀取出來的話,它就要求你提供提取密碼,PFX使用的時DER編碼,如何把PFX轉換為PEM編碼?

openssl pkcs12 -in for-iis.pfx -out for-iis.pem -nodes

這個時候會提示你輸入提取代碼. for-iis.pem就是可讀的文本.

生成pfx的命令類似這樣:openssl pkcs12 -export -in certificate.crt -inkey privateKey.key -out certificate.pfx


其中CACert.crt是CA(權威證書頒發機構)的根證書,有的話也通過-certfile參數一起帶進去.這麼看來,PFX其實是個證書密鑰庫.


p7b - 以樹狀展示證書鏈(certificate chain),同時也支持單個證書,不含私鑰。


JKS - 即Java Key Storage,這是Java的專利,跟OpenSSL關係不大,利用Java的一個叫"keytool"的工具,可以將PFX轉為JKS,當然了,keytool也能直接生成JKS,不過在此就不多表了.


備註實例:

1、從pfx導出crt和key:

操作命令:

openssl pkcs12 -in example.cn.ssl.pfx -nocerts -nodes -out example.key

openssl pkcs12 -in example.cn.ssl.pfx -clcerts -nokeys -out example.crt


2、將crt和key合併出pfx:

操作命令:

openssl pkcs12 -export -in certificate.crt -inkey privateKey.key -out certificate.pfx


Chrome 信任憑證的條件

  • 網址的 domain 要在CN
  • 要有 Subject Alternative Name field (Chrome 58 後)
  • DNS 要包含 CN
  • 雜湊 SHA256


函數的使用:

RSA加密的public key格式有多種,使用openssl庫加載rsa的公鑰時,使用的函數也不同,常見的有兩種:

密鑰開頭為"-----BEGIN RSA PUBLIC KEY-----",是RSA的PKCS#1格式,使用PEM_read_bio_RSAPublicKey()函數。

密鑰開頭為"-----BEGIN PUBLIC KEY-----",是RSA的PKCS#8格式,使用PEM_read_bio_RSA_PUBKEY()函數。

private key以此類推。


string Base64Encode_std(const string &encodeStr)
{
//ignore
}
string rsaEncode(const unsigned char *in, int len, const char *pubKey)
{
BIO *bio = NULL;
RSA *rsa = NULL;
char szOut[512] = {0};
string pkcs1_header = "-----BEGIN RSA PUBLIC KEY-----";
string pkcs8_header = "-----BEGIN PUNLIC KEY-----";
bio = BIO_bew(BIO_s_mem());
if (NULL == bio)
return "";
BIO_puts(bio, pubKey);
if (0 == strncmp(pubKey, pkcs8_header.c_str(), pkcs8.size()))
{
rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);
}
else if (0 == strncmp(pubKey, pkcs1_header.c_str(), pkcs1.size()))
{
rsa = PEM_read_bio_RSAPublicKey(bio, NULL, NULL, NULL);
}
if (NULL == rsa)
return "";
int ret = RSA_public_encrypt(len, in, (unsigned char *)szOut, rsa, RSA_PKCS1_PADDING);
if (ret < 0)
return "";
string encrypt_data = string(szOut, ret);
string resultStr = Base64Encode_std(encrypt_data);
if (bio)
BIO_free(bio);
if (rsa)
RSA_free(rsa);
return resultStr;
}

Reference:

使用 OpenSSL 產生憑證

OpenSSL.org

[Security] SSL — HTTPS 背後的功臣

der pem cer crt key pfx等概念及區別

[SSL 基礎]私有金鑰、CSR 、CRT 與 中繼憑證

如何使用 OpenSSL 建立開發測試用途的自簽憑證 (Self-Signed Certificate)


沒有留言:

張貼留言