1. 程式人生 > 實用技巧 >openssl原理與實戰

openssl原理與實戰

第1章 openssl

1.1 元件

a、libcrypto,libssl主要由開發者使用
b、openssl:多用途命令列工具
[root@shiyanji ~]# openssl version
OpenSSL 1.0.2k-fips  26 Jan 2017

1.2 命令

a、眾多子命令,大體分為三類,可用openssl ? 來顯示
   1)標準命令(Standard commands):每一個命令都使用命令自身來呼叫
  2)訊息摘要命令(Message Digest commands):使用dgst命令來呼叫
   3)加密命令(Cipher commands):使用enc命令來呼叫
b、標準命令:enc,ca,req,genrsa,...

1.3 基於openssl完成對稱加密

a、工具:openssl enc,gpg等
b、支援的演算法:3des,aes,blowflsh,towflsh
c、enc命令,可以使用whatis enc命令檢視
[root@shiyanji ~]#  whatis enc
enc (1ssl)           - symmetric cipher routines
(1)加密/etc/fstable檔案中的內容
  [root@shiyanji ~]# openssl enc -e -des3 -a -salt -in /etc/fstab -out fstab.ciphertext
  enter des-ede3-cbc encryption password:
  Verifying - enter des-ede3-cbc encryption password:
解釋
上述命令的意思是使用openssl enc命令,
-e: 表示進行加密(如果解密需要-d引數)
-des3: 表示使用des3演算法進行加密
-a: 表示使用base64的編碼格式,文字編碼,即編碼為文字,看上去就是一大推亂碼,如果不加-a就表示預設使用二進位制編碼。
-salt: 表示加一些雜誌進去,至於要怎麼加不用管。
-in /etc/fstab: 表示加密/etc/fstab檔案中的內容
-out fstab.ciphertext: 表示加密後的檔案儲存在fstab.ciphertext檔案中,接下來會讓輸入密碼,可以看到他是用des-ede3-cbc進行加密的
  a. 接下來檢視這個檔案
[root@shiyanji ~]# cat fstab.ciphertext 
U2FsdGVkX1/t8hNBuwrEGag7xNzQZflgEjA/nsbJRMQ80dgcwKf6RREo9TEYRhWl
wuvfHpkdJHj11XZ/YAnoSexL0U2xhLACHUIcwrlypj7ENjfoMh9FiG2aqlksNVEv
w7wkZzH29bYCPWOJgUpexfR6efH0WjZH+HQh2cSnsr81Omn3i/CX7QORswRLZG/C
jPyJtM5087ET3BuoYoVP1LIu5kQbG7mUOlH5aiQIcWC0Yylem1lBOJ7lXRyQCz/E
vfXSbhphoo9mNfqnA2OCSZ94d7rWg1zL2PdElZi26azfC2WcKvLhG0bTgudCkWks
DKtLAjHTy63Xr35LXUJlQdNkDrSi20geOF04mlyrAdIdb8bEjrB33068GfTFkvzV
kqVerMJY/ZiRUC1NIptmUvKUufhCTMCPtDX4QRQi1hG+fwYDdKiqjoWSjDlXI7NP
KGEkY98KFRxrDgsJNcY1xHuvfx2H4dMvcK67+b77jcQYxdavCw6oEXdHXuAyDRw0
nknHgyc3HiYCXzTVEijJrv5Ir65QSzctGEXIRv5snTlaQ0GkjVAelrBvBpMv1twX
JbynYIkChoIVEbmgUhx9/lBx8Qngz9oNm35za2FWfGDeQQE2td9QakltRcSsIjjg
wpwWpcON+zES0FC2FdzqUVVx1vm1kLExxe0qppBzYRjUOs0JGaJnZw==
(2) 接下來來解密這個檔案,解密和剛剛過程一樣,只是把-e換成-d,-in和-out對調
[root@shiyanji ~]# ls
anaconda-ks.cfg  bianyi  fstab.ciphertext
[root@shiyanji ~]# openssl enc -d -des3 -a -salt -in ./fstab.ciphertext -out ./fstab
enter des-ede3-cbc decryption password:
[root@shiyanji ~]# ls
anaconda-ks.cfg  bianyi  fstab  fstab.ciphertext
[root@shiyanji ~]# cat fstab

