動態

詳情 返回 返回

ssl證書,以 Nginx 為例 - 動態 詳情

1 證書概述

1.1 常見證書格式

  • 1)SSL 數字證書:

    • 在 HTTPS(HTTP over SSL)請求的 SSL 握手階段,服務端以數字證書的方式將 RSA 公鑰傳給客户端,以保證公鑰在傳輸過程中不被篡改。隨後在通信過程中,該公鑰將用於加密一個密鑰,這個密鑰則會對通信數據進行對稱加密。
    • SSL 數字證書的主要目的是用於傳遞服務端公鑰,以及驗證服務器信息。
  • 2)X.509 數字證書標準,定義證書文件的結構和內容,詳情參考 RFC5280。X.509 標準的證書文件具有不同的編碼格式,一般有 PEM 和 DER 兩種格式
  • 3)<font color=red>PEM:Privacy Enhanced Mail</font>,以 “-----BEGIN XXX-----” 開頭,“-----END XXX-----” 結尾,內容為 Base64 編碼的數據。

    • (1)查看 PEM 編碼的證書內容:

      openssl x509 -in xxx.pem -text -noout
    • (2)可以用來編碼存儲公鑰(RSA PUBLIC KEY)、私鑰(RSA PRIVATE KEY)、證書籤名請求(CERTIFICATE REQUEST)等數據
    • (3)Apache 和 Nginx 多使用這種編碼格式
  • 4)<font color=red>DER:Distinguished Encoding Rules</font>,文件內為二進制編碼。

    • (1)查看 DER 編碼的證書內容:

      openssl x509 -in xxx.der -inform der -text -noout
    • (2)Java 和 Windows 服務器應用偏向於使用這種編碼格式
  • 5)PEM 和 DER 之間的互轉:

    # PEM 轉 DER
    openssl x509 -in xxx.pem -outform der -out xxx.der
    # DER 轉 PEM
    openssl x509 -in xxx.der -inform der -outform pem -out xxx.pem
    
    # 要轉換 KEY 文件也類似,只不過把 x509 換成 rsa ,要轉 CSR 的話,把 x509 換成 req

1.2 證書的幾種擴展名

  • 1)常見的證書編碼格式雖然有 PEM 和 DER 格式,但文件擴展名除了 .pem 和 .der 這兩種外,還有 .crt、.cer、.key、.csr、.p12 等。
  • 2)<font color=blue>.crt</font>:常用於 UNIX 系統證書的後綴,可能採用 PEM 或 DER 編碼,多數為 PEM 編碼。
  • 3)<font color=blue>.cer</font>:常用於 Windows 系統證書的後綴,可能採用 PEM 或 DER 編碼,多數為 DER 編碼。
  • 4)<font color=blue>.key</font>:通常用來存放公鑰或私鑰,可能是 PEM 或 DER 編碼。
  • 5)<font color=blue>.csr</font>:證書籤名請求文件,用於服務器向證書分發機構申請證書。核心內容是公鑰,生成該申請文件時,同步也會生成私鑰,要自己保管好。
  • 6)<font color=blue>.pfx/.p12</font>:Predecessor of PKCS#12。UNIX 下,一般 CRT 和 KEY 分開存放到不同文件中。Windows 下則將它們存放在一個 PFX 文件(包含證書及私鑰)中,且通常附帶一個 “提取密碼”。

    # 將 PFX(DER 編碼) 轉換為 PEM 編碼
    openssl pkcs12 -in for-iis.pfx -out for-iis.pem -nodes
  • 7).crl:證書吊銷列表文件,用於記錄已被吊銷的證書。
  • 8).jks:Java Key Store,使用 keytool 可以生成,也可以將 PFX 轉換為 JKS。

