需要注意的是,接下来的编译,安装都将支持TLS1.3协议,由于TLS1.3目前还未完全成熟,因此需要我们进行额外的编译操作来使系统支持。
#查看openssl的版本信息
pi@raspberrypi:~ $ openssl version
OpenSSL 1.0.1t 3 May 2016
# 卸载系统自带的openssl,避免链接冲突问题。
sudo apt-get remove openssl
wget https://www.openssl.org/source/openssl-1.1.1g.tar.gz
tar -xf openssl-1.1.1g.tar.gz
cd openssl-1.1.1g
./Configure # 在需要确定编译器环境的时候,请执行./config, 参阅Q&A
make
make install
查看openssl的最新版本信息, 查看openssl支持的加密套件,并确定是否支持 TLS1.3协议
pi@raspberrypi:/usr/local $ openssl version
OpenSSL 1.1.1g 21 Apr 2020
pi@raspberrypi:/usr/local $ openssl ciphers -V
0x13,0x02 - TLS_AES_256_GCM_SHA384 TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD
0x13,0x03 - TLS_CHACHA20_POLY1305_SHA256 TLSv1.3 Kx=any Au=any Enc=CHACHA20/POLY1305(256) Mac=AEAD
0x13,0x01 - TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD
0xC0,0x2C - ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD
0xC0,0x30 - ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA
对以上的输出做一下说明:
Kx 表示
密钥交换的加密算法(需要结合wireshark以及TLS协议进行流程分析,在TLS1.2中,主要是指RSA和DH密钥交换算法, 根据rfc5246中的描述,Kx等于any时,表示匿名密钥交换算法, 一般通过Diffie-Hellman来实现密钥交换。
,
Au表示身份认证算法,Enc表示通信数据的加密算法, Mac表示消息验证算法(计算消息摘要的算法)。
通过openssl 测试网站是否支持 TLS1.3 协议
openssl s_client -connect www.nike.com:443 -tls1_3
Notice: Configure脚本是用来生成Makefile的脚本,用于确定系统,编译器, 编译安装目录等等编译环境,便于适应多环境和平台, 类似CMake,其目的就是 用来构建工程项目框架,通过./Configure --help可以查看相关帮助信息。
报错的Log如下:
pi@raspberrypi:~/pkg_compile/openssl-1.1.1g $ ./Configure
Usage: Configure [no- …] [enable- …] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no[no-]zlib|zlib-dynamic] [no-asm] [no-egd] [sctp] [386] [–prefix=DIR] [–openssldir=OPENSSLDIR] [–with-xxx[=vvv]] [–config=FILE] os/lags]
pick os/compiler from:
BS2000-OSD BSD-generic32 BSD-generic64
NOTE: If in doubt, on Unix-ish systems use ‘./config’,
A: 解决办法,可以通过
./Configure CC=编译器绝对路径
来选择编译器,
也可以直接执行 ./config
脚本, 该脚本会帮忙确定当前系统的编译环境,然后执行./Configure脚本。
pi@raspberrypi:~/pkg_compile/openssl-1.1.1g $ ./config
Operating system: armv7l-whatever-linux2
Configuring OpenSSL version 1.1.1g (0x1010107fL) for linux-armv4
Using os-specific seed configuration
Creating configdata.pm
Creating Makefile
A: 在标准的lib库路径找不到库,需要执行
ln -s /usr/local/lib/libssl.so.1.1 /usr/lib/libssl.so.1.1
ln -s /usr/local/lib/libcrypto.so.1.1 /usr/lib/libcrypto.so.1.1
或者配置 LD_LIBRARY_PATH
的环境变量,来添加动态库的搜索路径。
通过官网的Change-log文件:https://nginx.org/en/CHANGES-1.16, 可以知道最新版本的nginx 默认支持TLS1.3协议。
Changes with nginx 1.15.6 06 Nov 2018
*) Security: when using HTTP/2 a client might cause excessive memory
consumption (CVE-2018-16843) and CPU usage (CVE-2018-16844).
*) Security: processing of a specially crafted mp4 file with the
ngx_http_mp4_module might result in worker process memory disclosure
(CVE-2018-16845).
*) Feature: the “proxy_socket_keepalive”, “fastcgi_socket_keepalive”,
“grpc_socket_keepalive”, “memcached_socket_keepalive”,
“scgi_socket_keepalive”, and “uwsgi_socket_keepalive” directives.
*) Bugfix: if nginx was built with OpenSSL 1.1.0 and used with OpenSSL
1.1.1, the TLS 1.3 protocol was always enabled.
编译相关的内容也可以查阅官网的Documention, 编译与安装的命令:
cd pkg-compile
wget https://netix.dl.sourceforge.net/project/pcre/pcre/8.40/pcre-8.40.tar.gz #需要支持perl工具
wget http://www.zlib.net/zlib-1.2.11.tar.gz #需要支持 zlib库
wget https://nginx.org/download/nginx-1.16.1.tar.gz
tar -xf nginx-1.16.1.tar.gz
tar -xf pcre-8.40.tar.gz
tar -xf zlib-1.2.11.tar.gz
./configure --sbin-path=/usr/local/nginx/nginx
--conf-path=/usr/local/nginx/nginx.conf
--pid-path=/usr/local/nginx/nginx.pid
--with-http_ssl_module
--with-pcre=../pcre-8.40
--with-zlib=../zlib-1.2.11
make
make install
vim /usr/local/nginx/nginx.conf
killall nginx
/usr/local/nginx/nginx -c nginx.conf
修改server 块中 server_name 为 eth0接口的ip地址。
server {
listen 80;
server_name 192.168.1.196;
…
}
也可以修改nginx文件下的html的indexl.html页面代码
<html>
<head>
<title>Welcome to Starry!title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
style>
head>
<body>
<h1>Welcome to Starry!h1>
<p> Fighting For Starry!p>
<p> Go! Go! Go!p>
<p><em>Thank you for your love.em>p>
body>
html>
Openssl官网手册: https://www.openssl.org/docs/man1.1.1/
openssl genrsa -out cert.key #1024
#如果生成ras密钥到ca.key, 并使用des3算法加密(之后每次使用该密钥,都要输入密码)
#openssl genrsa -des3 -out cert.key 1024
#这条命令会需要如下,需要额外输入密码,对私钥的进行加密。
#pi@raspberrypi:/usr/local/nginx/tls_file $ sudo openssl genrsa -des3 -out ca.key
#Generating RSA private key, 2048 bit long modulus (2 primes)
#..+++++
#......................+++++
#e is 65537 (0x010001)
#Enter pass phrase for ca.key:
#Verifying - Enter pass phrase for ca.key:
# openssl rsa -in cert.key -pubout -out pubkey.pem #通过rsa参数,可以生成公钥信息,rsa参数专门用于实现rsa算法相关操作。
######################################################################
# openssl中 rsautl 参数用于实现基于rsa的加密解密的相关扩展使用工具,
# 通过rsa工具,使用公钥加密文件
# openssl rsautl -encrypt -in input.file -inkey pubkey.pem -pubin -out output.file
# 通过rsa工具,使用私钥来解密文件
# openssl rsautl -decrypt -in input.file -inkey key.pem -out output.file
######################################################################
# 用私钥来生成基于509证书标准的证书请求(req参数), 这个证书请求将包含了公钥信息,但是要注意这里只是证书请求,不是证书。
# 因为接下来还需签名机构加密头部, 类似于盖章,认证合法性, 所以称之为 证书请求。
# -new 表示生成证书请求,
# -x509 表示 生成证书请求的同时,生成自签名证书
# Notice: 在生成证书请求的时候,将会包含公钥等信息, 但是缺乏签名。
openssl req -new -days 365 -key cert.key -out cert.csr
以上命令会输出以下信息, 由于后续的CA在验证时会被使用到,这边揪出来特别说明。
为何会知道这几个选项会被使用, 查看 cat /usr/local/ssl/openssl.cnf
的时候,就会发现
# For the CA policy
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
openssl在进行证书验证的时候, 需要签发机构的证书中 countryName,stateOrProvinceName,organizationName要和证书请求中的值匹配, commonName 作为服务器域名也一定要提供, 并且不能和CA证书中的值一样,否则,在CA校验的时候,因为common name一样,会被认为是自签名证书。
Ignoring -days; not generating a certificate
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) [AU]:CN 国家名称
State or Province Name (full name) [Some-State]:FJ 省份名称
Locality Name (eg, city) []:QZ 所属市区
Organization Name (eg, company) [Internet Widgits Pty Ltd]:walleva 组织名称
Organizational Unit Name (eg, section) []:96
Common Name (e.g. server FQDN or YOUR name) []: Starry 全限定域名:同时带有主机名和域名的名称,为持有者取名。
Email Address []:[email protected]
Please enter the following ‘extra’ attributes
to be sent with your certificate request
A challenge password []:96 挑战密码,用于安全需要的时候,会被拿出来使用,这是一个可选项
string is too short, it needs to be at least 4 bytes long
A challenge password []:9696
An optional company name []:
# 输出证书请求的细节信息, 可以看到公钥等相关信息。
openssl req -in cert.crt -noout -text
# 可以直接就生成请求的同时, 就立马生成自签名证书,不经过机构进行认证签名, 有效期为 365天,
# 该证书未经过签名机构的证书的签名, 无法导入CA机构的签名证书到浏览器中被得到校验,纯粹就TLS通信测试时使用,不可用于生产环境。
# 如下:
# openssl req -x509 -days 365 -key cert.key -out cert.crt
# 正规的流程:
# 制作签名机构的私钥和签名证书(公钥)
# ---->签名(会对证书请求文件使用hash函数来提取摘要,然后对摘要使用私钥加密,得到签名,不影响证书内容,浏览器在验证的使用,则把签名机构的公钥证书拿出来解密,`私钥负责签名,公钥负责验证,`注意 RSA 加密方案和 RSA 签名方案是不同的)
# ------->制作私钥以及请求签名的证书 --->得到用于通信的证书。
# 基于509证书参数, 输出证书请求的详细细节, 可以看到RSA 公钥信息。
# openssl x509 -in cert.crt -noout -text
# Subject Public Key Info:
# Public Key Algorithm: rsaEncryption
# RSA Public-Key: (1024 bit)
# Modulus:
# 00:b8:c9:22:14:28:5c:57:88:82:e9:0c:e6:39:b3:
# a7:37:71:62:a4:10:89:20:18:97:5a:ec:95:49:e8:
# 64:a2:ea:bb:33:49:43:83:2d:81:2c:6f:43:6a:a8:
# 40:00:11:8c:03:9e:2b:6f:d9:94:f9:77:49:b0:97:
# 08:6a:9d:0b:cb:8f:e1:a8:3f:81:53:98:16:88:aa:
# a8:a1:c7:80:b6:38:b5:7b:20:02:ea:d7:6a:30:14:
# 5b:1d:c9:b1:63:63:07:36:fc:55:51:e8:6b:10:44:
# 8e:f7:a8:06:83:a6:61:a1:1a:d8:24:8a:d2:dd:d6:
# b0:f9:72:e4:9a:4f:13:7e:5d
# Exponent: 65537 (0x10001)
##########################################################################
给证书请求的文件进行签名有两种,经过验证都可以使用。
第一种:创建私有CA证书进行签名的方式
# 创建私有CA证书,使用该 CA证书 给证书请求文件进行签名
# openssl genrsa -des3 -out ca.key 4096 # 创建私有CA的私钥,并选择用des3 算法加密私钥。
openssl genrsa -out ca.key 4096 # 创建私有CA的私钥
# 生成私有CA的自签名证书,和前面的生成自签名证书,其实是一样的道理, 只是这个我们要把它当作 最顶层的签名证书。
openssl req -x509 -days 365 -key ca.key -out ca.crt
# 使用CA的私有证书和私钥进行证书请求文件的签名, 就可以得到最终的签名证书。
# 个人认为这是比较简化,随性的一种实现方式。
# set_serial 01 为证书设置序列号。
openssl x509 -req -days 365 -CA ca.crt -CAkey ca.key -set_serial 01 -in cert.csr -out cert_1.crt
# 对生成的证书进行校验,看是否能正常通过校验。
openssl verify -CAfile ca.crt cert_1.crt
第二种:该方式是比较正规的方式, 将会建立一个完整的CA机构目录,进行统一管理。
openssl genrsa -out ca.key # 创建私有CA的私钥,前面已创建CA私钥的话,可以省略。
openssl req -new -x509 -days 365 -key ca.key -out ca.crt #生成私有CA的自签名证书,前面已创建CA证书的话,可以省略。
# 利用CA签名证书
# openssl 将会指定默认的openssl.cnf 文件,来获取一些默认的参数配置。
openssl ca -keyfile ca.key -cert ca.crt -in cert.csr -out cert_2.crt -config /usr/local/openssl/openssl.cnf
# 以上命令会报错如下:
# Using configuration from /usr/local/ssl/openssl.cnf
# 1995927552:error:02001002:system library:fopen:No such file
# ordirectory:crypto/bio/bss_file.c:69:fopen('./demoCA/index.txt','r')
# 1995927552:error:2006D080:BIO routines:BIO_new_file:no such file:crypto/bio/bss_file.c:76:
mkdir -p demoCA/newcerts
touch ./demoCA/index.txt
touch ./demoCA/serial
echo 01 > demoCA/serial # 跟前面的方法一样,要设置证书的序列号。
# 对生成的证书进行校验,看是否能正常通过校验。
openssl verify -CAfile ca.crt cert_2.crt cert_1.crt
# 成功的话会出现以下log报告:
# cert_2.crt: OK
# cert_1.crt: OK
**进行校验的时候, 可能会碰到如下问题: **
Q: unable to load certificate?The countryName field is different
A: 因为个人证书请求和CA的签名证书的 countryName, localityName 等不一致, openssl.cnf有要求这几个值要一样,才能正确签名和校验
Q:error 18 at 0 depth lookup: self signed certificate
A: 因为个人证书请求和CA证书 中的 commonName 的值一样, 在证书校验的时候,就会当作是自签名证书,无法校验,回顾一下自签名证书的命令,确实就是这样,生成证书请求的同时,便会同时生成证书文件, 在这个时候,证书中的持有者和颁发者是一样的。
Openssl除了进行加密证书的制作,也可以加密,解密私密的文件。
notice: Openssl 设计得很巧妙, 比如想实现 rsa, aes-256-cbc算法相关操作,先设置算法名称,参数前没有‘-’符号,然后再配置该算法名称的具体小参数。 当先选择算法名称之后, 通过 openssl aes-256-cbc -help, 可以查看到其他的配套的功能参数。 同样的, 当先选择其他参数,比如rsautl, 通过openssl rsautl -help,可以查看到该大参数下对应的小参数名称。
1. 对称加密,比如aes, dh加密算法, 一般理解为加密和解密都使用相同的密钥,
DH加密算法也是对称加密算法, 客户端和服务器可以通过算法得到一样的密钥, 一般用来作为TLS通信中的密钥交换算法。
# -e 表示加密输入文件到输出文件上
openssl aes-256-cbc -e -in des.txt -out enc.txt
# -d 表示解密输入文件到输出文件上
openssl aes-256-cbc -d -in enc.txt -out des.txt
2. 非对称加密,比如rsa算法, 一般理解为公钥加密,私钥解密.
# 生成rsa密钥
sudo openssl genrsa -out rsa_pri.key
sudo openssl rsa -help
# 通过私钥得到公钥
sudo openssl rsa -in rsa_pri.key -pubout -out rsa_pub.key
# 利用pubin参数,输入公钥来加密明文
sudo openssl rsautl -encrypt -in plaintext -out ciphertext -inkey rsa_pub.key -pubin
# 使用私钥来解密密文。
sudo openssl rsautl -decrypt -in ciphertext -out plaintext -inkey rsa_pri.key
history
#HTTPS server
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /usr/local/nginx/tls_file/cert_sign.crt;
ssl_certificate_key /usr/local/nginx/tls_file/cert.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
################################################
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /usr/local/nginx/tls_file/cert_2.crt;
ssl_certificate_key /usr/local/nginx/tls_file/cert.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
#ssl_ciphers AES256-GCM-SHA384;
ssl_ciphers ECDHE-RSA-CHACHA20-POLY1305;
#ssl_ciphers HIGH:!aNULL:!MD5;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
配置完之后, 重启nginx,注意一旦有报什么错误警告,可以通过nginx记录的log 进行分析,
此时通过浏览器访问的时候,会出现以下警告。
这是因为浏览器中保存的CA证书机构无法校验我们下发的证书是否有效, 因为用来签名的CA机构也是我们自己创建的, 正常的生产环境中, 证书请求的文件要让正规机构去签名,才能正确工作, 此处测试,先忽略该错误。
为了消除上述的错误的话, 可以手动在浏览器中导入私有的签名机构的证书,方便浏览器进行 校验。
notice: 常规的生产环境不可随意导入他人的CA证书。
将刚刚创建的CA机构的证书导出到本地。
打开浏览器的证书管理,将其添加到受信任的证书机构中。
这样就可以进行证书的检验,但是,有一点疑问是我的google 浏览器会一直报以下错误:
一直说我的CA机构无效, 关于这一点,就没去追了, 有了解的伙伴可以在文章下方留言。
易混淆点:
同样的X.509证书,可能有不同的编码格式,目前有以下两种编码格式.
PEM - Privacy Enhanced Mail,打开看文本格式,以"-----BEGIN…"开头, "-----END…"结尾,内容是BASE64编码.
查看PEM格式证书的信息:openssl x509 -in certificate.pem -text -noout
Apache和NIX服务器偏向于使用这种编码格式.
DER - Distinguished Encoding Rules,打开看是二进制格式,不可读.
查看DER格式证书的信息:openssl x509 -in certificate.der -inform der -text -noout
Java和Windows服务器偏向于使用这种编码格式.
PEM转为DER:openssl x509 -in cert.crt -outform der -out cert.der
DER转为PEM :openssl x509 -in cert.crt -inform der -outform pem -out cert.pem
以下名称,我一般用来作为文件的后缀,以便更好地区分是什么内容的文件。
CRT - CRT应该是certificate的三个字母,其实还是证书的意思,常见于NIX系统,有可能是PEM编码,也有可能是DER编码,大多数应该是PEM编码,相信你已经知道怎么辨别.
CER - 还是certificate,还是证书,常见于Windows系统,同样的,可能是PEM编码,也可能是DER编码,大多数应该是DER编码.
KEY - 通常用来存放一个公钥或者私钥,并非X.509证书,编码同样的,可能是PEM,也可能是DER.
查看KEY的办法:openssl rsa -in mykey.key -text -noout
如果是DER格式的话,同理应该这样了:openssl rsa -in mykey.key -text -noout -inform der
CSR- Certificate Signing Request, 即证书签名请求,这个并不是证书,而是向权威证书颁发机构获得签名证书的申请,其核心内容是一个公钥(当然还附带了一些别的信息),在生成这个申请的时候,同时也会生成一个私钥,私钥要自己保管好.做过iOS APP的朋友都应该知道是怎么向苹果申请开发者证书的吧.