數字證書
對於一個安全的通信,應該有以下特征:
- 完整性:消息在傳輸過程中未被篡改
- 身份驗證:確認消息發送者的身份
- 不可否認:消息的發送者無法否認自己發送了信息
顯然,數字簽名和消息認證碼是不符合要求的,這里就需要數字證書來解決其弊端。
數字證書(digital certificate)又稱公開密鑰認證 PKC(英語:Public key certificate)。是在互聯網通信中,方式數字簽名的秘鑰被篡改,是用來證明公開密鑰擁有者的身份。此文件包含了公鑰信息、擁有者身份信息(主體)、以及數字證書認證機構(發行者)對這份文件的數字簽名,以保證這個文件的整體內容正確無誤。
數字證書認證機構 CA (Certificate Authority):是負責發放和管理數字證書的權威機構。
公鑰證書的格式標准
X.509
是密碼學中公鑰明證PKC的格式標准,所有的證書都符合ITU-T X.509國際標准。X.509證書的結構是用ASN1
(Abstract Syntax Notation One)進行描述數據結構,並使用ASN.1
語法進行編碼。
證書規范
X.509指的是ITU和ISO聯合制定的(RFC5280)里定義的的 X.509 v3
前使用最廣泛的標准為X.509的 v3版本規范 (RFC5280), 一般遵從X.509
格式規范的證書,會有以下的內容:
證書組成結構
結構 | 說明 |
---|---|
版本 | 現行通用版本是 V3, |
序號 | 用來識別每一張證書,用來追蹤和撤銷證書。只要擁有簽發者信息和序列號,就可以唯一標識一個證書,最大不能過20個字節;由CA來維護 |
主體 | 擁有此證書的法人或自然人身份或機器,包括: 國家(C,Country) 州/省(S,State)** 地域/城市(L,Location) 組織/單位(O,Organization) 通用名稱(CN,Common Name):在TLS應用上,此字段一般是域名 |
發行者 | 以數字簽名形式簽署此證書的數字證書認證機構 |
有效期(Validity) | 此證書的有效開始時間,在此前該證書並未生效;此證書的有效結束時間,在此后該證書作廢。 |
公開密鑰用途 | 指定證書上公鑰的用途,例如數字簽名、服務器驗證、客戶端驗證等 |
公開密鑰 | |
公開密鑰指紋 | |
數字簽名 | 使用信任的CA對內容進行 |
主體別名 | 例如一個網站可能會有多個域名(www.jd.com www.360buy.com..) 一個組織可能會有多個網站(*.baidu.com tieba.baidu.com), 不同的網域可以一並使用同一張證書,方便實現應用及管理。 |
互聯網上任意雙方之間實現通信時,證書的目的有兩種,
- 主機證書,主要實現主機與主機之間進程間通信的。
- 個人證書,主要用作個人通信的,主要用作加密的數據的發送。
主機類證書所擁有的標識主要為主機名
,主機證書名稱一定要與互聯網之上訪問名稱一致,否則此證書為不可信證書。
數字證書文件格式
X.509
一般推薦使用PEM
(Privacy Enhanced Mail)格式來存儲證書相關的文件。
.crt
& .cer
:證書文件后綴名
.key
: 私鑰后綴名
.csr
:證書請求文件后綴名
公鑰基礎設施(PKI)
公鑰基礎設施 PKI(Public-Key infrastructure)是為了能夠更有效地運用公鑰而制定的一系列規范和規格的總稱。
PKI的組成要素
- 用戶:使用PKI的人
- 注冊公鑰用戶。
- 使用已注冊公鑰用戶。
- 認證機構:
- 簽證機構:CA Certificate Authority
- 注冊機構:RA
- 倉庫
- 證書吊銷列表:CRL;證書存取庫,從簽發機構中獲得其簽發的證書,需要有存取庫來提供這些證書。
SSL/TLS
傳輸層安全協議,TLS,(Transport Layer Security),其前身為安全套接層 SSL(Secure Sockets Layer)。SSL3.0為SSL最高版本,3.1 即TLS 1.0
SSL/TLS是世界上應用最廣泛的密碼通信方法。比如說,當在網上商城中輸人信用卡號時,我們的Web瀏覽器就會使用SSL/TLS進行密碼通信。使用SSL/TLS可以對通信對象進行認證,還可以確保通信內容的機密性。
協議 | 時間 | 狀態 |
---|---|---|
SSL 1.0 | 未公布 | 未公布 |
SSL 2.0 | 1995年 | 已於2011年棄用 |
SSL 3.0 | 1996年 | 已於2015年棄用 |
TLS 1.0 | 1999年 | |
TLS 1.1 | 2006年 | |
TLS 1.2 | 2008年 | |
TLS 1.3 | 2018年 |
http協議本身為文本格式,數據發送做文本編碼;https協議實現的是二進制格式,數據發送做文本編碼。由於ssl的存在,雙方在實現通訊時,除了tcp協議三次 握手之外,雙方還需做ssl握手會話的過程(認證密鑰證書、數據交換等)。ssl會話的建立只能基於IP地址,無法基於主機名識別每一個通信方。一個IP地址在某個應用協議上只能建立一個ssl會話。
TLS采用了分層設計,雖然在TCP/IP協議棧上,SSL增加的半層,其內部實現為多層
- 最底層,基礎算法原語的實現,aes,rsa,md5
- 向上一層,選定參數后,符合密碼學標准分類的算法的實現
- aes-128-abc-pkcs7 abc內部塊的串聯方式 pkcs7 對稱加密公鑰格式。
- 再向上一層:組合算法實現的半成品。
- 用各種組件拼裝而成的種種成品密碼學協議/軟件 tls ssh。 openssh是利用openssl工具實現的軟件程序。
OpenSSL
OpenSSL是一個開放源代碼的軟件庫,並實現了SSL與TLS協議。OpenSSL可以運行在,MS Windows、Linux、MacOS。OpenSSL已經成為linux基礎公共組件,主要由三個開源組件組成:
openssl
:多用途的命令行工具,能實現對稱加密、非對稱加密、單項加密等。各功能分別使用單獨子命令來實現。libcrypto
:公共加密庫,實現了多種加密算法。libssl
:實現了SSL及TLS的功能庫
OpenSSL命令
OpenSSL命令分為 標准命令Standard commands
、消息摘要命令Message Digest commands
、密碼命令Cipher commands
三部分組成。
- 標准命令。完成某些功能時使用的,如生成隨機數、扮演CA簽發證書。
- enc 對稱加密
- crl 證書吊銷列表
- ca 證書簽發機構
- dgst 消息摘要算法(單項散列函數)
- dh 密鑰交換算法
- req 請求證書生成器
- 消息摘要命令算法,常用散列函數。
- 加密命令,所支持的加密算法。
OpenSSL 命令使用
對稱加密
加密
openssl enc -e -des3 -a -salt -in /etc/passwd -out ./passwd
解密
openssl enc -d -des3 -a -salt -in passwd
-d
解密-e
加密-a
base64編碼處理數據
單項加密
openssl中,單項加密即數字簽名計算message的摘要信息,為 openssl dgst...
單項散列函數通常應用於數字簽名於消息認證碼(MAC: Message Authentication Code 消息認證碼,單項加密的一種延申應用,用於實現再網絡通信中保證所傳輸的數據的完整性。)
[root@node01 ~]# openssl dgst -md5 /var/log/messages
MD5(/var/log/messages)= 4515fae68552c00646ee7e07aac25d1d
也可以簡寫為
[root@node01 ~]# openssl md5 /var/log/messages
MD5(/var/log/messages)= 24483320e6af7ed2cee401aa00c260e6
openssl也可以生成用戶密碼 sslpasswd
[root@localhost ~]# openssl passwd -1 -salt 123456
Password:
$1$123456$wWKtx7yY/RnLiPN.KaX.z.
$1$123456$wWKtx7yY/RnLiPN.KaX.z.
這是擴展Unix風格的crypt(3)
密碼哈希語法。格式為 $id$salt$encrypted
前$id$
符表示加密算法 1標識md5 6標識SHA-512
,123456是指定的salt,salt為id后的最多16位的對密碼加鹽。
Reference
crypt
unix style encrypted
使用openssl生成隨機數
hex基於16進制編碼格式 每個字節4位,4指的是4個字節,一個字節是8位二進制數。4位二進制可以用一個16進制字節標識(一個十六進制對應四個二進制 \(4*4=16\)) 出現字符 num*2
[root@localhost ~]# openssl rand -hex 16
8cd7c7a85e22b4548f6942468028fde4
[root@localhost ~]# openssl rand -base64 6
c0jDwKIG
使用OpenSSL生成自簽數字證書
獲取證書兩種方法:
- 使用證書授權機構
- 生成簽名請求(csr)
- 將csr發送給CA
- 從CA處接收簽名
- 自簽名的證書:自已簽發自己的公鑰
1. 建立RootCA
生成私鑰
參數 | 說明 |
---|---|
-new | 表示生成一個新證書簽署請求 |
-x509 | 專用於CA生成自簽證書,如果不是自簽證書則不需要此項 |
-key | 生成請求時用到的私鑰文件 |
-out | 證書的保存路徑 |
-days | 證書的有效期限,單位是day(天),默認是365天 |
cd /etc/pki/tls/
openssl genrsa -out private/cakey.pem 2048
# 路徑和名稱必須為openssl配置文件中路徑的名稱
2 自簽名證書
openssl req -new \
-x509 \
-key private/cakey.pem \
-out cacert.pem \
-days 3650 \
-subj "/C=HK/ST=HK/L=HK/O=chinamobile/OU=SY/CN=CHINA MOBILE"
自簽名證書是base64編碼的,查看證書內容
openssl x509 -in cacert.pem -noout -text
參數 | 說明 |
---|---|
x509 | 格式 |
-noout | 輸出時不生成新文件,只顯示內容 |
-text | 以文本格式輸出 |
數字證書中主題(Subject)中字段的含義
- 一般的數字證書產品的主題通常含有如下字段:
字段名 | 說明 |
---|---|
公用名稱 CN (Common Name) | 對於 SSL 證書,一般為網站域名;而對於代碼簽名證書則為申請單位名稱;而對於客戶端證書則為證書申請者的姓名; |
單位名稱 O (Organization Name) | 對於 SSL 證書,一般為網站域名;而對於代碼簽名證書則為申請單位名稱;而對於客戶端單位證書則為證書申請者所在單位名稱; |
OU | 可以理解為公司部門名稱 |
所在城市 L (Locality) | |
所在省份 ST(State/Provice) | |
所在國家 C (Country) |
可以看到生成了一個Chinamobile的自簽的RootCA
用戶或組織向CA申請公鑰(證書)
- 生成私鑰
mkdir child
openssl genrsa -out child/child.pem 2048
- 生成證書申請文件
child.csr
openssl req -new \
-key child/child.pem \
-out child/child.csr \
-subj "/C=HK/ST=HK/L=HK/O=chinamobile/OU=SY/CN=*.10086.com"
- 將證書申請文件發送給CA
可以通過任意方式發送申請文件給CA
CA頒發證書
touch /etc/pki/CA/index.txt
touch /etc/pki/CA/serial # 下一個要頒發的編號 16進制
touch /etc/pki/CA/crlnumber
echo 01 > /etc/pki/CA/serial
openssl ca -in child/child.csr \ # 簽發請求
-cert cacert.pem \ # CA證書
-keyfile private/cakey.pem \ # CA私鑰
-out child/a.crt -days 30
證書發送給客戶端
在應用軟件中使用證書
OpenSSL配置文件注釋
/etc/pki/tls/openssl.cnf
定義了管理CA的相關信息。
# 語法
# 變量 = 值
# 1. 字符串值最好使用雙引號界定,並且其中可以使用"\n","\r","\t","\\"這些轉義序列。
# 2. 可以使用 ${變量名} 的形式引用同一字段中的變量,使用 ${字段名::變量名} 的形式引用其它字段中的變量。
# 3. 可以使用 ${ENV::環境變量} 的形式引用操作系統中定義的環境變量,若變量不存在則會導致錯誤。
# 4. 可以在默認字段定義與操作系統環境變量同名的變量作為默認值來避免環境變量不存在導致的錯誤。
# 5. 如果在同一字段內有多個相同名稱的變量,那么后面的值將覆蓋前面的值。
# 6. 可以通過 ".include = 絕對路徑" 語法或 OPENSSL_CONF_INCLUDE 環境變量引入其他配置文件(*.cnf)。
# 定義 HOME 的默認值,防止操作系統中不存在 HOME 環境變量。
HOME = .
# 默認的隨機數種子文件,對應 -rand 命令行選項。
RANDFILE = $ENV::HOME/.rnd
# 擴展對象定義
# 如果沒有在 OpenSSL 命令行中定義X.509證書的擴展項,那么就會從下面對擴展對象的定義中獲取。
# 定義方法有兩種,第一種(反對使用)是存儲在外部文件中,也就是這里"oid_file"變量定義的文件。
#oid_file = $ENV::HOME/.oid
# 第二種是存儲在配置文件的一個字段中,也就是這里"oid_section"變量值所指定的字段。
oid_section = new_oids
# 要將此配置文件用於 "openssl x509" 命令的 "-extfile" 選項,
# 請在此指定包含 X.509v3 擴展的小節名稱
#extensions =
# 或者使用一個默認字段中僅包含 X.509v3 擴展的配置文件
[ new_oids ]
# 添加可以被 'ca', 'req', 'ts' 命令使用的擴展對象。格式如下:
# 對象簡稱 = 對象數字ID
# 下面是一些增強型密鑰用法(extendedKeyUsage)的例子
# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.
# Add a simple OID like this:
# testoid1=1.2.3.4
# Or use config file substitution like this:
# testoid2=${testoid1}.5.6
# Policies used by the TSA examples.
tsa_policy1 = 1.2.3.4.1
tsa_policy2 = 1.2.3.4.5.6
tsa_policy3 = 1.2.3.4.5.7
########################################################################################
################################### 證書簽發配置 ######################################
########################################################################################
# openssl 的 ca 命令實現了證書簽發的功能,其相關選項的默認值就來自於這里的設置。
# 這個字段只是通過唯一的 default_ca 變量來指定默認CA主配置字段的入口(-name 命令行選項的默認值)
########################################################################################
######################## 默認CA主配置字段,(★)標記表示必需項 #############################
########################################################################################
[ ca ] #
default_ca = CA_default # The default ca section # 默認CA
########################################################################################
######################### 默認CA主配置字段,(★)標記表示必需項 ############################
########################################################################################
[ CA_default ]
# 保存所有信息的文件夾,這個變量只是為了給后面的變量使用
dir = /etc/pki/CA
# (★)存放新簽發證書的默認目錄,證書名就是該證書的系列號,后綴是.pem 。對應 -outdir 命令行選項。
certs = $dir/certs
# 存放證書吊銷列表的
crl_dir = $dir/crl
# 數據庫,頒發了那些證書,以及證書狀態、編號。 數據索引。默認不存在的
database = $dir/index.txt
#unique_subject = no
#(★)存放新簽發證書的默認目錄,證書名就是該證書的系列號,后綴是.pem 。對應 -outdir 命令行選項。
new_certs_dir = $dir/newcerts # default place for new certs. # 新證書目錄
#(★)存放CA自身證書的文件名。對應 -cert 命令行選項。
certificate = $dir/cacert.pem
#(★)簽發證書時使用的序列號文本文件,里面必須包含下一個可用的16進制數字。。需手工創建
serial = $dir/serial
# 存放當前(下一個吊銷證書編號)CRL編號的文件,需手工創建
crlnumber = $dir/crlnumber
# 證書吊銷列表
crl = $dir/crl.pem
#(★)存放CA自身私鑰的文件名。對應 -keyfile 命令行選項。
private_key = $dir/private/cakey.pem
# 私鑰文件路徑
RANDFILE = $dir/private/.rand
# 定義X.509證書擴展項的字段。對應 -extensions 命令行選項。
x509_extensions = usr_cert
# 當用戶需要確認簽發證書時可讀證書DN域的顯示格式。可用值與 x509 指令的 -nameopt 選項相同。
name_opt = ca_default # Subject Name options
# 可用值與 x509 指令的 -certopt 選項相同,不過 no_signame 和 no_sigdump 總被默認設置。
cert_opt = ca_default # Certificate field options
# 是否將證書請求中的擴展項信息加入到證書擴展項中去。取值范圍以及解釋:
## none: 忽略所有證書請求中的擴展項
## copy: 將證書擴展項中沒有的項目復制到證書中
## copyall: 將所有證書請求中的擴展項都復制過去,並且覆蓋證書擴展項中原來已經存在的值。
## 此選項的主要用途是允許證書請求提供例如 subjectAltName 之類擴展的值。
# copy_extensions = copy
# 定義生成CRL時需要加入的擴展項字段。對應 -crlexts 命令行選項。
# crl_extensions = crl_ext
# 新簽發的證書默認有效期,以天為單位。依次對應 -days , -startdate , -enddate 命令行選項。
default_days = 365 # 頒發證書默認有效期
# crl的有效期 30天
default_crl_days= 30
# 默認hash算法
default_md = sha256
preserve = no # keep passed DN ordering
#(★)定義用於證書請求DN域匹配策略的字段,用於決定CA要求和處理證書請求提供的DN域的各個參數值的規則。
# 策略匹配 ,客戶端與ca之間區申請證書信息是否必須匹配,對應 -policy 命令行選項。
policy = policy_match
########################################################################################
################################ 為簽發的證書設置擴展項 ##################################
########################################################################################
# 變量名稱是DN域對象的名稱,變量值可以是:
# match: 該變量在證書請求中的值必須與CA證書相應的變量值完全相同,否則拒簽。
# supplied: 該變量在證書請求中必須提供(值可以不同),否則拒簽。
# optional: 該變量在證書請求中可以存在也可以不存在(相當於沒有要求)。
# 除非preserve=yes或者在ca命令中使用了-preserveDN,否則在簽發證書時將刪除匹配策略中未提及的對象。
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
########################################################################################
############## "特征名稱"字段包含了用戶的標識信息,對應 -subj 命令行選項 ###################
########################################################################################
[ req_distinguished_name ]
countryName = CN # 必須是兩字母國家代碼
stateOrProvinceName = # 省份或直轄市
localityName = # 城市
organizationName = # 組織名或公司名
organizationalUnitName = # 部門名稱
commonName = # 全限定域名或個人姓名
emailAddress = # Email地址
########################################################################################
################################# 為簽發的證書設置擴展項 #################################
########################################################################################
[ extendtsion_name ]
# 基本約束(該證書是否為CA證書)。"CA:FALSE"表示非CA證書(不能簽發其他證書的"葉子證書")。
basicConstraints = CA:FALSE
# 頒發機構密鑰標識符("always"表示始終包含)
authorityKeyIdentifier = keyid:always,issuer
# PKIX工作組推薦將使用者與頒發機構的密鑰標識符包含在證書中
subjectKeyIdentifier=hash
# 證書用途,如省略,則可以用於簽名外的任何。
# server SSL服務器
# objsign 簽名證書
# client 客戶端
# email 電子郵件
nsCertType = client
# Netscape Comment(nsComment)是包含注釋的字符串擴展名,當在某些瀏覽器中查看證書時,該注釋將顯示。
nsComment = "OpenSSL Generated Client Certificate"
# 密鑰用法:防否認(nonRepudiation)、數字簽名(digitalSignature)、密鑰加密(keyEncipherment)。
# 密鑰協商(keyAgreement)、數據加密(dataEncipherment)、僅加密(encipherOnly)、僅解密(decipherOnly)
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
# 增強型密鑰用法(參見"new_oids"字段):服務器身份驗證、客戶端身份驗證、時間戳。
extendedKeyUsage = critical,serverAuth, clientAuth, timeStamping
# 使用者備用名稱(email, URI, DNS, RID, IP, dirName)
# 例如,DNS常用於實現泛域名證書、IP常用於綁定特定的IP地址、"copy"表示直接復制
subjectAltName = DNS:www.example.com, DNS:*.example.net, IP:192.168.7.1, IP:13::17
OpenSSL擴展密鑰用法:生成多域名證書
SAN(Subject Alternative Name) 是 SSL/TLS
標准 x.509
中定義的一個擴展。使用了SAN字段的 SSL 證書,可以擴展此證書支持的域名,使一個證書可支持多個不同域名的解析。RFC 5280 4.2.1.6
可以看到面子書與京東的證書的 Subject Alternative Name
段中列了大量的域名,使用這種類型的證書能夠極大的簡化網站證書的管理
使用OpenSSL生成根CA
cd /etc/pki/tls/
openssl genrsa -out private/cakey.pem 2048
openssl req -new \
-x509 \
-key private/cakey.pem \
-out cacert.pem \
-days 3650 \
-subj "/C=HK/ST=HK/L=HK/O=chinamobile/OU=SY/CN=CHINA MOBILE"
准備openssl配置文件
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectKeyIdentifier=hash
authorityKeyIdentifier = keyid:always,issuer
nsComment = "OpenSSL Generated Client Certificate"
subjectAltName = DNS:etcd, DNS:hk-etcd, IP:10.0.0.1
nsCertType = client, server
可以看到此證書請求文件中會包含 Subject Alternative Names
字段,並包含之前在配置文件中填寫的域名。
使用 openssl 簽署帶有 SAN 擴展的證書請求csr
- 生成私鑰
mkdir child
openssl genrsa -out child/child.pem 2048
- 生成證書申請文件
child.csr
openssl req -new \
-key child/child.pem \
-out child/child.csr \
-subj "/C=HK/ST=HK/L=HK/O=chinamobile/OU=SY/CN=hketcd" \
-config ./openssl.cnf
單條命令實現方式
openssl req -new \
-key child/child.pem \
-subj "/C=HK/ST=HK/L=HK/O=chinamobile/OU=SY/CN=hketcd" \
-reqexts req_v3 \
-config <(cat /etc/pki/tls/openssl.cnf
<(printf "[aa]\nsubjectAltName=DNS:etcd, DNS:hk-etcd, IP:10.0.0.1")) \
-out child/a.crt
- CA頒發證書
單條命令實現
openssl ca \
-in child/child.csr \
-cert cacert.pem \
-keyfile private/cakey.pem \
-out child/a.crt \
-days 30 \
-extensions aa
-extfile <(cat /etc/pki/tls/openssl.cnf \
<(printf "[aa]\nsubjectAltName=DNS:etcd, DNS:hk-etcd, IP:10.0.0.1"))