1.3 關於 PKCS#12 格式

  • 1)證書一般和密鑰對一起保存,PKCS#12 格式可以將證書和密鑰對打包成一個文件,並對文件進行加密保存。
  • 2)PKCS#12 是公開密鑰加密學的一種格式,是微軟發佈的一種格式,後綴一般是 .pkcs12、.pfx、.p12。
  • 3)可以通過 OpenSSL pkcs12 子命令將密鑰對(privkey.pem)、服務器實體證書(cert.pem)、中間證書(chain.pem) 轉換成一個文件(會使用口令保護):

    # 中間證書如果不存在可以不指定
    openssl pkcs12          \
    -export -out cert.pfx   \
    -inkey privkey.pem -in cert.pem -certfile chain.pem
  • 4)需要使用證書時,可以從 cert.pfx 導出密鑰對和證書(需要輸入口令):

    # 導出密鑰對
    openssl pkcs12 -in cert.pfx -nodes -nocerts -out new_privkey.pem
    # 導出服務器實體證書
    openssl pkcs12 -in cert.pfx -nodes -clcerts -out new_cert.pem
    # 導出中間證書
    openssl pkcs12 -in cert.pfx -nodes -cacerts -out new_chain.pem

2 Nginx 下證書配置

2.1 證書的工作原理

2.1.1 單向認證

  • 1)單向認證(圖源自網絡):
  • 2)服務器和 CA 機構各有一套公私鑰(實際應用還有中間證書),通信前:

    • (1)服務器將自己的公鑰以及國家、省、市、公司、域名、郵箱 等信息發給 CA 機構請求籤名。
    • (2)CA 機構使用自己的私鑰對服務器的這些信息進行簽名,並生成證書返回給服務器。
  • 3)所謂驗證證書合法性,即客户端使用內置在 PC 或瀏覽器的 CA 機構公鑰,對證書的簽名進行驗證(私鑰加密,公鑰解密),簽名一致則表示服務器證書可信,進而表明證書內的服務器公鑰可信。

2.1.2 雙向認證

  • 1)雙向認證(圖源自網絡):
  • 2)可以發現,服務端需要使用根證書的公鑰解密客户端證書,從而拿到客户端公鑰。即 CA 機構的根證書需要分別對服務端、客户端的證書加密。

2.2 CA 機構簽發

2.2.1 免費 SSL 證書申請

  • 1)由於免費的 CA 機構不會對 IP 地址簽發證書,所以我們要整個域名,直接去微信搜索 “1元域名”(1 年)。

    • (1)在騰訊雲買到了 luyao.email 域名(可能需要一個模板去審核,耗時 1 小時)
    • (2)在騰訊雲的 ssl 免費證書申請頁面,沒有找到根據 csr(證書籤名請求文件,用於服務器向證書分發機構申請證書) 申請證書的地方,所以選擇阿里雲來申請免費證書

  • 2)生成服務器私鑰與證書籤名請求文件 csr:

    # 生成服務器私鑰
    openssl genrsa -out server_private.key 2048
    
    # 生成服務器的證書籤名請求文件 server.csr,用於服務器向證書分發機構申請證書。
    MSYS_NO_PATHCONV=1      \
    openssl req -new -key server_private.key -out server.csr \
    -subj "/C=CN/ST=Henan/L=Henan/O=luyao/OU=luyao/CN=luyao.email/emailAddress=luyaocode@outlook.com"
    
    • 這裏的 “MSYS_NO_PATHCONV=1” 用來解決使用 git bash 中 openssl 執行上述命令時,出現的 “/ 默認被認作為 git 的安裝目錄” 問題
  • 3)把上述生成的 server.csr 文件通過 “CSR管理” 上傳到阿里雲(同時上傳的還有 server_private.key 私鑰)
  • 4)在 “免費證書” 中申請證書,“選擇已有的 CSR” 為我們上傳的 csr 文件:
    image.png
  • 5)在證書申請記錄的 “驗證” 中按照要求配置域名的 DNS 解析記錄(申請成功刪除即可),等待 CA 機構審核即可(大概幾分鐘可接收到簽發成功短信)。
  • 6)下載 nginx 服務器證書,其中包括 luyao.email.key 和 luyao.email.pem。配置到 nginx:

    server {
        listen       443 ssl;
        server_name  luyao.email;
    
        ssl_certificate         ../sslKey/luyao.email.pem;
        ssl_certificate_key     ../sslKey/luyao.email.key;
    
        ssl_session_cache       shared:SSL:1m;
        ssl_session_timeout     5m;
    
        ssl_ciphers             ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
        ssl_protocols           TLSv1.1 TLSv1.2 TLSv1.3;
    
        ssl_prefer_server_ciphers  on;
    
        location / {
            root   html;
            index  index.html index.htm;
        }
    }
    
    # 自動切換 HTTP 到 HTTPS
    server {
        listen       80;
        server_name  luyao.email;
    
        #charset koi8-r;
    
        #access_log  logs/host.access.log  main;
    
        # redirect HTTP to HTTPS by rewrite
        rewrite ^(.*)$ https://$host$1;
        location / {
            root   html;
            index  index.html index.htm;
        }

2.2.2 雙向認證

  • 1)沒有找到免費可用的證書。

2.3 自簽證書

2.3.1 單向認證

  • 1)CA 機構:

    # 生成 CA 機構私鑰
    openssl genrsa -out ca_private.key 2048
    
    # 使用 CA 機構的私鑰生成證書,用來簽發服務器證書(“/ ”默認被認作為 git 的安裝目錄,MSYS_NO_PATHCONV 用來解決該問題)
    MSYS_NO_PATHCONV=1  \
    openssl req -new -x509 -key ca_private.key  -out ca.crt -days 365      \
    -subj "/C=CN/ST=Henan/L=Henan/O=ca/OU=ca/CN=www.ca.com/emailAddress=ca@ca.com"
    
    • 這裏的 ca_private.key 是我們自身作為 CA 機構為所有的服務器簽發證書所用的私鑰。而生成的 ca.crt 則用於給服務器請求證書籤名,即根證書 root.crt 。
  • 2)服務器:

    # 生成服務器私鑰
    openssl genrsa -out server_private.key 2048
    
    # 生成服務器的證書籤名請求文件 server.csr,用於服務器向證書分發機構申請證書。
    MSYS_NO_PATHCONV=1      \
    openssl req -new -key server_private.key -out server.csr \
    -subj "/C=CN/ST=Henan/L=Henan/O=server/OU=server/CN=server.com/emailAddress=server@server.com"
    
  • 3)將服務器的證書籤名請求文件 server.csr 發送給 CA 機構,由其對該證書進行簽名:

    # 被 CA 機構簽名後的證書文件 server.crt
    openssl x509 -req -days 365 -CA ca.crt -CAkey ca_private.key  -CAcreateserial \
    -in server.csr -out server.crt
    
  • 4)配置到 Nginx:

    server {
        listen       443 ssl;
        server_name  localhost;
        
        ssl_certificate         ../sslKey/server.crt;
        ssl_certificate_key     ../sslKey/server_private.key;
        
        ......
    }

