你想要了解但是卻羞於發問的有關SSL的一切


Everything You Ever Wanted to Know About SSL (but Were Afraid to Ask)

Or perhaps more accurately, “practical things I’ve learned about SSL”. This post (and the companion Spring Boot application) will demonstrate using SSL certificates to validate and authenticate connections to secure endpoints over HTTPS for some common use cases (web servers, browser authentication, unit and integration testing). It shows how to configure Apache HTTP server for two-way SSL, unit testing SSL authentication with Apache’s HttpClient and HttpServer (Java), and integration testing a REST API within a Spring Boot application running on an embedded Tomcat container.

There are lots of ways for a client to authenticate itself against a server, including basic authentication, form-based authentication, and OAuth.

To prevent exposing user credentials over the wire, the client communicates with the server over HTTPS, and the server’s identify is confirmed by validating its SSL certificate. The server doesn’t necessarily care who the client is, just as long as they have the correct credentials.

An even higher level of security can be gained with using SSL certificates for both the client and the server.

  譯者信息

你想要了解但是卻羞於發問的有關SSL的一切

或者更准確的說,“我所知的關於的SSL的實事”。本文(以及Spring Boot應用指南)將告訴你在一些通用服務(web服務器、瀏覽器認證、單元和集成測試)的使用場景中,如何使用SSL證書來保證通過HTTPS與遠端的連接的安全性。其間介紹了如何配置Apache HTTP服務器的雙向SSL,使用Apache’sHttpClient和HttpServer進行單元測試時的SSL認證(java),以及使用運行在嵌入的Tomcat容器里的Spring Boot應用來進行REST API集成測試。

客戶端向服務器認證自己有很多種方式,包括basic認證,基於form的認證和OAuth。

為了防止用戶認證信息在網絡上泄露,客戶端與服務端的通信需要建立在HTTPS上,通過驗證服務端的SSL證書來確定其身份。服務端並不需要關心客戶端是誰,只需要它們有正確的身份。

通過同時在服務端和客戶端啟用SSL證書來獲得更高的安全級別。

Two-way SSL authentication (also known as “mutual authentication”, and “TLS/SSL with client certificates”) refers to two parties authenticating each other through verifying provided digital certificates, so that both parties are assured of the other’s identity.

Terminology

TLS vs SSL

TLS is the successor to SSL. It is a protocol that ensures privacy between communicating applications. Unless otherwise stated, in this document consider TLS and SSL as interchangable.

Certificate (cert)

The public half of a public/private key pair with some additional metadata about who issued it etc. It may be freely given to anyone.

Private Key

A private key can verify that its corresponding certificate/public key was used to encrypt data. It is never given out publicly.

Certificate Authority (CA)

A company that issues digital certificates. For SSL/TLS certificates, there are a small number of providers (e.g. Symantec/Versign/Thawte, Comodo, GoDaddy) whose certificates are included by most browsers and Operating Systems. They serve the purpose of a “trusted third party”.

Certificate Signing Request (CSR)

A file generated with a private key. A CSR can be sent to a CA to request to be signed. The CA uses its private key to digitally sign the CSR and create a signed cert. Browsers can then use the CA’s cert to validate the new cert has been approved by the CA.

X.509

A specification governing the format and usage of certificates.

譯者信息

雙向 SSL 認證(也被稱為“相互認證”,或“使用客戶端證書的 TLS/SSL”)是指雙方通過校驗彼此提供的數字證書來進行認證,以便雙方都可以確認對方的身份。

        術語

TLS 與 SSL

TLS 的前身是 SSL。其是一個用於在應用程序之間進行通信時保障隱私的協議。除非另有說明,本文中認為 TLS 與 SSL 是等價的。

證書(cert)

包含了提供者信息等一些額外元數據的公鑰/私鑰對的公鑰部分。它可以被自由的提供給任何人。

私鑰

一個私鑰可以驗證與其對應的用來對數據進行加密的證書和公鑰。其決不公開提供。

證書頒發機構(CA)

一個頒發數字證書的公司。對於 SSL/TLS 證書,也有少數供應商(例如 Symantec/Versign/Thawte、Comodo、GoDaddy)的證書囊括了大多數瀏覽器和操作系統。它們的目的是成為一個“可信的第三方”。

證書簽名請求(CSR)

用私鑰生成的一個文件。一個 CSR 可以向一個 CA 發送簽名請求。CA 則使用其私鑰對 CSR 進行數字簽名,並創建一個已簽名的證書。然后瀏覽器可以使用 CA 提供的證書來驗證新的證書是否已被 CA 批准。

X.509

用於描述證書的格式和用法的一個規范。

Authentication with SSL

SSL is the standard security technology for establishing an encrypted link between a web server and a browser. Normally when a browser (the client) establishes an SSL connection to a secure web site, only the server certificate is checked. The browser either relies on itself or the operating system providing a list of certs that have been designated as root certificates and to be trusted as CAs.

One-way SSL authentication (server -> client)

Client and server use 9 handshake messages to establish the encrypted channel prior to message exchanging:

  1. Client sends ClientHello message proposing SSL options.

  2. Server responds with ServerHello message selecting the SSL options.

  3. Server sends Certificate message, which contains the server’s certificate.

  4. Server concludes its part of the negotiation with ServerHelloDone message.

  5. Client sends session key information (encrypted with server’s public key) in ClientKeyExchange message.

  6. Client sends ChangeCipherSpec message to activate the negotiated options for all future messages it will send.

  7. Client sends Finished message to let the server check the newly activated options.

  8. Server sends ChangeCipherSpec message to activate the negotiated options for all future messages it will send.

  9. Server sends Finished message to let the client check the newly activated options.

Two-way SSL authentication (server <-> client)

Client and server use 12 handshake messages to establish the encrypted channel prior to message exchanging:

  1. Client sends ClientHello message proposing SSL options.

  2. Server responds with ServerHello message selecting the SSL options.

  3. Server sends Certificate message, which contains the server’s certificate.

  4. Server requests client’s certificate in CertificateRequest message, so that the connection can be mutually authenticated.

  5. Server concludes its part of the negotiation with ServerHelloDone message.

  6. Client responds with Certificate message, which contains the client’s certificate.

  7. Client sends session key information (encrypted with server’s public key) in ClientKeyExchange message.

  8. Client sends a CertificateVerify message to let the server know it owns the sent certificate.

  9. Client sends ChangeCipherSpec message to activate the negotiated options for all future messages it will send.

  10. Client sends Finished message to let the server check the newly activated options.

  11. Server sends ChangeCipherSpec message to activate the negotiated options for all future messages it will send.

  12. Server sends Finished message to let the client check the newly activated options.

譯者信息 SSL認證

SSL實際上就是在一個web服務器與瀏覽器之間建立加密鏈接的標准安全技術。一般來說,一個瀏覽器(客戶端)建立一個SSL連接到一個安全的web站點,它只檢查該服務器證書。該瀏覽器一方面依靠其本身,或者提供已經被指定為根證書的列表證書以及受信任的CAs的操作系統。

單向SSL認證(服務器->客戶端)

客戶端與服務器使用9個握手消息,以及通過優先建立加密通道來進行消息交換。

  1.客戶端發送ClientHello消息來提議SSL選項。

  2.服務器通過響應ServerHello消息來選擇SSL選項。

  3.服務器發送Certificate消息,其中包括該服務器證書。

  4.客戶端通過ServerHelloDone消息,來判斷其部分談判.

  5.客戶端在其ClientKeyExchange消息之中發送會話密匙信息(加密服務器公匙)

  6.客戶端通過發送ChangeCipherSpec消息來激活所有發送的未來消息的談判選項。

  7。客戶端通過發送Finished消息,讓服務器檢查新激活的選項。

  8.客戶端通過發送ChangeCipherSpec消息來激活所有發送未來消息的談判選項。

  9.服務器發送Finished消息,讓客戶端檢查新激活的選項。

雙向SSL認證(服務器<->客戶端)

 客戶端與服務器使用12個握手消息,以及優先建立加密通道來進行消息交換:

 

  1.客戶端發送ClientHello消息來提議SSL選項。

  2.服務器通過響應ServerHello消息來選擇SSL選項。

  3.服務器發送Certificate消息,其中包括該服務器證書。

  4.客戶端通過ServerHelloDone消息,來判斷其部分談判.

  5.客戶端在其ClientKeyExchange消息之中發送會話密匙信息(加密服務器公匙)

  6.客戶端通過發送ChangeCipherSpec消息來激活所有發送的未來消息的談判選項。

  7。客戶端通過發送Finished消息,讓服務器檢查新激活的選項。

  8.客戶端通過發送ChangeCipherSpec消息來激活所有發送未來消息的談判選項。

  9.服務器發送Finished消息,讓客戶端檢查新激活的選項。

File Formats for Certs and Keys

Privacy-Enhanced Mail (PEM)

PEM is just Distinguished Encoding Rules (DER) that has been Base64 encoded. Used for keys and certificates.

PKCS12

PKCS12 is a password-protected format that can contain multiple certificates and keys.

Java KeyStore (JKS)

Java version of PKCS12 and also password protected. Entries in a JKS file must have an “alias” that is unique. If an alias is not specified, “mykey” is used by default. It’s like a database for certs and keys.

Tools

OpenSSL

An open source toolkit implementing the SSL (v2/v3) and TLS (v1) protocols, as well as a full-strength general purpose cryptography library.

Keytool

Manages a Java KeyStore of cryptographic keys, X.509 certificate chains, and trusted certificates. Ships with the JDK.

Create a local SSL server with Apache

Modified from: https://gist.github.com/jonathantneal/774e4b0b3d4d739cbc53

Configuring Apache

Switch to root:

1
sudo su

Within Terminal, start Apache:

1
apachectl start

In a web browser, visit http://localhost. You should see a message stating that It works!

Configuring Apache for HTTP: Setting up a port 80 Virtual Host

Within Terminal, edit the Apache Configuration:

1
vi /etc/apache2/httpd.conf

Enable SSL by uncommenting line 143:

1
LoadModule ssl_module libexec/apache2/mod_ssl.so

Within your editor, replace line 212 to suppress messages about the server’s fully qualified domain name:

1
ServerName localhost

Next, uncomment line 160 and line 499 to enable Virtual Hosts.

123
LoadModule vhost_alias_module libexec/apache2/mod_vhost_alias.soInclude /private/etc/apache2/extra/httpd-vhosts.conf

Uncomment line 518 to include httpd-ssl.conf (to listen on port 443):

1
Include /private/etc/apache2/extra/httpd-ssl.conf

Optionally, uncomment line 169 to enable PHP.

1
LoadModule php5_module libexec/apache2/libphp5.so

Within Terminal, edit the Virtual Hosts

1
vi /etc/apache2/extra/httpd-vhosts.conf

Within your editor, replace the entire contents of this file with the following, replacing rhowlett with your user name.