#
# /etc/fstab
# Created by anaconda on Sat Mar  7 13:05:16 2020
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
UUID=ac6edd9a-8b57-4b20-b1d8-e819dcf0bbaf /                       xfs     defaults        0 0
UUID=fb4ef11d-89e8-462b-822f-cd367570413b /boot                   xfs     defaults        0 0
UUID=1b710427-4470-468c-9eac-bb37aad84c3c swap                    swap    defaults        0 0

1.4 基於openssl完成單向加密

a、工具:openssl dgst,md5sum,sha1sum,sha224sum,...
b、dgst命令:openssl dgst -md5 /PATH/TO/SOMEFILE
[root@shiyanji ~]# ls
anaconda-ks.cfg  bianyi  fstab  fstab.ciphertext
計算檔案特徵碼
[root@shiyanji ~]# md5sum fstab
68e9ea4409f367ccb5f4444ab65dd806  fstab
用openssl計算特徵碼
[root@shiyanji ~]# openssl dgst -md5 fstab
MD5(fstab)= 68e9ea4409f367ccb5f4444ab65dd806
可以看到,輸出的方式雖然不一樣,但是計算出來的特徵碼是一樣的,因為都是用的md5演算法

1.5 公鑰加密

a、加密
  1)演算法:RSA,ELGamal
  2)工具:openssl rsautl,gpg
b、數字簽名
  1)演算法:RSA,DSA,ELGamal
  2)工具:openssl rsautl,gpg
c、金鑰交換
  1)演算法:DH,RSA也支援

1.6 生成金鑰

(1) 生成私鑰:要想完成公鑰加密技術加密資料首先我們要生成金鑰對,如果去獲取金鑰對就變得比較關鍵了
             openssl 有個子命令叫openssl genrsa或openssl gendsa,可以通過openssl genrsa指明要生成多少位的金鑰,他的金鑰位數支援 
             512,768,1024,2048,4096等,必須是2的n次方倍的位數。所以只能是上述的這種位數
       (umask 077;openssl genrsa -out /PATH/TO/PRIVATE_KEY_FILE NUM_BITS)