2.3.2 雙向認證

  • 1)雙向認證

    # (1)CA 機構
    # CA 私鑰
    openssl genrsa -out ca_private.key 2048
    # CA 根證書
    MSYS_NO_PATHCONV=1          \
      openssl req -new -x509  \
      -key ca_private.key     \
      -out ca_root.crt        \
      -days 365               \
      -subj /C=CN/ST=Henan/L=Henan/O=ca/OU=ca/CN=ca.com/emailAddress=ca@ca.com
    
    
    # (2)服務器
    # 服務器私鑰
    openssl genrsa -out server_private.key 2048
    # 服務器請求證書
    MSYS_NO_PATHCONV=1      \
      openssl req -new    \
      -key server_private.key     \
      -out server.csr     \
      -subj /C=CN/ST=Henan/L=Henan/O=server/OU=server/CN=luyao.email/emailAddress=server@server.com
    # CA 機構根據服務器請求證書生成服務器證書
    openssl x509 -req   \
      -days 365           \
      -CA ca_root.crt     \
      -CAkey ca_private.key   \
      -CAcreateserial     \
      -in server.csr      \
      -out server.crt
    
    # (3)客户端
    # 客户端 1 私鑰
    openssl genrsa -out client1_private.key 2048
    # 客户端 1 請求證書
    MSYS_NO_PATHCONV=1              \
      openssl req -new            \
      -key client1_private.key     \
      -out client1.csr             \
      -subj /C=CN/ST=Henan/L=Henan/O=client/OU=client/CN=luyao.email/emailAddress=client@client.com
    # CA 機構根據客户端請求證書生成客户端證書
    openssl x509 -req   \
      -days 365       \
      -CA ca_root.crt \
      -CAkey ca_private.key   \
      -CAcreateserial \
      -in client1.csr  \
      -out client1.crt
    
    # 客户端 2 私鑰
    openssl genrsa -out client2_private.key 2048
    # 客户端 2 請求證書
    MSYS_NO_PATHCONV=1  \
      openssl req -new    \
      -key client2_private.key     \
      -out client2.csr     \
      -subj /C=CN/ST=Henan/L=Henan/O=client/OU=client/CN=luyao.email/emailAddress=client@client.com
    # CA 機構根據客户端請求證書生成客户端證書
    openssl x509 -req   \
      -days 365       \
      -CA ca_root.crt \
      -CAkey ca_private.key   \
      -CAcreateserial \
      -in client2.csr  \
      -out client2.crt
  • 4)配置到 Nginx:

      server {
          listen       10443 ssl;
          server_name  localhost;
    
          ssl_certificate         ../sslKey/server.crt;
          ssl_certificate_key     ../sslKey/server_private.key;
          ssl_client_certificate  ../sslKey/ca_root.crt;
          ssl_verify_client       on;
    
          ssl_session_cache       shared:SSL:1m;
          ssl_session_timeout     5m;
    
          ssl_ciphers             ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
          ssl_prefer_server_ciphers  on;
    
          location / {
              root   html;
              index  index.html index.htm;
          }
      }
  • 5)測試:

    curl --cert client.crt --key client_private.key --cacert server.crt https://luyao.email:10443

附錄 1:Windows 憑據

1.1 查看 Windows 憑據

  • (1) 圖形化界面查看:

    • "Win + R" 後輸入 "control" 回車,“用户賬户” -> “憑據處理器” -> “管理 Windows 憑據”

  • (2) 命令查看:

    cmdkey /list

1.2 cmdkey 使用

  • (1) 先看一下使用説明

    PS C:\Windows\system32> cmdkey
    創建,顯示和刪除保存的用户名和密碼。
    此命令的語法為:
    CMDKEY [{/add | /generic}:targetname {/smartcard | /user:username {/pass{:password}}} | /delete{:targetname | /ras} | /list{:targetname}]
    
    示例:
      要列出可用的憑據:
         cmdkey /list
         cmdkey /list:targetname
      要創建域憑據:
         cmdkey /add:targetname /user:username /pass:password
         cmdkey /add:targetname /user:username /pass
         cmdkey /add:targetname /user:username
         cmdkey /add:targetname /smartcard
      要創建普通憑據:
         /add 開關可以由 /generic 替代,來創建普通憑據
      要刪除現有憑據:
         cmdkey /delete:targetname
      要刪除 RAS 憑據:
         cmdkey /delete /ras
  • (2) 整理:

    # 查看
    cmdkey /list
    cmdkey /list:targetname     # 這裏的 targetname 支持正則,如 git* 可以列出所有目標以 git 開頭的憑據
    
    # 刪除
    cmdkey /delete:git:http://xxx.com
    
    # 添加
    cmdkey /generic:git:http://xxx.com /user:licong /pass:Passw0rd
    

參考文章

  • https://www.cnblogs.com/guogangj/p/4118605.html
  • https://blog.csdn.net/u011001084/article/details/54708258
  • https://blog.csdn.net/as3luyuan123/article/details/13709923
  • https://help.aliyun.com/zh/api-gateway/user-guide/mutual-tls-...

Add a new 評論

Some HTML is okay.