123456789101112
<VirtualHost *:80>    ServerName localhost    DocumentRoot “/Users/rhowlett/Sites/localhost”    <Directory “/Users/rhowlett/Sites/localhost”>        Options Indexes FollowSymLinks        AllowOverride All        Order allow,deny        Allow from all        Require all granted    </Directory></VirtualHost>

Within Terminal, restart Apache:

1
apachectl restart
譯者信息

文件格式證書與密匙

私人安全增強性郵件(PEM)

PEM 就是使用 Base64 編碼的區分編碼規則(DER)。通常用於密匙與認證。

PKCS12

PKCS12 就是一個能含有多個證書與密匙的密碼保護格式。

Java KeyStore (JKS)

PKCS12 的 Java 版本以及密碼保護。一個 JKS 文件的條目必須有一個“alias” ,即獨一無二。如果一個 alias 不是特定的,“mykey” 默認會被使用。它就像一個密匙與證書數據庫。

工具

OpenSSL

一個實現 SSL (v2/v3) 與 TLS (v1)協議的開源工具包,以及一個通用地完全版加密庫。

密匙工具

管理一個加密鈅匙, X.509 證書鏈,以及受信任證書的 Java KeyStore。附帶 JDK 的 ships

使用Apache創建本地SSL服務器

通過https://gist.github.com/jonathantneal/774e4b0b3d4d739cbc53修改

配置 Apache

切換到 root:

sudo su

在終端,啟動 Apache:

apachectl start

在 web 瀏覽器中,訪問 http://localhost。你應該看到它運行的工作狀態。

為 http 配置 Apache:設置一個 80 端口的虛擬主機

在終端,編輯 Apache 配置:

vi /etc/apache2/httpd.conf

通過取消第 143 行,啟用 SSL:

LoadModule ssl_module libexec/apache2/mod_ssl.so

在你的編輯器里,通過替換第 212 行來壓制服務器被完全地限定域名的消息:

ServerName localhost

下一步,取消批注 160 行與499 行,支持虛擬主機。

LoadModule vhost_alias_module libexec/apache2/mod_vhost_alias.soInclude /private/etc/apache2/extra/httpd-vhosts.conf


取消批注第 518 行,包括 httpd-ssl.conf(監聽 443 端口)

Include /private/etc/apache2/extra/httpd-ssl.conf

在終端,重啟 Apache:

apachectl restart

Configuring Apache: Creating a Site

Within Terminal, Create a Sites directory, which will be the parent directory of many individual Site subdirectories:

1
mkdir ~/Sites

Next, create a localhost subdirectory within Sites, which will be our first site:

1
mkdir ~/Sites/localhost

Finally, create an HTML document within localhost:

1
echo “<h1>localhost works</h1>” > ~/Sites/localhost/index.html

Now, in a web browser, visit http://localhost. You should see a message stating that localhost works.

Configuring SSL

Note: I used snaplogic for all passwords below

Modified from: http://www.stefanocapitanio.com/configuring-two-way-authentication-ssl-with-apache/

Within Terminal, create a SSL directory:

1234
mkdir /etc/apache2/sslcd /etc/apache2/sslmkdir certs private

Create the CA cert

Create a database to keep track of each certificate signed:

12
echo ‘100001’ > serialtouch certindex.txt

Make a custom config file for openssl to use:

1
vi openssl.cnf
#
# OpenSSL configuration file.
#

# Establish working directory.

dir = .

[ ca ]
default_ca = CA_default

[ CA_default ]
serial = $dir/serial
database = $dir/certindex.txt
new_certs_dir = $dir/certs
certificate = $dir/cacert.pem
private_key = $dir/private/cakey.pem
default_days = 365
default_md = sha512
preserve = no
email_in_dn = no
nameopt = default_ca
certopt = default_ca
policy = policy_match

[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ req ]
default_bits = 2048 # Size of keys
default_keyfile = key.pem # name of generated keys
default_md = sha512 # message digest algorithm
string_mask = nombstr # permitted characters
distinguished_name = req_distinguished_name
req_extensions = v3_req