1)生成一個1024位的金鑰
[root@shiyanji ~]# openssl genrsa 1024
Generating RSA private key, 1024 bit long modulus
......................++++++
..............................++++++
e is 65537 (0x10001)
-----BEGIN RSA PRIVATE KEY-----
MIICXwIBAAKBgQDkCASx2V9ZKFhKHvSXdyLBdKwLPdNgbCUSptfI8+tsEjBHXkPH
9lu4B4DgK9WgOLARlgDnhVeI1IiqyweOTD6LlOkhu7AjGIfh4o/a09Kf42DzAOvJ
LI5LRRsZA7eGOTLr/mMDbH5LwzB53lvuhf/09zDKRFtO8FqfWZ3CZUTxhwIDAQAB
AoGBAJyFqHtPovQ3Dktqbifdvfyekk1xFbuU3+mqnmmwjIN1BLCoUsxaHWD3vY2i
aRN+ddTMaziAPbKNeHYLwNb7HN41FQXEv18GDREmNkJ+NeeKLsIebox921aNJsn5
NRExX5GhlMdbxlripBeNgy4l9xuiFEIGrKOxka62kJ5JtKLZAkEA9GZjQGBN3mRL
4a9otF2mNZ9oyT/Rk9UCozyAA/uKPvVQG5IpQQmGnC7S3s77Z1pMrO3cilAjbT3L
Cir3hvwajQJBAO7avdWRIVslIfjvjndMMlGRvE/3tM6lGhQyCnqcCiUiKv3IOa+6
i/ohCTHr1vvP9ZNZTGqFwj+eJShuNN5koWMCQQC93UDjxS0ZRO+ST3PXEx3JcKK2
HYcSApw+9gQ5k9NtX6QxFxZHeUAC23lkMIYsX4FLoqn/JYywFB5FMuYDDp0NAkEA
kfJs3ouAkz3cRUyzg6e2c2sWYtKb00zE46Q0DPk9pbT8CfgHb54QG/WFtdBCm7lV
eASvkcNLjy3lzI+SlHVuuwJBAKHTjM31+QOCLtyo5882Ei+LrbcDcsm9HZjsBIth
umoaRRGL7K20f2L/9Hoe3WWUQ9Km7faJIDqvuOeCl7niXAM=
-----END RSA PRIVATE KEY-----
可以看到,生成的是一個私鑰,公鑰是從私鑰中提取出來的。也可以將這個金鑰對儲存下來,可以通過輸出重定向或者-out引數
[root@shiyanji ~]#  openssl genrsa 1024 > /tmp/mykey.private
[root@shiyanji ~]# ls -l /tmp/mykey.private 
-rw-r--r-- 1 root root 887 Dec  6 15:02 /tmp/mykey.private
可以看到檔案所有使用者都是有讀許可權的,即私鑰能被其他人讀取,因此任何時候生成的私鑰都應該改為僅自己能讀能寫,因此可以通過這種方式來進行建立
[root@shiyanji ~]# (umask 077;openssl genrsa -out /tmp/mykey3.private 2048)
[root@shiyanji ~]# ls -l /tmp/mykey3.private 
-rw------- 1 root root 1679 Dec  6 15:03 /tmp/mykey3.private
可以看到通過這種方式創建出來的檔案許可權為600,即只有自己可以讀寫。
使用括號括起來表示在子shell中執行,在子shell中設定umask為077然後第二個命令也就受子shell影響了,等結束後回到主程序父shell umask是不變的
(2) 提出公鑰。一般不需要自己提,介紹方法
[root@shiyanji ~]# openssl rsa -in /tmp/mykey3.private -pubout -pubout
writing RSA key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4VLGe2jodB9ANDADYGld
rN31h8B0s/Qs/80oXcbPt+Sr0Q4sSpYWnSw1FlZNmN+JcYDS9IOQvbHFjWpy/UpV
wJ0GMQKKabo48M02SZeHpUHAlS48Kc3XGbvz75T8RPjff14lpZiNib8L0NmIA7ja
ATqVuDkYqxf0vlUYDnNyWCQ3bJgdqWpFxa5KAIUrxJ9xn/xyqtzAHyBNK5Z5VXir
GbWc++U41EkuaFUt2zu/JuP0456m4NgaPtJU5Ov7A4imA5c1pS5UEd0+qi2/IwYu
/I5BaCf0Ili8bihn5hE55hCDVxuKAv8p4BduukMZdeG77K0hXr9FpyYAUDeNYzUC
JQIDAQAB
-----END PUBLIC KEY-----

1.7 Linux系統上的隨機數生成器

不管是用的什麼演算法,都嚴重依賴隨機數
a、/dev/random:僅從熵池返回隨機數,隨機數用盡,阻塞
b、/dev/urandom:從熵池返回隨機數,隨機數用盡,會利用軟體生成偽隨機數,非阻塞。但是偽隨機數是不安全的
c、熵池中的隨機數來源:熵池就是執行中的核心在記憶體中維護的一段空間,這段空間中儲存了大量的隨機數,不過剛啟動時是空的。他的來源一般有兩種
 1)硬碟IO中斷時間間隔
 2)鍵盤IO中斷時間間隔,獲取隨機數的時候不是複製,而是剪下,如果取的隨機數多餘生成的隨機數隨機數就被耗盡了。
 3)所以隨機數取的時候被阻塞就猛著敲鍵盤,或者複製檔案,這種操作會有大量的磁碟IO

第2章 自建CA

2.1 概述

1、公共信任CA,私有CA
2、建立私有CA:
 a、openssl
 b、OpenCA:一個開源的CA工具,其實其底層也是用的opensll,只是使用起來更簡單了
3、openssl命令
 a、配置檔案 /etc/pki/tls/openssl.cnf。
     這個配置檔案中為openssl扮演一個CA管理工具提供了相關配置,可以在[ca]這個欄位中檢視

2.2 /etc/pki/tls/openssl.cnf解釋

[root@www openssl]# cat /etc/pki/tls/openssl.cnf |grep -Ev "^#|^$"|grep -wA22 ca
[ ca ]
default_ca    = CA_default        # The default ca section
[ CA_default ]
dir        = /etc/pki/CA         #Where everything is kept,即作為CA的預設工作目錄
certs        = $dir/certs        # Where the issued certs are kept,用來放簽發過的證書的位置
crl_dir        = $dir/crl        # Where the issued crl are kept,用來存放吊銷的證書
database    = $dir/index.txt     #database index file. #資料庫檔案,存放了已經頒發過的證書的索引
                    # several ctificates with same subject.
new_certs_dir    = $dir/newcerts     #default place for new certs.
certificate    = $dir/cacert.pem     #The CA certificate #CA的自簽證書
serial        = $dir/serial          #The current serial number #指明當前序列號碼,用來為當前主機上每一個證書提供序列號
crlnumber    = $dir/crlnumber        #the current crl number #為當前主機上每一個吊銷的證書提供序列號
                    # must be commented out to leave a V1 CRL
crl        = $dir/crl.pem            #The current CRL
private_key    = $dir/private/cakey.pem# The private key #指CA自己的私鑰
RANDFILE    = $dir/private/.rand     #private random number file
x509_extensions    = usr_cert        #The extentions to add to the cert
name_opt     = ca_default            #Subject Name options
cert_opt     = ca_default            #Certificate field options
default_days    = 365                #how long to certify for #證書的預設有效期
default_crl_days= 30                 #how long before next CRL 
default_md    = sha256               #use SHA-256 by default #預設訊息摘要演算法是sha256
preserve    = no                     #keep passed DN ordering
policy        = policy_match

2.2 構建私有CAb步驟

第一個里程:生成私鑰;預設放在/etc/pki/CA/private/目錄下

(umask 077;openssl genrsa -out /etc/pki/CA/private/cakey.pem 4096)
[root@shiyanji ~]# (umask 077;openssl genrsa -out /etc/pki/CA/private/cakey.pem 4096)
Generating RSA private key, 4096 bit long modulus
.........................++
......++
e is 65537 (0x10001)

第二個里程:生成自簽證書

[root@shiyanji ~]# openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/cacert.pem -days 3656 
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) [XX]:CN
State or Province Name (full name) []:Beijing
Locality Name (eg, city) [Default City]:Beijing
Organization Name (eg, company) [Default Company Ltd]:ceshi
Organizational Unit Name (eg, section) []:ops    
Common Name (eg, your name or your server's hostname) []:ca.ceshi.com
Email Address []:
[root@shiyanji ~]#  ll /etc/pki/CA/
total 4
-rw-r--r--  1 root root 2009 Dec  6 15:14 cacert.pem
drwxr-xr-x. 2 root root    6 Aug  9  2019 certs
drwxr-xr-x. 2 root root    6 Aug  9  2019 crl
drwxr-xr-x. 2 root root    6 Aug  9  2019 newcerts
drwx------. 2 root root   23 Dec  6 15:11 private
上述/etc/pki/CA/目錄下的其它目錄如果存在不用管它如果不存在需要手動建立
1)我們上述命令解釋如下:
-new:表示生成一個新請求
-x509:如果是自簽證書就需要加此引數
-key:表示私鑰在什麼地方(因為證書中的公鑰是在私鑰中提取的)
-out:指明證書儲存在什麼地方,/etc/pki/CA/目錄是固定位置
-days:指明證書的有效期限是多少天,預設是365天,這兒指明的是10年
2)需要輸入的內容
Country Name:兩個字元的國家程式碼,此處CN,即中國
State or Province Name:在哪個州,此處寫的Beijing
Locality Name:在哪個城市,此處寫的Beijing
Organization Name:公司名字,此處的是ceshi
Organizational Unit Name:部門名稱,此處寫的是運維部,即Ops
Common Name:證書持有者自己的人名或證書所在的伺服器的名字,
Email Address:管理員郵箱,

第三個里程:為CA提供所需的目錄及檔案

1)建立目錄
mkdir /etc/pki/CA/{certs,crl,newcerts}
2)建立檔案
touch /etc/pki/CA/{serial,index.txt}
[root@shiyanji ~]# ll /etc/pki/CA/
total 4
-rw-r--r--  1 root root 2009 Dec  6 15:14 cacert.pem
drwxr-xr-x. 2 root root    6 Aug  9  2019 certs
drwxr-xr-x  2 root root    6 Dec  6 15:18 {certs,crl,newcerts}
drwxr-xr-x. 2 root root    6 Aug  9  2019 crl
-rw-r--r--  1 root root    0 Dec  6 15:19 index.txt
drwxr-xr-x. 2 root root    6 Aug  9  2019 newcerts
drwx------. 2 root root   23 Dec  6 15:11 private
-rw-r--r--  1 root root    0 Dec  6 15:19 serial
3)serial檔案不能為空因此可以重定向一個數據進去
echo 01 > /etc/pki/CA/serial

第四個里程:要用到證書進行安全通訊的伺服器,需要向CA請求籤署證書

a. 步驟
1)這個步驟需要在要用到證書進行安全通訊的伺服器上面,
 假如現在有一臺伺服器node2中有httpd服務,然後進入到相應的httpd目錄中建立ssl目錄,在目錄中生成相應的私鑰和對應的證書籤署請求
並將公鑰發給CA伺服器www請求證書
1)建立相應的資料夾
[root@node2 ~]# mkdir /etc/httpd/conf/ssl
[root@node2 ~]# cd /etc/httpd/conf/ssl
[root@node2 ssl]# ls
2)生成私鑰
[root@node2 ssl]# (umask 077;openssl genrsa -out /etc/httpd/conf/ssl/httpd.key 2048)
Generating RSA private key, 2048 bit long modulus
...................................................+++
............................................+++
e is 65537 (0x10001)
[root@node2 ssl]# ll
total 4
-rw------- 1 root root 1679 Apr 20 05:34 httpd.key
3)生成證書籤署請求
[root@node2 ssl]# openssl req -new -key /etc/httpd/conf/ssl/httpd.key -out /etc/httpd/conf/ssl/httpd.csr -days 365 
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) [XX]:CN
State or Province Name (full name) []:Beijing
Locality Name (eg, city) [Default City]:Beijing
Organization Name (eg, company) [Default Company Ltd]:wohaoshuai
Organizational Unit Name (eg, section) []:Ops
Common Name (eg, your name or your server's hostname) []:www.ceshi.com
Email Address []:[email protected]

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
上述-out 引數後的/etc/httpd/ssl/httpd.csr檔案即為簽署請求
下面讓輸入的內容中www.ceshi.com這個內容一般是網際網路訪問主機的域名,訪問時也必須嚴格按照此名字否則證書不通過
最後兩行的密碼敲enter即可
4)然後把httpd.csr這個證書籤署請求發給CA伺服器www讓其給簽署一下,下面是www伺服器的操作
首先拷貝node2伺服器上的證書籤署請求 
[root@www /]# scp [email protected]:/etc/httpd/conf/ssl/httpd.csr /application/
[email protected]'s password: 
httpd.csr                      
[root@www /]# ll /application/httpd.csr
-rw-r--r-- 1 root root 1066 4月  20 05:45 /application/httpd.csr
然後開始簽署 
root@www /]# openssl ca -in /application/httpd.csr -out /etc/pki/CA/certs/httpd.crt -days 365
Using configuration from /etc/pki/tls/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1)
        Validity
            Not Before: Apr 19 21:49:21 2020 GMT
            Not After : Apr 19 21:49:21 2021 GMT
        Subject:
            countryName               = CN
            stateOrProvinceName       = Beijing
            organizationName          = wohaoshuai
            organizationalUnitName    = Ops
            commonName                = www.wohaoshuai.com
            emailAddress              = [email protected]
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            Netscape Comment: 
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier: 
                A3:69:40:E3:BA:9A:31:C7:B4:83:D1:A9:E6:66:F1:4B:6B:3D:CB:66
            X509v3 Authority Key Identifier: 
                keyid:0F:8F:62:47:89:2E:2F:AD:3D:B0:FD:79:E9:C8:A7:57:B2:23:74:1C

Certificate is to be certified until Apr 19 21:49:21 2021 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
注意簽署後的證書是httpd.crt,開始證書籤署請求的名字是httpd.crs。後面兩個詢問是問你籤不籤,並且確認籤不籤,輸入y即可
然後來看此時的database檔案
[root@www /]# cat /etc/pki/CA/index.txt
V    210419214921Z        01    unknown    /C=CN/ST=Beijing/O=wohaoshuai/OU=Ops/CN=www.ceshi.com/[email protected]
V表示已經簽過的。01是序列號,最後這一段是subject,是主題資訊,也叫主題標識
5)然後把簽好了的證書傳送給node2
[root@www /]# scp /etc/pki/CA/certs/httpd.crt [email protected]:/etc/httpd/conf/ssl/
[email protected]'s password: 
httpd.crt    
b、總結(以httpd為例)
1)用到證書的主機生成私鑰
mkdir /etc/httpd/conf/ssl
cd /etc/httpd/conf/ssl
(umask 077;openssl genrsa -out /etc/httpd/conf/ssl/httpd.key 2048)
2)生成證書籤署請求
openssl req -new -key /etc/httpd/conf/ssl/httpd.key -out /etc/httpd/conf/ssl/httpd.csr -days 365
3)將請求通過可靠方式傳送給CA主機
scp [email protected]:/etc/httpd/conf/ssl/httpd.csr /application/
4)在CA主機上籤署證書
openssl ca -in /application/httpd.csr -out /etc/pki/CA/certs/httpd.crt -days 365
   1) 檢視證書中的資訊,可以通過引數檢視相應的欄位內容,此處只檢視序列號和subject資訊 
      [root@node2 ssl]# openssl x509 -in httpd.crt -noout -serial -subject
      serial=01
      subject= /C=CN/ST=Beijing/O=ceshi/OU=Ops/CN=www.ceshi.com/[email protected]

吊銷證書

a、步驟
1)客戶端獲取要吊銷的證書的serial(在使用證書的主機上執行);
[root@node2 ssl]# openssl x509 -in httpd.crt -noout -serial -subject
serial=01
subject= /C=CN/ST=Beijing/O=wohaoshuai/OU=Ops/CN=www.wohaoshuai.com/[email protected]
2)在CA上執行,CA主機吊銷證書
  1)先根據客戶端提交的serial和subject資訊,對比本機資料庫index.txt中儲存的是否一致
  2)吊銷
      [root@www /]# openssl ca -revoke /etc/pki/CA/newcerts/01.pem
      其中的01.pem即serial.pem,也就是相應httpd.crt證書的序列號,證書建立時該序列號就有了
  3)生成吊銷證書的吊銷編號(第一次吊銷證書時執行)
   echo 01 > /etc/pki/CA/crinumber
  4)更新證書吊銷列表
   openssl ca -gencrl -out thisca.crl
  5)檢視crl檔案
   openssl crl -in /PATH/FROM/CRL_FILE.crl -noout -text