[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US
countryName_min = 2
countryName_max = 2

stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Colorado

localityName = Locality Name (eg, city)
localityName_default = Boulder

0.organizationName = Organization Name (eg, company)
0.organizationName_default = SnapLogic

# we can do this but it is not needed normally :-)
#1.organizationName = Second Organization Name (eg, company)
#1.organizationName_default = World Wide Web Pty Ltd

organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = SnapTeam

commonName = Common Name (eg, YOUR name)
commonName_max = 64
commonName_default = localhost 

emailAddress = Email Address
emailAddress_max = 64

# SET-ex3 = SET extension number 3

[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20

unstructuredName = An optional company name

[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US 
countryName_min = 2
countryName_max = 2

stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Colorado

localityName = Locality Name (eg, city)

0.organizationName = Organization Name (eg, company)
0.organizationName_default = SnapLogic

# we can do this but it is not needed normally :-)
#1.organizationName = Second Organization Name (eg, company)
#1.organizationName_default = World Wide Web Pty Ltd

organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = SnapTeam

commonName = Common Name (eg, YOUR name)
commonName_max = 64
commonName_default = localhost

emailAddress = Email Address
emailAddress_max = 64

# SET-ex3 = SET extension number 3

[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20

unstructuredName = An optional company name
[ v3_ca ]
basicConstraints = CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always

[ v3_req ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash

Note that I’ve set default_md to sha512 so that modern browsers won’t complain about Weak Signature Algorithms.

譯者信息

配置Apache: 建立一個站點

終端, 建立Sites文件夾, 它將是很多獨立Site子文件夾的父文件夾:

1
mkdir ~/Sites

接下來建立一個在Sites文件夾下建立localhost子文件夾,它將是我們的第一個站點:

1
mkdir ~/Sites/localhost

最后,在localhost內建立HTML文檔:

1
echo “<h1>localhost works</h1>” > ~/Sites/localhost/index.html

現在,在瀏覽器訪問http://localhost,你會看到一個消息,代表localhost已經起作用。

配置SSL

提示: 下面的密碼我都用dsnaplogic

從這個鏈接修改而來: http://www.stefanocapitanio.com/configuring-two-way-authentication-ssl-with-apache/

終端內,建立SSL文件夾:

1234
mkdir /etc/apache2/sslcd /etc/apache2/sslmkdir certs private

建立CA證書

建立一個數據庫來跟蹤所有簽了名的證書:

12
echo ‘100001’ > serialtouch certindex.txt

定義一個openssl的config文件:

1
vi openssl.cnf

 

#
# OpenSSL configuration file.
#

# Establish working directory.

dir = .

[ ca ]
default_ca = CA_default

[ CA_default ]
serial = $dir/serial
database = $dir/certindex.txt
new_certs_dir = $dir/certs
certificate = $dir/cacert.pem
private_key = $dir/private/cakey.pem
default_days = 365
default_md = sha512
preserve = no
email_in_dn = no
nameopt = default_ca
certopt = default_ca
policy = policy_match

[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ req ]
default_bits = 2048 # Size of keys
default_keyfile = key.pem # name of generated keys
default_md = sha512 # message digest algorithm
string_mask = nombstr # permitted characters
distinguished_name = req_distinguished_name
req_extensions = v3_req

[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US
countryName_min = 2
countryName_max = 2

stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Colorado

localityName = Locality Name (eg, city)
localityName_default = Boulder

0.organizationName = Organization Name (eg, company)
0.organizationName_default = SnapLogic

# we can do this but it is not needed normally :-)
#1.organizationName = Second Organization Name (eg, company)
#1.organizationName_default = World Wide Web Pty Ltd

organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = SnapTeam

commonName = Common Name (eg, YOUR name)
commonName_max = 64
commonName_default = localhost 

emailAddress = Email Address
emailAddress_max = 64

# SET-ex3 = SET extension number 3

[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20

unstructuredName = An optional company name

[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US 
countryName_min = 2
countryName_max = 2

stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Colorado

localityName = Locality Name (eg, city)

0.organizationName = Organization Name (eg, company)
0.organizationName_default = SnapLogic

# we can do this but it is not needed normally :-)
#1.organizationName = Second Organization Name (eg, company)
#1.organizationName_default = World Wide Web Pty Ltd

organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = SnapTeam

commonName = Common Name (eg, YOUR name)
commonName_max = 64
commonName_default = localhost

emailAddress = Email Address
emailAddress_max = 64

# SET-ex3 = SET extension number 3

[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20

unstructuredName = An optional company name
[ v3_ca ]
basicConstraints = CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always

[ v3_req ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash注意,我還將default_md設置為sha512,這樣,現在的瀏覽器就不會報。

Create a CA by creating a root certificate. This will create the private key (private/cakey.pem) and the public key (cacert.pem, a.k.a. the certificate) of the CA. Use the default localhost for the common name:

| root@SL-MBP-RHOWLETT.local:/private/etc/apache2/ssl 
| => openssl req -new -x509 -extensions v3_ca -keyout private/cakey.pem -out cacert.pem -days 365 -config ./openssl.cnf
Generating a 2048 bit RSA private key
................................+++
.............................+++
writing new private key to 'private/cakey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
phrase is too short, needs to be at least 4 chars
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [Colorado]:
Locality Name (eg, city) [Milan]:Boulder
Organization Name (eg, company) [Organization default]:SnapLogic
Organizational Unit Name (eg, section) [SnapLogic]:SnapTeam 
Common Name (eg, YOUR name) [localhost]:
Email Address []:

Create the Server cert

Create a key and signing request for the server. This will create the CSR for the server (server-req.pem) and the server’s private key (private/server-key.pem). Use the default localhost for the common name:

| root@SL-MBP-RHOWLETT.local:/etc/apache2/ssl 
| => openssl req -new -nodes -out server-req.pem -keyout private/server-key.pem -days 365 -config openssl.cnf 
Generating a 2048 bit RSA private key
......+++
..................................+++
writing new private key to 'private/server-key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [Colorado]:
Locality Name (eg, city) [Boulder]:
Organization Name (eg, company) [SnapLogic]:
Organizational Unit Name (eg, section) [SnapTeam]:
Common Name (eg, YOUR name) [localhost]:
Email Address []:

Have the CA sign the server’s CSR. This will create the server’s public certificate (server-cert.pem):

| root@SL-MBP-RHOWLETT.local:/etc/apache2/ssl 
| => openssl ca -out server-cert.pem -days 365 -config openssl.cnf -infiles server-req.pem 
Using configuration from openssl.cnf
Enter pass phrase for ./private/cakey.pem:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'US'
stateOrProvinceName   :PRINTABLE:'Colorado'
localityName          :PRINTABLE:'Boulder'
organizationName      :PRINTABLE:'SnapLogic'
organizationalUnitName:PRINTABLE:'SnapTeam'
commonName            :PRINTABLE:'localhost'
Certificate is to be certified until Oct  4 16:30:23 2016 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

Create the Client cert

Each client will create a key and signing request. We will just create one for now. You must use a different common name than the server/CA - here I’m using client. This will create the client’s CSR (client-req.pem) and the client’s private key (private/client-key.pem):

| root@SL-MBP-RHOWLETT.local:/etc/apache2/ssl 
| => openssl req -new -nodes -out client-req.pem -keyout private/client-key.pem -days 365 -config openssl.cnf 
Generating a 2048 bit RSA private key
....................................................+++
...........+++
writing new private key to 'private/client-key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [Colorado]:
Locality Name (eg, city) [Boulder]:
Organization Name (eg, company) [SnapLogic]:
Organizational Unit Name (eg, section) [SnapTeam]:
Common Name (eg, YOUR name) [localhost]:client
Email Address []:

Have the CA sign the client’s CSR. This will create the client’s public certificate (client-cert.pem):

| root@SL-MBP-RHOWLETT.local:/etc/apache2/ssl 
| => openssl ca -out client-cert.pem -days 365 -config openssl.cnf -infiles client-req.pem 
Using configuration from openssl.cnf
Enter pass phrase for ./private/cakey.pem:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'US'
stateOrProvinceName   :PRINTABLE:'Colorado'
localityName          :PRINTABLE:'Boulder'
organizationName      :PRINTABLE:'SnapLogic'
organizationalUnitName:PRINTABLE:'SnapTeam'
commonName            :PRINTABLE:'client'
Certificate is to be certified until Oct  4 16:40:01 2016 GMT (365 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

Finally, create the PKCS12 file containing the client’s private key, the client’s public cert and the CA cert. This will create the (Mac-friendly) PKCS12 file (client-cert.p12):

| root@SL-MBP-RHOWLETT.local:/etc/apache2/ssl 
| => openssl pkcs12 -export -in client-cert.pem -inkey private/client-key.pem -certfile cacert.pem -name "Client" -out client-cert.p12 
Enter Export Password:
Verifying - Enter Export Password:

Configuring Apache for HTTPS and one-way SSL auth

As root:

vi /etc/apache2/extra/httpd-vhosts.conf

Add a Virtual Host for port 443 and enable SSL:

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot "/Users/rhowlett/Sites/localhost"

    <Directory "/Users/rhowlett/Sites/localhost">
        Options Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all
        Require all granted
    </Directory>
</VirtualHost>

<VirtualHost *:443>
    ServerName localhost
    DocumentRoot "/Users/rhowlett/Sites/localhost"

    SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
    SSLEngine on
    SSLCertificateFile /etc/apache2/ssl/server-cert.pem
    SSLCertificateKeyFile /etc/apache2/ssl/private/server-key.pem

    <Directory "/Users/rhowlett/Sites/localhost">
        Options Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all
        Require all granted
    </Directory>
</VirtualHost>

Restart Apache:

apachectl restart

(Mac) Install the CA cert into Keychain Access

譯者信息

通過建立Root證書方式建立CA證書,這同時也會建立CA的私鑰 (private/cakey.pem) 和公鑰 (cacert.pem)。使用默認的localhost作為Common Name:

| root@SL-MBP-RHOWLETT.local:/private/etc/apache2/ssl 
| => openssl req -new -x509 -extensions v3_ca -keyout private/cakey.pem -out cacert.pem -days 365 -config ./openssl.cnf
Generating a 2048 bit RSA private key
................................+++
.............................+++
writing new private key to 'private/cakey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
phrase is too short, needs to be at least 4 chars
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [Colorado]:
Locality Name (eg, city) [Milan]:Boulder
Organization Name (eg, company) [Organization default]:SnapLogic
Organizational Unit Name (eg, section) [SnapLogic]:SnapTeam 
Common Name (eg, YOUR name) [localhost]:
Email Address []:

建立服務器證書

為服務器建立密鑰和簽名請求,這將會為服務器建立CSR文件 (server-req.pem) 以及服務器的私鑰 (private/server-key.pem)。同樣使用默認的localhost作為Common Name:

| root@SL-MBP-RHOWLETT.local:/etc/apache2/ssl 
| => openssl req -new -nodes -out server-req.pem -keyout private/server-key.pem -days 365 -config openssl.cnf 
Generating a 2048 bit RSA private key
......+++
..................................+++
writing new private key to 'private/server-key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [Colorado]:
Locality Name (eg, city) [Boulder]:
Organization Name (eg, company) [SnapLogic]:
Organizational Unit Name (eg, section) [SnapTeam]:
Common Name (eg, YOUR name) [localhost]:
Email Address []:

獲得了CA簽名和服務器的CSR之后,下面會生成服務器的共有證書 (server-cert.pem):

| root@SL-MBP-RHOWLETT.local:/etc/apache2/ssl 
| => openssl ca -out server-cert.pem -days 365 -config openssl.cnf -infiles server-req.pem 
Using configuration from openssl.cnf
Enter pass phrase for ./private/cakey.pem:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'US'
stateOrProvinceName   :PRINTABLE:'Colorado'
localityName          :PRINTABLE:'Boulder'
organizationName      :PRINTABLE:'SnapLogic'
organizationalUnitName:PRINTABLE:'SnapTeam'
commonName            :PRINTABLE:'localhost'
Certificate is to be certified until Oct  4 16:30:23 2016 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

生成客戶端證書

每個客戶端都會生成一個密鑰和簽名請求,我們在這里只做一次。你必須使用與服務器不同的Common Name,這里我用client。 下面會生成客戶端的CSR (client-req.pem) 和其私鑰 (private/client-key.pem):

| root@SL-MBP-RHOWLETT.local:/etc/apache2/ssl 
| => openssl req -new -nodes -out client-req.pem -keyout private/client-key.pem -days 365 -config openssl.cnf 
Generating a 2048 bit RSA private key
....................................................+++
...........+++
writing new private key to 'private/client-key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [Colorado]:
Locality Name (eg, city) [Boulder]:
Organization Name (eg, company) [SnapLogic]:
Organizational Unit Name (eg, section) [SnapTeam]:
Common Name (eg, YOUR name) [localhost]:client
Email Address []:

有了CA簽名和客戶端的CSR,下面會生成客戶端的公有證書 (client-cert.pem):

| root@SL-MBP-RHOWLETT.local:/etc/apache2/ssl 
| => openssl ca -out client-cert.pem -days 365 -config openssl.cnf -infiles client-req.pem 
Using configuration from openssl.cnf
Enter pass phrase for ./private/cakey.pem:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'US'
stateOrProvinceName   :PRINTABLE:'Colorado'
localityName          :PRINTABLE:'Boulder'
organizationName      :PRINTABLE:'SnapLogic'
organizationalUnitName:PRINTABLE:'SnapTeam'
commonName            :PRINTABLE:'client'
Certificate is to be certified until Oct  4 16:40:01 2016 GMT (365 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

最后生成包含客戶端私鑰、共有證書和CA證書的的PKCS12文件。下面會生成 (以Mac為例) PKCS12文件 (client-cert.p12):

| root@SL-MBP-RHOWLETT.local:/etc/apache2/ssl 
| => openssl pkcs12 -export -in client-cert.pem -inkey private/client-key.pem -certfile cacert.pem -name "Client" -out client-cert.p12 
Enter Export Password:
Verifying - Enter Export Password:

配置Apache的HTTPS和單向SSL驗證

在root下:

vi /etc/apache2/extra/httpd-vhosts.conf

添加一個443端口的Virtual Host並且開啟SSL:

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot "/Users/rhowlett/Sites/localhost"

    <Directory "/Users/rhowlett/Sites/localhost">
        Options Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all
        Require all granted
    </Directory>
</VirtualHost>

<VirtualHost *:443>
    ServerName localhost
    DocumentRoot "/Users/rhowlett/Sites/localhost"

    SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
    SSLEngine on
    SSLCertificateFile /etc/apache2/ssl/server-cert.pem
    SSLCertificateKeyFile /etc/apache2/ssl/private/server-key.pem

    <Directory "/Users/rhowlett/Sites/localhost">
        Options Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all
        Require all granted
    </Directory>
</VirtualHost>

重啟Apache:

apachectl restart

 (在Mac下) 安裝CA證書到Keychain Access

Open /etc/apache2/ssl in Finder:

Open the CA cert (cacert.pem) by double-clicking it to install it to Keychain Access:

Mark it as trusted:

Open your browser to https://localhost and you should see a successful secure connection:

Configuring Apache for two-way SSL auth

As root:

vi /etc/apache2/extra/httpd-vhosts.conf

Add the SSLVerifyClient, SSLCertificateFile, and SSLCACertificateFile options:

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot "/Users/rhowlett/Sites/localhost"

    <Directory "/Users/rhowlett/Sites/localhost">
        Options Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all
        Require all granted
    </Directory>
</VirtualHost>

<VirtualHost *:443>
    ServerName localhost
    DocumentRoot "/Users/rhowlett/Sites/localhost"

    SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
    SSLEngine on
    SSLCertificateFile /etc/apache2/ssl/server-cert.pem
    SSLCertificateKeyFile /etc/apache2/ssl/private/server-key.pem

    SSLVerifyClient require
    SSLVerifyDepth 10
    SSLCACertificateFile /etc/apache2/ssl/cacert.pem

    <Directory "/Users/rhowlett/Sites/localhost">
        Options Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all
        Require all granted
    </Directory>
</VirtualHost>

Restart Apache:

apachectl restart

OpenSSL can now confirm that the two-way SSL handshake can be successfully completed:

| rhowlett@SL-MBP-RHOWLETT.local:~/Downloads 
| => openssl s_client -connect localhost:443 -tls1 -cert /etc/apache2/ssl/client-cert.pem -key /etc/apache2/ssl/private/client-key.pem
CONNECTED(00000003)
depth=1 /C=US/ST=Colorado/L=Boulder/O=SnapLogic/OU=SnapTeam/CN=localhost
verify error:num=19:self signed certificate in certificate chain
verify return:0
---
Certificate chain
 0 s:/C=US/ST=Colorado/O=SnapLogic/OU=SnapTeam/CN=localhost
   i:/C=US/ST=Colorado/L=Boulder/O=SnapLogic/OU=SnapTeam/CN=localhost
 1 s:/C=US/ST=Colorado/L=Boulder/O=SnapLogic/OU=SnapTeam/CN=localhost
   i:/C=US/ST=Colorado/L=Boulder/O=SnapLogic/OU=SnapTeam/CN=localhost
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDPjCCAiYCAxAAATANBgkqhkiG9w0BAQ0FADBtMQswCQYDVQQGEwJVUzERMA8G
A1UECBMIQ29sb3JhZG8xEDAOBgNVBAcTB0JvdWxkZXIxEjAQBgNVBAoTCVNuYXBM
b2dpYzERMA8GA1UECxMIU25hcFRlYW0xEjAQBgNVBAMTCWxvY2FsaG9zdDAeFw0x
NTEwMDYxOTE1MTNaFw0xNjEwMDUxOTE1MTNaMFsxCzAJBgNVBAYTAlVTMREwDwYD
VQQIEwhDb2xvcmFkbzESMBAGA1UEChMJU25hcExvZ2ljMREwDwYDVQQLEwhTbmFw
VGVhbTESMBAGA1UEAxMJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAyvia0x0Nd4tYyvoXEYtI3s/eLIQ3wFsOJIibNy70PLhp35gScQ69
MiIrVDYqIydVbInzyY5kuhttrUIrHCIiDwa5OqEiExJ+ollY9icnrMLrEXJqvv5C
/fduS5byC6StNg7xHQkYlYLUYMw8QQyCZFQVGXlxZeG6i086ffMYduFimkBAkNj5
/LkIwrOELpGnNcrOJxQEnLi8vmRI3oiCrgVc0ugrFBnoj3Tf6y3lx23fYgLbqf9c
bRCS6V3eppa/x9sezv9KQ+pDYly0bwKIcvJ9xLp7qPiO+smGGvS97Ec4NAif8y6v
pU92cPH32cv1p0AIDF0+GMOgVyAYZgSKQwIDAQABMA0GCSqGSIb3DQEBDQUAA4IB
AQBedsAvkB1yNLE2GCJWWQ19qEKOIBYCRQc2z29PgF/LAz5GVOIw/ZiN37C2vTob
jk1NnqfOx5aipQ5Pe5D2yfbarDl0kaqRn9MhBySi+oi3AgUZ5yL0x/nGF9O8jszJ
OM1FUC6qXKic5pR0qTrdXigONlKb0Au+l3z5dFMiqnNmDrNlI8kW1OXrwy/jvyPv
H1bHWAKYFTvHi2v7A0B96V1VvFBLbuQztckPQ3VpFDOwWhWLr2D90vxFd1Ea0SCi
3bysz4ax9XP0bmXJY+968nV31qQJMkk5/3rE5PWVZibsniccfdujgSQYl+yNA3sB
F5h6mCR6pAONZFo6+U3zARSb
-----END CERTIFICATE-----
subject=/C=US/ST=Colorado/O=SnapLogic/OU=SnapTeam/CN=localhost
issuer=/C=US/ST=Colorado/L=Boulder/O=SnapLogic/OU=SnapTeam/CN=localhost
---
Acceptable client certificate CA names
/C=US/ST=Colorado/L=Boulder/O=SnapLogic/OU=SnapTeam/CN=localhost
---
SSL handshake has read 4004 bytes and written 1539 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES256-SHA
    Session-ID: A1D9CE5273963BCF70503B499D7714ECE2B628CEE59CE554615743ACEEA8E281
    Session-ID-ctx: 
    Master-Key: 0920CEE1491E9A116B2DF959430890D449D49DA990A178C0AC980DD5AF359B7E1CDD4B2D8237C8F81BAE186BC06E7BB0
    Key-Arg   : None
    TLS session ticket:
    0000 - 5c 8f 01 d5 5d c1 62 d5-65 d7 8f 05 5f 47 d2 82   \...].b.e..._G..
    0010 - f0 fd 2c 88 be 58 25 6c-9e 9a 1e 78 6a b4 66 c4   ..,..X%l...xj.f.
    0020 - 0d 3d 31 04 97 a2 5f e7-6f 3c 9f c9 b1 44 6a ab   .=1..._.o<...Dj.
    0030 - 84 89 76 e4 63 9b 81 b7-c3 28 e0 95 c6 c3 f5 89   ..v.c....(......
    0040 - d5 f9 7f da df fb 12 f7-de 2a ec e8 c2 01 59 07   .........*....Y.
    0050 - 9e ad 91 56 91 34 88 73-66 d1 ea c1 72 dc 56 ee   ...V.4.sf...r.V.
    0060 - ee 61 fe 5e 38 f0 aa d6-3a 7d ad ef e6 be 2a 15   .a.^8...:}....*.
    0070 - dc cc 9f 04 5e e8 f9 2b-07 21 6b 0f da 9f 08 2e   ....^..+.!k.....
    0080 - 88 af 96 41 98 f3 ff 8a-01 66 1a 1d 61 47 1b e5   ...A.....f..aG..
    0090 - ec ab b7 af 79 aa 7d 25-ca e0 fa f4 2b 2e 9a dd   ....y.}%....+...
    00a0 - 95 0c 4b 35 d8 96 8b f0-1e 20 c1 c3 47 fc 65 ed   ..K5..... ..G.e.
    00b0 - 21 e4 50 59 1e 33 6a 5c-c6 27 f1 65 be 5b 0f 35   !.PY.3j\.'.e.[.5
    00c0 - 1d ba ac bf f5 9c d9 b7-32 87 11 ae b7 87 9b 52   ........2......R
    00d0 - bb 00 6b 66 af e2 94 45-e3 8f fb e0 b4 c6 d7 5a   ..kf...E.......Z
    00e0 - f8 1d 7a af e3 ee bb 6b-93 ff 46 af ed 86 bc f8   ..z....k..F.....
    00f0 - 6d e2 c9 60 eb 61 8e b9-7e bd 4d bb 1e 01 95 d2   m..`.a..~.M.....
    0100 - f5 d5 ee 82 10 4a 1d 23-9e 94 d7 0b 46 e4 d4 32   .....J.#....F..2
    0110 - 11 92 76 4a 94 9e a3 61-21 9b 4c 49 6c df 7b 18   ..vJ...a!.LIl.{.
    0120 - b7 49 66 bd 48 0d eb 9a-ad e9 32 c7 b9 6d 70 1a   .If.H.....2..mp.
    0130 - c7 a1 25 21 b4 f1 03 5b-80 83 e9 da 8d 56 f1 d9   ..%!...[.....V..
    0140 - 8b c5 32 b7 3a 67 5b 9c-51 84 a0 09 04 4f 48 60   ..2.:g[.Q....OH`
    0150 - 27 c0 fe 1c 45 7a 3b b2-22 8d ed 65 72 23 8a bf   '...Ez;."..er#..
    0160 - e3 09 eb 78 98 ec 08 06-9d 37 02 1a 4b ae cd 3a   ...x.....7..K..:
    0170 - 9c a4 bd 5d 47 5e d3 d7-7b 89 7b 97 78 a6 4c 10   ...]G^..{.{.x.L.
    0180 - bf 3e ed 1f f4 fe e5 97-90 ee 31 58 5f ff c6 c2   .>........1X_...
    0190 - 61 b7 df 0a f5 27 c6 a8-ac 61 a3 d0 1e 3a 6a 42   a....'...a...:jB
    01a0 - a9 18 b4 fb 4b 25 87 62-97 26 48 35 d0 16 d1 06   ....K%.b.&H5....
    01b0 - 9d 82 b5 e2 7b f2 24 c5-83 a1 4b fe 8d 38 ae 30   ....{.$...K..8.0
    01c0 - 8e eb e1 ac 8b 48 fa 27-b0 e1 ce b3 17 62 69 f0   .....H.'.....bi.
    01d0 - 30 17 ae 31 9d bf 77 64-66 5b 13 8e a2 63 2e 58   0..1..wdf[...c.X
    01e0 - 02 10 26 e1 3b 0d 55 fc-3d 0f d5 08 2d 1e 28 0a   ..&.;.U.=...-.(.
    01f0 - c2 fd a2 f3 2a 40 25 ed-2b 06 2c 92 c3 78 a3 b3   ....*@%.+.,..x..
    0200 - 35 bc d9 6c 57 97 ca 93-0f f3 b8 e4 60 d8 99 b4   5..lW.......`...
    0210 - b8 ba ae b7 47 4a 59 84-5b f9 5e b2 11 44 42 bd   ....GJY.[.^..DB.
    0220 - e8 46 3d 1d 09 70 72 f6-23 df 89 f8 f7 b7 84 d2   .F=..pr.#.......
    0230 - 7d 42 0e 5d d7 76 c2 da-0b 61 f9 48 3c c9 5f ba   }B.].v...a.H<._.
    0240 - ab be 5f 82 2b 03 07 f1-83 12 69 ee 56 b5 7e 06   .._.+.....i.V.~.
    0250 - 03 d7 8e b3 70 7c 93 75-3d cd e0 a1 1b 8a 14 ef   ....p|.u=.......
    0260 - 91 c6 74 14 1e 16 4c 46-07 c5 62 04 70 a7 fd 5d   ..t...LF..b.p..]
    0270 - e5 67 d8 bf 43 bb 5e f3-7c 37 db 1a 66 cb ad 7d   .g..C.^.|7..f..}
    0280 - cc 30 e4 9b 35 30 b5 6c-d0 4b ba b2 8b 01 71 0e   .0..50.l.K....q.
    0290 - 0a af ec 4e 6a 1a f8 6f-b7 5e 2b b9 e9 ec b6 b6   ...Nj..o.^+.....
    02a0 - 38 1c 70 5c 86 bf ae a4-e6 41 9d c9 9f 40 e4 a0   8.p\.....A...@..
    02b0 - 4b 0d 3d ab 01 90 da 55-cb b8 c8 e6 94 8d 76 35   K.=....U......v5
    02c0 - 94 b5 e2 1a 7c 69 5c b3-ee 08 8b bd 3f 97 c4 31   ....|i\.....?..1
    02d0 - 72 8a 30 a8 c6 3e 74 74-dc 47 c1 d0 ce bd 0b 19   r.0..>tt.G......
    02e0 - f4 93 55 8c 1f 02 b3 6e-f3 4d 44 f1 cc f0 ef 2d   ..U....n.MD....-
    02f0 - 4d 16 92 a3 15 fe 69 db-cc b1 b5 6b d0 4a 49 fc   M.....i....k.JI.
    0300 - 67 9e 0c 47 96 08 0e f2-b2 5c 06 24 45 f3 6a 7d   g..G.....\.$E.j}
    0310 - 6e 1b 2b 9a 68 23 11 3a-43 79 8c 77 9e 98 be 38   n.+.h#.:Cy.w...8
    0320 - 9a 0e e1 a5 17 bd 0f 7b-e0 ac ca 94 ac 48 68 5c   .......{.....Hh\
    0330 - f1 2b 98 b5 8d 36 b6 4f-aa 6f e7 d4 4d a3 f0 4c   .+...6.O.o..M..L
    0340 - cb 09 92 91 01 b9 c2 f1-49 24 64 d3 14 2f a3 5f   ........I$d../._
    0350 - 74 6f c0 54 16 73 c8 40-33 bc 7e e9 3b d8 d5 7c   to.T.s.@3.~.;..|
    0360 - 78 49 5c 80 83 88 4e 4b-46 f2 7a 6b 62 c4 ca 42   xI\...NKF.zkb..B
    0370 - 18 b6 22 40 77 fc 26 0e-28 50 89 7a 14 49 ba b0   .."@w.&.(P.z.I..
    0380 - 2c d7 26 7a 30 f9 9b 90-ba 9a 1f 3b 80 1b 0b 25   ,.&z0......;...%
    0390 - f0 e7 83 83 55 1f 1e f0-71 5b 64 a4 1e 76 91 bb   ....U...q[d..v..
    03a0 - d9 19 f5 2d 2e 54 d7 3a-93 95 29 ae 44 09 e6 cd   ...-.T.:..).D...
    03b0 - ec 79 8d b6 3c 09 d5 05-8d fc 2b 79 88 37 25 92   .y..<.....+y.7%.
    03c0 - 73 ae e6 8a d6 0c 1a eb-7b b9 08 44 4e 81 67 36   s.......{..DN.g6
    03d0 - a6 3a 57 43 d0 ed dc 3e-bb 0f 87 02 f5 fe 80 bb   .:WC...>........
    03e0 - 28 17 6e 7e ad c4 d9 4c-0a 53 fa 41 d2 d2 7c 76   (.n~...L.S.A..|v
    03f0 - a4 95 10 26 1d 5b 7d 19-23 dd 28 a0 48 c1 96 d9   ...&.[}.#.(.H...

    Start Time: 1444189099
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
---
closed

(Mac) Install the client PKCS12 file into Keychain Access

Open /etc/apache2/ssl in Finder and double-click the client PKCS12 file (client-cert.p12) to install it to Keychain Access:

Open https://localhost in your browser again and select the client cert when prompted:

You should then once again see a successful secure connection:

cURL will also work:

| => curl -v --cert /etc/apache2/ssl/client-cert.p12:snaplogic https://localhost
* Rebuilt URL to: https://localhost/
*   Trying ::1...
* Connected to localhost (::1) port 443 (#0)
* WARNING: SSL: Certificate type not set, assuming PKCS#12 format.
* Client certificate: client
| => curl -v --cert /etc/apache2/ssl/client-cert.p12:snaplogic https://localhost
* Rebuilt URL to: https://localhost/
*   Trying ::1...
* Connected to localhost (::1) port 443 (#0)
* WARNING: SSL: Certificate type not set, assuming PKCS#12 format.
* Client certificate: client
* TLS 1.0 connection using TLS_DHE_RSA_WITH_AES_256_CBC_SHA
* Server certificate: localhost
* Server certificate: localhost
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.43.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Tue, 05 Jan 2016 23:16:29 GMT
< Server: Apache/2.4.16 (Unix) PHP/5.5.29 OpenSSL/0.9.8zg
< Last-Modified: Fri, 02 Oct 2015 18:34:41 GMT
< ETag: "19-521236aaf5240"
< Accept-Ranges: bytes
< Content-Length: 25
< Content-Type: text/html
< 
<h1>localhost works</h1>
* Connection #0 to host localhost left intact
譯者信息

在 Finder 中打開 /etc/apache2/ssl

開發 CA 證書(cacert.pem)通過雙擊它來安裝 Keychain Access:

標記為可信任的:在你的瀏覽器中打開 https://localhost 地址,你就可以看到一個成功的安全連接:

為雙向 SSL 認證配置 Apache

根目錄:

vi /etc/apache2/extra/httpd-vhosts.conf

增加 SSLVerifyClient, SSLCertificateFile,以及 SSLCACertificateFile 選項:

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot "/Users/rhowlett/Sites/localhost"

    <Directory "/Users/rhowlett/Sites/localhost">
        Options Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all
        Require all granted
    </Directory>
</VirtualHost>

<VirtualHost *:443>
    ServerName localhost
    DocumentRoot "/Users/rhowlett/Sites/localhost"

    SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
    SSLEngine on
    SSLCertificateFile /etc/apache2/ssl/server-cert.pem
    SSLCertificateKeyFile /etc/apache2/ssl/private/server-key.pem

    SSLVerifyClient require
    SSLVerifyDepth 10
    SSLCACertificateFile /etc/apache2/ssl/cacert.pem

    <Directory "/Users/rhowlett/Sites/localhost">
        Options Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all
        Require all granted
    </Directory>
</VirtualHost>

重啟 Apache:

apachectl restart

現在,OpenSSL 能確認雙向 SSL 信號交換能成功地完成:

| rhowlett@SL-MBP-RHOWLETT.local:~/Downloads 
| => openssl s_client -connect localhost:443 -tls1 -cert /etc/apache2/ssl/client-cert.pem -key /etc/apache2/ssl/private/client-key.pem
CONNECTED(00000003)
depth=1 /C=US/ST=Colorado/L=Boulder/O=SnapLogic/OU=SnapTeam/CN=localhost
verify error:num=19:self signed certificate in certificate chain
verify return:0
---
Certificate chain
 0 s:/C=US/ST=Colorado/O=SnapLogic/OU=SnapTeam/CN=localhost
   i:/C=US/ST=Colorado/L=Boulder/O=SnapLogic/OU=SnapTeam/CN=localhost
 1 s:/C=US/ST=Colorado/L=Boulder/O=SnapLogic/OU=SnapTeam/CN=localhost
   i:/C=US/ST=Colorado/L=Boulder/O=SnapLogic/OU=SnapTeam/CN=localhost
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDPjCCAiYCAxAAATANBgkqhkiG9w0BAQ0FADBtMQswCQYDVQQGEwJVUzERMA8G
A1UECBMIQ29sb3JhZG8xEDAOBgNVBAcTB0JvdWxkZXIxEjAQBgNVBAoTCVNuYXBM
b2dpYzERMA8GA1UECxMIU25hcFRlYW0xEjAQBgNVBAMTCWxvY2FsaG9zdDAeFw0x
NTEwMDYxOTE1MTNaFw0xNjEwMDUxOTE1MTNaMFsxCzAJBgNVBAYTAlVTMREwDwYD
VQQIEwhDb2xvcmFkbzESMBAGA1UEChMJU25hcExvZ2ljMREwDwYDVQQLEwhTbmFw
VGVhbTESMBAGA1UEAxMJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAyvia0x0Nd4tYyvoXEYtI3s/eLIQ3wFsOJIibNy70PLhp35gScQ69
MiIrVDYqIydVbInzyY5kuhttrUIrHCIiDwa5OqEiExJ+ollY9icnrMLrEXJqvv5C
/fduS5byC6StNg7xHQkYlYLUYMw8QQyCZFQVGXlxZeG6i086ffMYduFimkBAkNj5
/LkIwrOELpGnNcrOJxQEnLi8vmRI3oiCrgVc0ugrFBnoj3Tf6y3lx23fYgLbqf9c
bRCS6V3eppa/x9sezv9KQ+pDYly0bwKIcvJ9xLp7qPiO+smGGvS97Ec4NAif8y6v
pU92cPH32cv1p0AIDF0+GMOgVyAYZgSKQwIDAQABMA0GCSqGSIb3DQEBDQUAA4IB
AQBedsAvkB1yNLE2GCJWWQ19qEKOIBYCRQc2z29PgF/LAz5GVOIw/ZiN37C2vTob
jk1NnqfOx5aipQ5Pe5D2yfbarDl0kaqRn9MhBySi+oi3AgUZ5yL0x/nGF9O8jszJ
OM1FUC6qXKic5pR0qTrdXigONlKb0Au+l3z5dFMiqnNmDrNlI8kW1OXrwy/jvyPv
H1bHWAKYFTvHi2v7A0B96V1VvFBLbuQztckPQ3VpFDOwWhWLr2D90vxFd1Ea0SCi
3bysz4ax9XP0bmXJY+968nV31qQJMkk5/3rE5PWVZibsniccfdujgSQYl+yNA3sB
F5h6mCR6pAONZFo6+U3zARSb
-----END CERTIFICATE-----
subject=/C=US/ST=Colorado/O=SnapLogic/OU=SnapTeam/CN=localhost
issuer=/C=US/ST=Colorado/L=Boulder/O=SnapLogic/OU=SnapTeam/CN=localhost
---
Acceptable client certificate CA names
/C=US/ST=Colorado/L=Boulder/O=SnapLogic/OU=SnapTeam/CN=localhost
---
SSL handshake has read 4004 bytes and written 1539 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES256-SHA
    Session-ID: A1D9CE5273963BCF70503B499D7714ECE2B628CEE59CE554615743ACEEA8E281
    Session-ID-ctx: 
    Master-Key: 0920CEE1491E9A116B2DF959430890D449D49DA990A178C0AC980DD5AF359B7E1CDD4B2D8237C8F81BAE186BC06E7BB0
    Key-Arg   : None
    TLS session ticket:
    0000 - 5c 8f 01 d5 5d c1 62 d5-65 d7 8f 05 5f 47 d2 82   \...].b.e..._G..
    0010 - f0 fd 2c 88 be 58 25 6c-9e 9a 1e 78 6a b4 66 c4   ..,..X%l...xj.f.
    0020 - 0d 3d 31 04 97 a2 5f e7-6f 3c 9f c9 b1 44 6a ab   .=1..._.o<...Dj.
    0030 - 84 89 76 e4 63 9b 81 b7-c3 28 e0 95 c6 c3 f5 89   ..v.c....(......
    0040 - d5 f9 7f da df fb 12 f7-de 2a ec e8 c2 01 59 07   .........*....Y.
    0050 - 9e ad 91 56 91 34 88 73-66 d1 ea c1 72 dc 56 ee   ...V.4.sf...r.V.
    0060 - ee 61 fe 5e 38 f0 aa d6-3a 7d ad ef e6 be 2a 15   .a.^8...:}....*.
    0070 - dc cc 9f 04 5e e8 f9 2b-07 21 6b 0f da 9f 08 2e   ....^..+.!k.....
    0080 - 88 af 96 41 98 f3 ff 8a-01 66 1a 1d 61 47 1b e5   ...A.....f..aG..
    0090 - ec ab b7 af 79 aa 7d 25-ca e0 fa f4 2b 2e 9a dd   ....y.}%....+...
    00a0 - 95 0c 4b 35 d8 96 8b f0-1e 20 c1 c3 47 fc 65 ed   ..K5..... ..G.e.
    00b0 - 21 e4 50 59 1e 33 6a 5c-c6 27 f1 65 be 5b 0f 35   !.PY.3j\.'.e.[.5
    00c0 - 1d ba ac bf f5 9c d9 b7-32 87 11 ae b7 87 9b 52   ........2......R
    00d0 - bb 00 6b 66 af e2 94 45-e3 8f fb e0 b4 c6 d7 5a   ..kf...E.......Z
    00e0 - f8 1d 7a af e3 ee bb 6b-93 ff 46 af ed 86 bc f8   ..z....k..F.....
    00f0 - 6d e2 c9 60 eb 61 8e b9-7e bd 4d bb 1e 01 95 d2   m..`.a..~.M.....
    0100 - f5 d5 ee 82 10 4a 1d 23-9e 94 d7 0b 46 e4 d4 32   .....J.#....F..2
    0110 - 11 92 76 4a 94 9e a3 61-21 9b 4c 49 6c df 7b 18   ..vJ...a!.LIl.{.
    0120 - b7 49 66 bd 48 0d eb 9a-ad e9 32 c7 b9 6d 70 1a   .If.H.....2..mp.
    0130 - c7 a1 25 21 b4 f1 03 5b-80 83 e9 da 8d 56 f1 d9   ..%!...[.....V..
    0140 - 8b c5 32 b7 3a 67 5b 9c-51 84 a0 09 04 4f 48 60   ..2.:g[.Q....OH`
    0150 - 27 c0 fe 1c 45 7a 3b b2-22 8d ed 65 72 23 8a bf   '...Ez;."..er#..
    0160 - e3 09 eb 78 98 ec 08 06-9d 37 02 1a 4b ae cd 3a   ...x.....7..K..:
    0170 - 9c a4 bd 5d 47 5e d3 d7-7b 89 7b 97 78 a6 4c 10   ...]G^..{.{.x.L.
    0180 - bf 3e ed 1f f4 fe e5 97-90 ee 31 58 5f ff c6 c2   .>........1X_...
    0190 - 61 b7 df 0a f5 27 c6 a8-ac 61 a3 d0 1e 3a 6a 42   a....'...a...:jB
    01a0 - a9 18 b4 fb 4b 25 87 62-97 26 48 35 d0 16 d1 06   ....K%.b.&H5....
    01b0 - 9d 82 b5 e2 7b f2 24 c5-83 a1 4b fe 8d 38 ae 30   ....{.$...K..8.0
    01c0 - 8e eb e1 ac 8b 48 fa 27-b0 e1 ce b3 17 62 69 f0   .....H.'.....bi.
    01d0 - 30 17 ae 31 9d bf 77 64-66 5b 13 8e a2 63 2e 58   0..1..wdf[...c.X
    01e0 - 02 10 26 e1 3b 0d 55 fc-3d 0f d5 08 2d 1e 28 0a   ..&.;.U.=...-.(.
    01f0 - c2 fd a2 f3 2a 40 25 ed-2b 06 2c 92 c3 78 a3 b3   ....*@%.+.,..x..
    0200 - 35 bc d9 6c 57 97 ca 93-0f f3 b8 e4 60 d8 99 b4   5..lW.......`...
    0210 - b8 ba ae b7 47 4a 59 84-5b f9 5e b2 11 44 42 bd   ....GJY.[.^..DB.
    0220 - e8 46 3d 1d 09 70 72 f6-23 df 89 f8 f7 b7 84 d2   .F=..pr.#.......
    0230 - 7d 42 0e 5d d7 76 c2 da-0b 61 f9 48 3c c9 5f ba   }B.].v...a.H<._.
    0240 - ab be 5f 82 2b 03 07 f1-83 12 69 ee 56 b5 7e 06   .._.+.....i.V.~.
    0250 - 03 d7 8e b3 70 7c 93 75-3d cd e0 a1 1b 8a 14 ef   ....p|.u=.......
    0260 - 91 c6 74 14 1e 16 4c 46-07 c5 62 04 70 a7 fd 5d   ..t...LF..b.p..]
    0270 - e5 67 d8 bf 43 bb 5e f3-7c 37 db 1a 66 cb ad 7d   .g..C.^.|7..f..}
    0280 - cc 30 e4 9b 35 30 b5 6c-d0 4b ba b2 8b 01 71 0e   .0..50.l.K....q.
    0290 - 0a af ec 4e 6a 1a f8 6f-b7 5e 2b b9 e9 ec b6 b6   ...Nj..o.^+.....
    02a0 - 38 1c 70 5c 86 bf ae a4-e6 41 9d c9 9f 40 e4 a0   8.p\.....A...@..
    02b0 - 4b 0d 3d ab 01 90 da 55-cb b8 c8 e6 94 8d 76 35   K.=....U......v5
    02c0 - 94 b5 e2 1a 7c 69 5c b3-ee 08 8b bd 3f 97 c4 31   ....|i\.....?..1
    02d0 - 72 8a 30 a8 c6 3e 74 74-dc 47 c1 d0 ce bd 0b 19   r.0..>tt.G......
    02e0 - f4 93 55 8c 1f 02 b3 6e-f3 4d 44 f1 cc f0 ef 2d   ..U....n.MD....-
    02f0 - 4d 16 92 a3 15 fe 69 db-cc b1 b5 6b d0 4a 49 fc   M.....i....k.JI.
    0300 - 67 9e 0c 47 96 08 0e f2-b2 5c 06 24 45 f3 6a 7d   g..G.....\.$E.j}
    0310 - 6e 1b 2b 9a 68 23 11 3a-43 79 8c 77 9e 98 be 38   n.+.h#.:Cy.w...8
    0320 - 9a 0e e1 a5 17 bd 0f 7b-e0 ac ca 94 ac 48 68 5c   .......{.....Hh\
    0330 - f1 2b 98 b5 8d 36 b6 4f-aa 6f e7 d4 4d a3 f0 4c   .+...6.O.o..M..L
    0340 - cb 09 92 91 01 b9 c2 f1-49 24 64 d3 14 2f a3 5f   ........I$d../._
    0350 - 74 6f c0 54 16 73 c8 40-33 bc 7e e9 3b d8 d5 7c   to.T.s.@3.~.;..|
    0360 - 78 49 5c 80 83 88 4e 4b-46 f2 7a 6b 62 c4 ca 42   xI\...NKF.zkb..B
    0370 - 18 b6 22 40 77 fc 26 0e-28 50 89 7a 14 49 ba b0   .."@w.&.(P.z.I..
    0380 - 2c d7 26 7a 30 f9 9b 90-ba 9a 1f 3b 80 1b 0b 25   ,.&z0......;...%
    0390 - f0 e7 83 83 55 1f 1e f0-71 5b 64 a4 1e 76 91 bb   ....U...q[d..v..
    03a0 - d9 19 f5 2d 2e 54 d7 3a-93 95 29 ae 44 09 e6 cd   ...-.T.:..).D...
    03b0 - ec 79 8d b6 3c 09 d5 05-8d fc 2b 79 88 37 25 92   .y..<.....+y.7%.
    03c0 - 73 ae e6 8a d6 0c 1a eb-7b b9 08 44 4e 81 67 36   s.......{..DN.g6
    03d0 - a6 3a 57 43 d0 ed dc 3e-bb 0f 87 02 f5 fe 80 bb   .:WC...>........
    03e0 - 28 17 6e 7e ad c4 d9 4c-0a 53 fa 41 d2 d2 7c 76   (.n~...L.S.A..|v
    03f0 - a4 95 10 26 1d 5b 7d 19-23 dd 28 a0 48 c1 96 d9   ...&.[}.#.(.H...

    Start Time: 1444189099
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
---
closed

(Mac) Keychain Access 中安裝客戶端 PKCS12 文件

在 Finder 中打開 /etc/apache2/ssl,通過雙擊客戶端 PKCS12 文件(client-cert.p12)來安裝Keychain Access:

在你的瀏覽器中打開 https://localhost 地址,當提示時,選擇客戶端證書:

那時,你應該再一次看到一個安全的連接:

cURL 也將運行:

| => curl -v --cert /etc/apache2/ssl/client-cert.p12:snaplogic https://localhost
* Rebuilt URL to: https://localhost/
*   Trying ::1...
* Connected to localhost (::1) port 443 (#0)
* WARNING: SSL: Certificate type not set, assuming PKCS#12 format.
* Client certificate: client
| => curl -v --cert /etc/apache2/ssl/client-cert.p12:snaplogic https://localhost
* Rebuilt URL to: https://localhost/
*   Trying ::1...
* Connected to localhost (::1) port 443 (#0)
* WARNING: SSL: Certificate type not set, assuming PKCS#12 format.
* Client certificate: client
* TLS 1.0 connection using TLS_DHE_RSA_WITH_AES_256_CBC_SHA
* Server certificate: localhost
* Server certificate: localhost
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.43.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Tue, 05 Jan 2016 23:16:29 GMT
< Server: Apache/2.4.16 (Unix) PHP/5.5.29 OpenSSL/0.9.8zg
< Last-Modified: Fri, 02 Oct 2015 18:34:41 GMT
< ETag: "19-521236aaf5240"
< Accept-Ranges: bytes
< Content-Length: 25
< Content-Type: text/html
< 
<h1>localhost works</h1>
* Connection #0 to host localhost left intact

Unit Testing SSL Authentication with Apache’s HttpClient and HttpServer

Apache’s HttpComponents provides HttpClient, “an efficient, up-to-date, and feature-rich package implementing the client side of the most recent HTTP standards and recommendations.”

It also provides HttpCore, which includes an embedded HttpServer, which can be used for unit testing.

Generate a PKCS12 (.p12) file from the public server-cert.pem, the private server-key.pem, and the CA cert cacert.pem created above to be used by the local test HttpServer instance:

| rhowlett@SL-MBP-RHOWLETT.local:~/dev/robinhowlett/github/everything-ssl/src/main/resources/ssl 
| => openssl pkcs12 -export -in /etc/apache2/ssl/server-cert.pem -inkey /etc/apache2/ssl/private/server-key.pem -certfile /etc/apache2/ssl/cacert.pem -name "Server" -out server-cert.p12
Enter Export Password:
Verifying - Enter Export Password:

If you see unable to write 'random state', run sudo rm ~/.rnd and try again

Java KeyStores (JKS)

Java has its own version of PKCS12 called Java KeyStore (JKS). It is also password protected. Entries in a JKS file must have an “alias” that is unique. If an alias is not specified, “mykey” is used by default. It’s like a database for certs and keys.

For both the “KeyStore” and “TrustStore” fields in the REST SSL Account settings, we are going to use JKS files. The difference between them is for terminology reasons: KeyStores provide credentials, TrustStores verify credentials.

Clients will use certificates stored in their TrustStores to verify identities of servers. They will present certificates stored in their KeyStores to servers requiring them.

Client Certificate Flow

The JDK ships with a tool called Keytool. It manages a JKS of cryptographic keys, X.509 certificate chains, and trusted certificates.

譯者信息

使用 Apache 的 HttpClient 和 HttpServer 進行單元測試 SSL 認證

Apache 的 HttpComponents 提供 HttpClient,“一個有效的,最新的,以及實現最近的客戶端 http 標准與建議的豐富多樣的包”

它也提供 HttpCore,其中包括一個嵌入式的 HttpServer,可用於單元測試。

通過本地測試 HttpServer 實例來創建以上的:從公眾的 server-cert.pem,私人的 server-key.pem,以及 CA 證書 cacert.pem 來生成 PKCS12 (.p12) 文件:

| rhowlett@SL-MBP-RHOWLETT.local:~/dev/robinhowlett/github/everything-ssl/src/main/resources/ssl 
| => openssl pkcs12 -export -in /etc/apache2/ssl/server-cert.pem -inkey /etc/apache2/ssl/private/server-key.pem -certfile /etc/apache2/ssl/cacert.pem -name "Server" -out server-cert.p12
Enter Export Password:
Verifying - Enter Export Password:

如果你看到 unable to write 'random state',運行 sudo rm ~/.rnd,再試一次

Java KeyStores(JKS)

Java 有它自己所謂的 Java KeyStore (JKS)PKCS12 版本。也就是密碼保護。在 JKS 條目文件中,必須有一個“alias” ,意即獨一無二。如果

一個 alias 不是被指定,那么“mykey”會被默認使用。它就像一個數據庫組與鑰匙。

對於在 REST SSL 賬號設置中的兩個“KeyStore”與“TrustStore” 字段,我們將使用 JKS 文件。它們之間的差異原因是因為術語。KeyStores 提供憑證,TrustStores 驗證憑證。

客戶端使用存貯在 TrustStores 之中的證書來驗證服務器身份。他們將呈現存儲在 KeyStores 之中的證書,以此讓服務器來請求他們。

 

Client Certificate Flow

使用所謂一個 Keytool 工具的 JDK ships。它管理一個 JKS 的加密密匙,X.509 證書鏈接,以及可信任的證書。

Creating KeyStores and TrustStores with Keytool

Create the Server’s KeyStore from the PKCS12 file:

| rhowlett@SL-MBP-RHOWLETT.local:~/dev/robinhowlett/github/everything-ssl/src/main/resources/ssl 
| => keytool -importkeystore -deststorepass snaplogic -destkeypass snaplogic -destkeystore server_keystore.jks -srckeystore server-cert.p12 -srcstoretype PKCS12 -srcstorepass snaplogic -alias server

View the server keystore to confirm it now contains the server’s cert:

| rhowlett@SL-MBP-RHOWLETT.local:~/dev/robinhowlett/github/everything-ssl/src/main/resources/ssl 
| => keytool -list -v -keystore server_keystore.jks 
Enter keystore password:  

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: server
Creation date: Jan 4, 2016
Entry type: PrivateKeyEntry
Certificate chain length: 2
Certificate[1]:
Owner: CN=localhost, OU=SnapTeam, O=SnapLogic, ST=Colorado, C=US
Issuer: CN=localhost, OU=SnapTeam, O=SnapLogic, L=Boulder, ST=Colorado, C=US
Serial number: 100001
Valid from: Tue Oct 06 13:15:13 MDT 2015 until: Wed Oct 05 13:15:13 MDT 2016
Certificate fingerprints:
     MD5:  62:83:6B:84:1B:CB:DE:26:CA:E0:9D:E8:04:84:B6:C1
     SHA1: AD:D4:27:FF:9A:68:77:25:95:C3:A2:BE:F6:22:AD:82:5C:2B:AF:EB
     SHA256: 8D:8D:EA:E5:7C:7A:E9:42:C9:9E:71:2A:76:C7:BE:BE:34:CC:4A:CC:83:ED:FE:C8:8E:C6:06:D2:D8:89:59:4A
     Signature algorithm name: SHA512withRSA
     Version: 1
Certificate[2]:
Owner: CN=localhost, OU=SnapTeam, O=SnapLogic, L=Boulder, ST=Colorado, C=US
Issuer: CN=localhost, OU=SnapTeam, O=SnapLogic, L=Boulder, ST=Colorado, C=US
Serial number: e4e00ed07233a969
Valid from: Tue Oct 06 13:14:51 MDT 2015 until: Wed Oct 05 13:14:51 MDT 2016
Certificate fingerprints:
     MD5:  F3:5E:28:E4:28:47:F2:EC:82:E2:BD:16:31:DC:90:02
     SHA1: 6F:0F:49:BA:A9:30:01:E9:4C:60:B3:A1:85:7D:BB:C6:79:1F:41:7B
     SHA256: A7:9D:25:E4:A6:34:8A:A3:5B:9A:CD:F3:62:D0:D8:2F:6A:A0:71:6A:6D:19:F3:04:A1:FD:BC:FB:21:40:DE:A1
     Signature algorithm name: SHA512withRSA
     Version: 3

Extensions: 

#1: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 03 09 12 6E 8B DD 7A 80   FB F5 21 AB 75 D9 B8 49  ...n..z...!.u..I
0010: 79 5B 61 1F                                        y[a.
]
[CN=localhost, OU=SnapTeam, O=SnapLogic, L=Boulder, ST=Colorado, C=US]
SerialNumber: [    e4e00ed0 7233a969]
]

#2: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
  CA:true
  PathLen:2147483647
]

#3: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 03 09 12 6E 8B DD 7A 80   FB F5 21 AB 75 D9 B8 49  ...n..z...!.u..I
0010: 79 5B 61 1F                                        y[a.
]
]



*******************************************
*******************************************

Create the client’s truststore and import the server’s public certificate:

| rhowlett@SL-MBP-RHOWLETT.local:~/dev/robinhowlett/github/everything-ssl/src/main/resources/ssl 
| => keytool -import -v -trustcacerts -keystore client_truststore.jks -storepass snaplogic -alias server -file /etc/apache2/ssl/server-cert.pem
Owner: CN=localhost, OU=SnapTeam, O=SnapLogic, ST=Colorado, C=US
Issuer: CN=localhost, OU=SnapTeam, O=SnapLogic, L=Boulder, ST=Colorado, C=US
Serial number: 100001
Valid from: Tue Oct 06 13:15:13 MDT 2015 until: Wed Oct 05 13:15:13 MDT 2016
Certificate fingerprints:
     MD5:  62:83:6B:84:1B:CB:DE:26:CA:E0:9D:E8:04:84:B6:C1
     SHA1: AD:D4:27:FF:9A:68:77:25:95:C3:A2:BE:F6:22:AD:82:5C:2B:AF:EB
     SHA256: 8D:8D:EA:E5:7C:7A:E9:42:C9:9E:71:2A:76:C7:BE:BE:34:CC:4A:CC:83:ED:FE:C8:8E:C6:06:D2:D8:89:59:4A
     Signature algorithm name: SHA512withRSA
     Version: 1
Trust this certificate? [no]:  yes
Certificate was added to keystore
[Storing client_truststore.jks]

View the client’s truststore to confirm it contains the server’s cert:

| rhowlett@SL-MBP-RHOWLETT.local:~/dev/robinhowlett/github/everything-ssl/src/main/resources/ssl 
| => keytool -list -v -keystore client_truststore.jks 
Enter keystore password:  

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: server
Creation date: Jan 4, 2016
Entry type: trustedCertEntry

Owner: CN=localhost, OU=SnapTeam, O=SnapLogic, ST=Colorado, C=US
Issuer: CN=localhost, OU=SnapTeam, O=SnapLogic, L=Boulder, ST=Colorado, C=US
Serial number: 100001
Valid from: Tue Oct 06 13:15:13 MDT 2015 until: Wed Oct 05 13:15:13 MDT 2016
Certificate fingerprints:
     MD5:  62:83:6B:84:1B:CB:DE:26:CA:E0:9D:E8:04:84:B6:C1
     SHA1: AD:D4:27:FF:9A:68:77:25:95:C3:A2:BE:F6:22:AD:82:5C:2B:AF:EB
     SHA256: 8D:8D:EA:E5:7C:7A:E9:42:C9:9E:71:2A:76:C7:BE:BE:34:CC:4A:CC:83:ED:FE:C8:8E:C6:06:D2:D8:89:59:4A
     Signature algorithm name: SHA512withRSA
     Version: 1


*******************************************
*******************************************
譯者信息

使用 Keytool 創建 KeyStores 和 TrustStores

從 PKCS12 文件中創建服務器的 KeyStore:

| rhowlett@SL-MBP-RHOWLETT.local:~/dev/robinhowlett/github/everything-ssl/src/main/resources/ssl 
| => keytool -importkeystore -deststorepass snaplogic -destkeypass snaplogic -destkeystore server_keystore.jks -srckeystore server-cert.p12 -srcstoretype PKCS12 -srcstorepass snaplogic -alias server

查看服務器 keystore 以確認它現在包含了服務器證書:

| rhowlett@SL-MBP-RHOWLETT.local:~/dev/robinhowlett/github/everything-ssl/src/main/resources/ssl 
| => keytool -list -v -keystore server_keystore.jks 
Enter keystore password:  

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: server
Creation date: Jan 4, 2016
Entry type: PrivateKeyEntry
Certificate chain length: 2
Certificate[1]:
Owner: CN=localhost, OU=SnapTeam, O=SnapLogic, ST=Colorado, C=US
Issuer: CN=localhost, OU=SnapTeam, O=SnapLogic, L=Boulder, ST=Colorado, C=US
Serial number: 100001
Valid from: Tue Oct 06 13:15:13 MDT 2015 until: Wed Oct 05 13:15:13 MDT 2016
Certificate fingerprints:
     MD5:  62:83:6B:84:1B:CB:DE:26:CA:E0:9D:E8:04:84:B6:C1
     SHA1: AD:D4:27:FF:9A:68:77:25:95:C3:A2:BE:F6:22:AD:82:5C:2B:AF:EB
     SHA256: 8D:8D:EA:E5:7C:7A:E9:42:C9:9E:71:2A:76:C7:BE:BE:34:CC:4A:CC:83:ED:FE:C8:8E:C6:06:D2:D8:89:59:4A
     Signature algorithm name: SHA512withRSA
     Version: 1
Certificate[2]:
Owner: CN=localhost, OU=SnapTeam, O=SnapLogic, L=Boulder, ST=Colorado, C=US
Issuer: CN=localhost, OU=SnapTeam, O=SnapLogic, L=Boulder, ST=Colorado, C=US
Serial number: e4e00ed07233a969
Valid from: Tue Oct 06 13:14:51 MDT 2015 until: Wed Oct 05 13:14:51 MDT 2016
Certificate fingerprints:
     MD5:  F3:5E:28:E4:28:47:F2:EC:82:E2:BD:16:31:DC:90:02
     SHA1: 6F:0F:49:BA:A9:30:01:E9:4C:60:B3:A1:85:7D:BB:C6:79:1F:41:7B
     SHA256: A7:9D:25:E4:A6:34:8A:A3:5B:9A:CD:F3:62:D0:D8:2F:6A:A0:71:6A:6D:19:F3:04:A1:FD:BC:FB:21:40:DE:A1
     Signature algorithm name: SHA512withRSA
     Version: 3

Extensions: 

#1: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 03 09 12 6E 8B DD 7A 80   FB F5 21 AB 75 D9 B8 49  ...n..z...!.u..I
0010: 79 5B 61 1F                                        y[a.
]
[CN=localhost, OU=SnapTeam, O=SnapLogic, L=Boulder, ST=Colorado, C=US]
SerialNumber: [    e4e00ed0 7233a969]
]

#2: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
  CA:true
  PathLen:2147483647
]

#3: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 03 09 12 6E 8B DD 7A 80   FB F5 21 AB 75 D9 B8 49  ...n..z...!.u..I
0010: 79 5B 61 1F                                        y[a.
]
]



*******************************************
*******************************************

創建客戶端的 truststore 並導入服務器公共證書:

| rhowlett@SL-MBP-RHOWLETT.local:~/dev/robinhowlett/github/everything-ssl/src/main/resources/ssl 
| => keytool -import -v -trustcacerts -keystore client_truststore.jks -storepass snaplogic -alias server -file /etc/apache2/ssl/server-cert.pem
Owner: CN=localhost, OU=SnapTeam, O=SnapLogic, ST=Colorado, C=US
Issuer: CN=localhost, OU=SnapTeam, O=SnapLogic, L=Boulder, ST=Colorado, C=US
Serial number: 100001
Valid from: Tue Oct 06 13:15:13 MDT 2015 until: Wed Oct 05 13:15:13 MDT 2016
Certificate fingerprints:
     MD5:  62:83:6B:84:1B:CB:DE:26:CA:E0:9D:E8:04:84:B6:C1
     SHA1: AD:D4:27:FF:9A:68:77:25:95:C3:A2:BE:F6:22:AD:82:5C:2B:AF:EB
     SHA256: 8D:8D:EA:E5:7C:7A:E9:42:C9:9E:71:2A:76:C7:BE:BE:34:CC:4A:CC:83:ED:FE:C8:8E:C6:06:D2:D8:89:59:4A
     Signature algorithm name: SHA512withRSA
     Version: 1
Trust this certificate? [no]:  yes
Certificate was added to keystore
[Storing client_truststore.jks]

查看客戶端 truststore 以確認它現在包含了服務器證書:

| rhowlett@SL-MBP-RHOWLETT.local:~/dev/robinhowlett/github/everything-ssl/src/main/resources/ssl 
| => keytool -list -v -keystore client_truststore.jks 
Enter keystore password:  

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: server
Creation date: Jan 4, 2016
Entry type: trustedCertEntry

Owner: CN=localhost, OU=SnapTeam, O=SnapLogic, ST=Colorado, C=US
Issuer: CN=localhost, OU=SnapTeam, O=SnapLogic, L=Boulder, ST=Colorado, C=US
Serial number: 100001
Valid from: Tue Oct 06 13:15:13 MDT 2015 until: Wed Oct 05 13:15:13 MDT 2016
Certificate fingerprints:
     MD5:  62:83:6B:84:1B:CB:DE:26:CA:E0:9D:E8:04:84:B6:C1
     SHA1: AD:D4:27:FF:9A:68:77:25:95:C3:A2:BE:F6:22:AD:82:5C:2B:AF:EB
     SHA256: 8D:8D:EA:E5:7C:7A:E9:42:C9:9E:71:2A:76:C7:BE:BE:34:CC:4A:CC:83:ED:FE:C8:8E:C6:06:D2:D8:89:59:4A
     Signature algorithm name: SHA512withRSA
     Version: 1


*******************************************
*******************************************

One-Way SSL

At this point we have enough to demonstrate one-way SSL with the local test HttpServer instance. The createLocalTestServer method instantiates an embedded HttpServer instance with an (optional) sslContext (null meaning HTTP-only) and a boolean “forceSSLAuth” indicating if client certificates are required or not:

123456789101112
protected HttpServer createLocalTestServer(SSLContext sslContext, boolean forceSSLAuth)        throws UnknownHostException {    final HttpServer server = ServerBootstrap.bootstrap()            .setLocalAddress(Inet4Address.getByName("localhost"))            .setSslContext(sslContext)            .setSslSetupHandler(socket -> socket.setNeedClientAuth(forceSSLAuth))            .registerHandler("*",                    (request, response, context) -> response.setStatusCode(HttpStatus.SC_OK))            .create();    return server;}

The getStore method loads the JKS files from the classpath, and the getKeyManagers and getTrustManagers methods turn that store into the respective Key- or TrustManager arrays that are used to initialize an SSLContext:

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
private static final String JAVA_KEYSTORE = "jks";/ * KeyStores provide credentials, TrustStores verify credentials.  * Server KeyStores stores the server's private keys, and certificates for corresponding public * keys. Used here for HTTPS connections over localhost.  * Client TrustStores store servers' certificates. */protected KeyStore getStore(final String storeFileName, final char[] password) throws        KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {    final KeyStore store = KeyStore.getInstance(JAVA_KEYSTORE);    URL url = getClass().getClassLoader().getResource(storeFileName);    InputStream inputStream = url.openStream();    try {        store.load(inputStream, password);    } finally {        inputStream.close();    }    return store;}/ * KeyManagers decide which authentication credentials (e.g. certs) should be sent to the remote * host for authentication during the SSL handshake.  * Server KeyManagers use their private keys during the key exchange algorithm and send * certificates corresponding to their public keys to the clients. The certificate comes from * the KeyStore. /protected KeyManager[] getKeyManagers(KeyStore store, final char[] password) throws        NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException {    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(            KeyManagerFactory.getDefaultAlgorithm());    keyManagerFactory.init(store, password);    return keyManagerFactory.getKeyManagers();}/ * TrustManagers determine if the remote connection should be trusted or not.  * Clients will use certificates stored in their TrustStores to verify identities of servers. * Servers will use certificates stored in their TrustStores to verify identities of clients. /protected TrustManager[] getTrustManagers(KeyStore store) throws NoSuchAlgorithmException,        KeyStoreException {    TrustManagerFactory trustManagerFactory =            TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());    trustManagerFactory.init(store);    return trustManagerFactory.getTrustManagers();}

The SSLContext is created and initialized like so:

12345678910111213141516
/Create an SSLContext for the server using the server's JKS. This instructs the server topresent its certificate when clients connect over HTTPS. /protected SSLContext createServerSSLContext(final String storeFileName, final char[]        password) throws CertificateException, NoSuchAlgorithmException, KeyStoreException,        IOException, UnrecoverableKeyException, KeyManagementException {    KeyStore serverKeyStore = getStore(storeFileName, password);    KeyManager[] serverKeyManagers = getKeyManagers(serverKeyStore, password);    TrustManager[] serverTrustManagers = getTrustManagers(serverKeyStore);    SSLContext sslContext = SSLContexts.custom().useProtocol("TLS").build();    sslContext.init(serverKeyManagers, serverTrustManagers, new SecureRandom());    return sslContext;}

The following unit test shows making a HTTPS request to the local test HttpServer instance and validating the server’s public certificate with the client’s truststore:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
private static final boolean ONE_WAY_SSL = false; // no client certificatesprivate static final char[] KEYPASS_AND_STOREPASS_VALUE = "snaplogic".toCharArray();private static final String SERVER_KEYSTORE = "ssl/server_keystore.jks";private static final String CLIENT_TRUSTSTORE = "ssl/client_truststore.jks";private CloseableHttpClient httpclient;@Beforepublic void setUp() throws Exception {    httpclient = HttpClients.createDefault();}@Testpublic void httpsRequest_With1WaySSLAndValidatingCertsAndClientTrustStore_Returns200OK()        throws Exception {    SSLContext serverSSLContext =            createServerSSLContext(SERVER_KEYSTORE, KEYPASS_AND_STOREPASS_VALUE);    final HttpServer server = createLocalTestServer(serverSSLContext, ONE_WAY_SSL);    server.start();    String baseUrl = getBaseUrl(server);    // The server certificate was imported into the client's TrustStore (using keytool -import)    KeyStore clientTrustStore = getStore(CLIENT_TRUSTSTORE, KEYPASS_AND_STOREPASS_VALUE);    SSLContext sslContext =            new SSLContextBuilder().loadTrustMaterial(                    clientTrustStore, new TrustSelfSignedStrategy()).build();    httpclient = HttpClients.custom().setSSLContext(sslContext).build();    /    The HTTP client will now validate the server's presented certificate using its TrustStore.     Since the cert was imported to the client's TrustStore explicitly (see above), the     certificate will validate and the request will succeed     /    try {        HttpResponse httpResponse = httpclient.execute(                new HttpGet("https://&quot; + baseUrl + "/echo/this"));        assertThat(httpResponse.getStatusLine().getStatusCode(), equalTo(200));    } finally {        server.stop();    }}protected String getBaseUrl(HttpServer server) {    return server.getInetAddress().getHostName() + ":" + server.getLocalPort();}

The above unit test is included in the everything-ssl GitHub project, along with the following (which are useful to see the  behavior when the SSL handshake fails, when server certificate validation is bypassed, malformed contexts etc.)

  • execute_WithNoScheme_ThrowsClientProtocolExceptionInvalidHostname

  • httpRequest_Returns200OK

  • httpsRequest_WithNoSSLContext_ThrowsSSLExceptionPlaintextConnection

  • httpsRequest_With1WaySSLAndValidatingCertsButNoClientTrustStore_ThrowsSSLException

  • httpsRequest_With1WaySSLAndTrustingAllCertsButNoClientTrustStore_Returns200OK

  • httpsRequest_With1WaySSLAndValidatingCertsAndClientTrustStore_Returns200OK

譯者信息

單向 SSL

此時此刻,我們必須通過本地測試的 HttpServer 實例來足夠地證明單向 SSL。createLocalTestServer 方法使用一個(選項)sslContext(null僅僅意味着http)以及一個boolean

“forceSSLAuth”表明是否請求客戶端證書來實例化一個嵌入式的 HttpServer 實例:

123456789101112
protected HttpServer createLocalTestServer(SSLContext sslContext, boolean forceSSLAuth)        throws UnknownHostException {    final HttpServer server = ServerBootstrap.bootstrap()            .setLocalAddress(Inet4Address.getByName("localhost"))            .setSslContext(sslContext)            .setSslSetupHandler(socket -> socket.setNeedClientAuth(forceSSLAuth))            .registerHandler

getStore 方法從類路徑加載 jks 文件,以及 getKeyManagers 與 getTrustManagers 方法,把那個存儲轉變成各自的用於初始化一個 SSLContext 的 Key- o 或者 TrustManager 數組:

12345678910111213141516171819202122232425262728293031323334353637383940414243444

創建 SSLContext 以及像這樣初始化:

12345678910111213141516
/Create an SSLContext for the server using the server's

以下的單元測試顯示了對本地測試 HttpServer 實例做了一個 HTTPS 請求,以及使用客戶端 truststore 來驗證服務器公開證書:

123456789101112131415161718192021222324252627282930313233343536373839404142434445

在 everything-ssl GitHub project,以上的單元測試中,連同以下的(當 SSL 信號交換失敗時,當繞過服務器證書驗證時,以及難看的上下文等等時,你可以看到該行為有利。

  • execute_WithNoScheme_ThrowsClientProtocolExceptionInvalidHostname

  • httpRequest_Returns200OK

  • httpsRequest_WithNoSSLContext_ThrowsSSLExceptionPlaintextConnection

  • httpsRequest_With1WaySSLAndValidatingCertsButNoClientTrustStore_ThrowsSSLException

  • httpsRequest_With1WaySSLAndTrustingAllCertsButNoClientTrustStore_Returns200OK

  • httpsRequest_With1WaySSLAndValidatingCertsAndClientTrustStore_Returns200OK


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM