├── 示例
├── res
│ ├── 8.9.2-1.pcap
│ ├── 8.9.2-2.pcap
│ ├── 8.9.2-3.pcap
│ ├── 8.9.2-4.pcap
│ └── 8.9.2-5.pcap
├── chapter3.md
├── index.md
├── chapter8.md
├── chapter5.md
├── chapter7.md
├── chapter9.md
├── chapter6.md
├── chapter10.md
└── chapter2.md
├── README.md
└── errata.md
/示例/res/8.9.2-1.pcap:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ywdblog/httpsbook/HEAD/示例/res/8.9.2-1.pcap
--------------------------------------------------------------------------------
/示例/res/8.9.2-2.pcap:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ywdblog/httpsbook/HEAD/示例/res/8.9.2-2.pcap
--------------------------------------------------------------------------------
/示例/res/8.9.2-3.pcap:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ywdblog/httpsbook/HEAD/示例/res/8.9.2-3.pcap
--------------------------------------------------------------------------------
/示例/res/8.9.2-4.pcap:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ywdblog/httpsbook/HEAD/示例/res/8.9.2-4.pcap
--------------------------------------------------------------------------------
/示例/res/8.9.2-5.pcap:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ywdblog/httpsbook/HEAD/示例/res/8.9.2-5.pcap
--------------------------------------------------------------------------------
/示例/chapter3.md:
--------------------------------------------------------------------------------
1 | 1:3.3.1 小节
2 |
3 | ```
4 | # 显示机器支持的密码套件
5 | $ openssl ciphers -V | column -t
6 |
7 | # 测试某个网站是否支持特定协议、特定密码套件的连接
8 | $ openssl s_client -cipher "ECDHE-RSA-AES128-SHA" -connect www.example.com:443 -tls1_1
9 | ```
--------------------------------------------------------------------------------
/示例/index.md:
--------------------------------------------------------------------------------
1 | 示例每章一个文件,以小节作为索引。
2 |
3 | 目录:
4 |
5 | - [第二章](chapter2.md)
6 | - [第三章](chapter3.md)
7 | - [第五章](chapter5.md)
8 | - [第六章](chapter6.md)
9 | - [第七章](chapter7.md)
10 | - [第八章](chapter8.md)
11 | - [第九章](chapter9.md)
12 | - [第十章](chapter10.md)
--------------------------------------------------------------------------------
/示例/chapter8.md:
--------------------------------------------------------------------------------
1 | 1:8.9.1 小节
2 |
3 | tcpdump 捕获流量:
4 |
5 | ```
6 | $ tcpdump -s 0 -i eth1 port 443 and host 10.235.173.30 -w https.pcap
7 | ```
8 |
9 | 2:8.9.2 小节
10 |
11 | (1)显示握手失败的 TLS/SSL 消息(图8-16)
12 |
13 | [wireshark 8.9.2-1.pcap 包](res/8.9.2-1.pcap)
14 |
15 | (2)RSA 密钥交换的例子
16 |
17 | [wireshark 8.9.2-2.pcap 包](res/8.9.2-2.pcap)
18 |
19 | (3)ECDHE 密钥交换的例子
20 |
21 | [wireshark 8.9.2-3.pcap 包](res/8.9.2-3.pcap)
22 |
23 | (4)基于 Session ID 会话恢复的例子
24 |
25 | [wireshark 8.9.2-4.pcap 包](res/8.9.2-4.pcap)
26 |
27 | (5)基于 Session Ticket 会话恢复的例子
28 |
29 | [wireshark 8.9.2-5.pcap 包](res/8.9.2-5.pcap)
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 本仓库关于我的新书《深入浅出HTTPS:从原理到实战》,和这本书的一切都可以讨论。
2 |
3 | 1:[本书代码示例](示例/index.md)
4 |
5 | 2:勘误可查看或提交到 [errata.md](errata.md)
6 |
7 | 3:如果想了解这本书,可以查看 [《我的书》](https://mp.weixin.qq.com/s/80oQhzmP9BTimoReo1oMeQ)
8 |
9 | 
10 |
11 | 4:如果想了解我,可以查看 [《我是谁》](https://mp.weixin.qq.com/s/ezBrPc5OIjUlHvCBOAVWKg)
12 |
13 | 5:我的公众号(ID:yudadanwx,虞大胆的叽叽喳喳) ,我会持续性更新,包含密码学&HTTPS相关信息。
14 |
15 | 
16 |
17 | 6:本书购买地址
18 |
19 | - [京东购买连接](https://item.jd.com/12382462.html)
20 | - [当当购买连接](http://product.dangdang.com/25291819.html)
--------------------------------------------------------------------------------
/errata.md:
--------------------------------------------------------------------------------
1 | 本书勘误,欢迎大家提交!
2 |
3 | 页码 | 错误点 | 更正
4 | ------------ | ------------- | ---------
5 | P107,3.2章节 | 第 9 行: 将主密钥转换为多个密码“快” | “快”应改为"块"
6 | P107,3.2.1章节 | 倒数第 2 行: 客户端和服务器端持有一个密钥对,在客户端和服务器端连接的时候分别发送给对方 | 建议改为“客户端和服务器端各持有一份密钥对(公钥+私钥),在它们连接的时候都将自己的公钥发送给对方”似乎更好理解
7 | P124,3.3.1章节 | 倒数第 8 行,“服务器接收到验证消息后,使用加密块解密出摘要数据” 中的 “加密块” | 建议改成“密钥块”与上文保持名称一致。
8 | P148,5.2.1章节 | 第 9 行: `example_cert.pem` 表示 CSR 文件 | 其中的 `example_cert.pem` 应改为 `example_csr.pem`
9 | P158,5.6.2章节 | 添加 HSTS 配置,语句最后少了一个 ";" | 在语句末尾添加一个分号";"
10 | P180,6.2.5章节 | 第 6,7, 14 行中出现的“范域名”的“范” | 应改为“泛”
11 | P216,6.7.5章节 | ` openssl req -in myreq.pem -noout -verify -key example_csr.pem `| `openssl req -in example_csr.pem -noout -verify `
12 | P219,6.7.7章节 | 第 2 行,“查看那个 CA 机构签发了证书”中的 “那个” | 应改为 “哪个”
13 | P232,6.7.10章节| 使用不支持 OCSP 封套的 HTTPS 网站进行演示(letsencrypt.org),使用支持 OCSP 封套的 HTTPS 网站进行演示(www.baidu.com) | 写反了,letsencrypt.org 支持 OCSP 封套,而 www.baidu.com 不支持
14 | P249,7.2.2章节 | “申请证书” 小节,倒数第 10 行“用验证密钥对的公钥验证签名”中的“验证密钥对” | 建议改为“校验密钥对”与上文保持名称一致。
15 | P257,7.3.6章节 | -d “表示要为那些主机生成证书”,“那些” | 应改为 “哪些”
16 | P350,7.3.6章节 | “(2)aECDSA” 下面的命令行不完整 | 应该在开头加上“$ openssl”
17 | P360,9.1.2章节 | 第5行,“移除” | 应改为 “移动”
18 | P449,10.3.2章节 | htts 少了一个 p字母 | 应改为 “https”
19 | P452,10.3.3章节 | apt 误写为 apr | 应该为 “apt”
20 | P486,10.5.3章节 | 倒数第 14 行 “ssl_certificate_key www.example.com” | 应改为 “ssl_certificate_key www.example.key.pem”
21 |
--------------------------------------------------------------------------------
/示例/chapter5.md:
--------------------------------------------------------------------------------
1 | 1:5.2.1 小节
2 |
3 | 生成私钥对和 CSR:
4 |
5 | ```
6 | $ openssl req \
7 | -newkey rsa:1024 -nodes -keyout example_key.pem \
8 | -out example_csr.pem
9 | ```
10 |
11 | 生成自签名证书:
12 |
13 | ```
14 | $ openssl x509 \
15 | -signkey example_key.pem \
16 | -in example_csr.pem \
17 | -req -days 365 -out example_cert.pem
18 | ```
19 |
20 | 2:5.2.3 小节
21 |
22 | ```
23 | # 下载 Certbot 客户端
24 | $ git clone https://github.com/certbot/certbot
25 |
26 | $ cd certbot
27 |
28 | # 一步生成证书
29 | $./certbot-auto certonly --webroot -w /usr/nginx/web -d rss.newyingyong.cn
30 | ```
31 |
32 | 3:5.3.1 小节
33 |
34 | 安装 Nginx:
35 |
36 | ```
37 | $ apt-get install nginx
38 |
39 | # 显示 Nginx 版本
40 | $ nginx -V
41 | ```
42 |
43 | 配置 HTTPS:
44 |
45 | ```
46 | $ vim /etc/nginx/sites-enabled/default
47 |
48 | server {
49 | # 启用 443 端口
50 | listen 443 ssl;
51 |
52 | # 服务器域名
53 | server_name www.example.com;
54 |
55 | # 程序目录
56 | root /var/www/html;
57 |
58 | # 路径可以自定义
59 | # ssl_certificate 表示证书路径
60 | ssl_certificate /etc/cert/fullchain.pem;
61 |
62 | # ssl_certificate_key 表示密钥对路径
63 | ssl_certificate_key /etc/cert/privkey.pem;
64 | }
65 | ```
66 |
67 | 重新启动 Nginx:
68 |
69 | ```
70 | $ service nginx restart
71 | ```
72 |
73 | 4:5.3.2 小节
74 |
75 | 安装:
76 |
77 | ```
78 | $ apt-get install apache2
79 |
80 | # 启用 ssl 模块
81 | $ a2enmod ssl
82 |
83 | # 显示版本
84 | $ apache2 -v
85 | ```
86 |
87 | 配置 HTTPS:
88 |
89 | ```
90 | # 编辑配置文件
91 | vim /etc/apache2/sites-available/default-ssl.conf
92 |
93 |
94 | DocumentRoot /var/www/html
95 | ServerName www.example.com
96 |
97 | # 开启 SSL
98 | SSLEngine on
99 | SSLCertificateFile /etc/cert/fullchain.pem;
100 | SSLCertificateKeyFile /etc/cert/privkey.pem;
101 |
102 | ```
103 |
104 | 重新启动 Apache2:
105 |
106 | ```
107 | $ a2ensite default-ssl.conf
108 | $ service apache2 restart
109 | ```
110 |
111 | 5:5.4 小节
112 |
113 | 301 首页重定向:
114 |
115 | ```
116 | server {
117 | listen 80;
118 | server_name www.example.com;
119 | rewrite ^ https://$server_name;
120 | }
121 | ```
122 |
123 | HTTP URL to HTTPS URL:
124 |
125 | ```
126 | server {
127 | listen 80;
128 | server_name www.example.com;
129 | rewrite ^ https://$server_name$request_uri? permanent;
130 | }
131 | ```
132 |
133 | (6)5.5.2 小节
134 |
135 | HSTS 配置:
136 |
137 | ```
138 | server {
139 | listen 80;
140 | server_name www.example.com;
141 | rewrite ^ https://$server_name$request_uri? permanent;
142 | }
143 |
144 | server {
145 | listen 443 ssl;
146 | server_name www.example.com;
147 |
148 | # 有效期是 1000 秒、域名下的子域名都配置 HSTS
149 | add_header Strict-Transport-Security 'max-age=1000; includeSubDomains; preload;'
150 |
151 | ssl_certificate /etc/cert/fullchain.pem;
152 | ssl_certificate_key /etc/cert/privkey.pem;
153 | ```
154 |
155 |
--------------------------------------------------------------------------------
/示例/chapter7.md:
--------------------------------------------------------------------------------
1 | 1:7.3.1 小节
2 |
3 | 安装 certbot-bot:
4 |
5 | ```
6 | # 下载 certbot-auto 客户端
7 | $ wget https://dl.eff.org/certbot-auto
8 |
9 | # 修改程序权限
10 | $ chmod a+x ./certbot-auto
11 |
12 | # 查看帮助
13 | $ ./certbot-auto --help
14 |
15 | # 查看 Certbot 客户端版本
16 | $ ./certbot-auto --version
17 | ```
18 |
19 | 2:7.3.2 小节
20 |
21 | ```
22 | # 注册帐号
23 | $ certbot-auto register --agree-tos
24 |
25 | # 更改帐号邮箱地址
26 | $ certbot-auto register --update-registration --email admin@example.com
27 | ```
28 |
29 | 3:7.3.4 小节
30 |
31 | ```
32 | # 使用非交互式操作
33 | $ certbot-auto -n
34 |
35 | # 测试证书
36 | $ certbot-auto --test-cert
37 |
38 | # 模拟运行
39 | $ certbot-auto --dry-run
40 |
41 | # 运行 nginx 插件
42 | $ certbot-auto run --nginx
43 | ```
44 |
45 | 4:7.3.5 小节
46 |
47 | ```
48 | # apache 插件
49 | $ certbot-auto run --apache
50 | ```
51 |
52 | 5:7.3.6 小节
53 |
54 | ```
55 | # webroot 插件
56 | $certbot-auto certonly --webroot \
57 | -w /usr/share/nginx/html -d www2.example.com \
58 | -w /usr/share/nginx/html -d www1.example.com \
59 | --rsa-key-size 2048 --dry-run
60 | ```
61 |
62 | 6:7.3.7 小节
63 |
64 | ```
65 | # 默认使用 tls-sni 域名验证方式
66 | $ certbot-auto certonly --standalone -d www1.example.com
67 |
68 | # 使用 http 域名验证方式
69 | $ certbot-auto certonly --standalone -d www1.example.com --preferred-challenges http
70 | ```
71 |
72 | 7:7.3.8 小节
73 |
74 | ```
75 | # manual 插件
76 | $ certbot-auto certonly -d www4.example.com --manual --preferred-challenges dns
77 | ```
78 |
79 | 8:7.3.9 小节
80 |
81 | 更新证书:
82 |
83 | ```
84 | $ certbot-auto certonly --standalone -d www4.example.com \
85 | --force-renewa --rsa-key-size 2048
86 | ```
87 |
88 | 扩展证书:
89 |
90 | ```
91 | $ certbot-auto certonly --standalone --expand \
92 | -d www4.example.com -d www5.example.com
93 | ```
94 |
95 | 9:7.3.10 小节
96 |
97 | 查看系统安装的证书:
98 |
99 | ```
100 | $ certbot-auto certificates
101 | ```
102 |
103 | 指定证书更新:
104 |
105 | ```
106 | certbot-auto certonly --standalone --cert-name www4.example.com \
107 | -d www4.example.com -d www5.example.com --expand --dry-run
108 | ```
109 |
110 | 10:7.3.11 小节
111 |
112 | 撤销证书:
113 |
114 | ```
115 | $ certbot-auto revoke --reason keycompromise \
116 | --cert-path /etc/letsencrypt/archive/www4.example.com/cert1.pem
117 | ```
118 |
119 | 删除本地证书:
120 |
121 | ```
122 | $ certbot delete --cert-name www4.example.com
123 | ```
124 |
125 | 11:7.3.12 小节
126 |
127 | ```
128 | # 扫描所有的证书文件,校验是否续期
129 | $ certbot-auto renew
130 |
131 | # 扫描证书名是 www4.example.com 下的所有证书文件,校验是否续期
132 | $ certbot-auto renew --cert-name www4.example.com
133 |
134 | # 校验某个证书是否续期
135 | $ certbot-auto renew --cert-path /etc/letsencrypt/archive/www4.example.com/cert1.pem
136 | $ certbot renew --post-hook "service nginx restart"
137 | ```
138 |
139 | cron:
140 |
141 | ```
142 | $ vim /etc/crontab
143 |
144 | $ 43 6 * * * certbot renew --post-hook "service nginx restart"
145 | ```
146 |
147 | 12: 7.3.13 小节
148 |
149 | (1)基于 CSR 申请证书
150 |
151 | ```
152 | # 生成密钥对和 CSR 文件
153 | $ openssl req -new -sha256 -newkey rsa:2048 -nodes \
154 | -subj '/CN=www6.example.com/O=Test, Inc./C=CN/ST=Beijing/L=Haidian' \
155 | -keyout www6.example.com_key.pem -out www6.example.com_csr.der
156 |
157 | # certbot 直接发送 CSR 文件给 Let's Encrypt
158 | $ certbot-auto certonly --standalone \
159 | --preferred-challenges tls-sni-01 \
160 | --csr=www6.example.com_csr.der
161 | ```
162 |
163 | (2)申请 ECDSA 证书
164 |
165 | ```
166 | # 生成一个 ECC 密钥对
167 | $ openssl ecparam -genkey -name secp384r1 -noout -out key.pem
168 |
169 | # 基于 ECC 密钥对生成 CSR
170 | $ openssl req -new -sha512 -nodes \
171 | -subj '/CN=www1.www.example.com/O=Test, Inc./C=CN/ST=Beijing/L=Haidian' \
172 | -key key.pem -outform der -out www1.www.example.com_csr.der
173 |
174 | # 使用 standalone 插件生成证书
175 | $ certbot-auto certonly --standalone \
176 | --preferred-challenges tls-sni-01 \
177 | --csr=www1.www.example.com_csr.der
178 | ```
--------------------------------------------------------------------------------
/示例/chapter9.md:
--------------------------------------------------------------------------------
1 | 1:9.1 小节
2 |
3 | ```
4 | # 查看本机openssl是否支持RC4算法
5 | $ openssl ciphers -V 'RC4' | column -t
6 |
7 | # 查看本机openssl是否支持某个密码套件
8 | $ openssl ciphers -V 'ECDHE-ECDSA-AES256-GCM-SHA384' | column -t
9 | ```
10 |
11 | 2: 9.1.2 小节
12 |
13 | 身份验证和密钥交换关键字:
14 |
15 | ```
16 | $ openssl ciphers -V "aRSA" | column -t
17 |
18 | $ openssl ciphers -V "kRSA" | column -t
19 |
20 | $ openssl ciphers -V "ECDSA" | column -t
21 |
22 | $ openssl ciphers -V "DH" | column -t
23 |
24 | $ openssl ciphers -V "EDH" | column -t
25 |
26 | $ openssl ciphers -V "ADH" | column -t
27 |
28 | $ openssl ciphers -V 'kECDHE' | column -t
29 |
30 | $ openssl ciphers -V 'ECDHE' | column -t
31 |
32 | $ openssl ciphers -V 'DSS' | column -t
33 |
34 | $ openssl ciphers -V 'kPSK' | column -t
35 |
36 | $ openssl ciphers -V 'kECDHEPSK' | column -t
37 |
38 | $ ciphers -V 'kDHEPSK' | column -t
39 |
40 | $ openssl ciphers -V 'kRSAPSK' | column -t
41 |
42 | $ openssl ciphers -V 'SRP' | column -t
43 | ```
44 |
45 | 加密算法相关密码套件:
46 |
47 | ```
48 | $ openssl ciphers -V 'AESGCM' | column -t
49 |
50 | $ openssl ciphers -V 'CHACHA20' | column -t
51 |
52 | $ openssl ciphers -V 'AESCCM' | column -t
53 |
54 | $ openssl ciphers -V 'AES' | column -t
55 |
56 | $ openssl ciphers -V '3DES' | column -t
57 | ```
58 |
59 | 摘要算法关键字:
60 |
61 | ```
62 | $ openssl ciphers -V 'MD5' | column -t
63 |
64 | $ openssl ciphers -V 'SHA' | column -t
65 |
66 | $ openssl ciphers -V 'SHA384' | column -t
67 | ```
68 |
69 | 分组关键字:
70 |
71 | ```
72 | $ openssl ciphers -V 'COMPLEMENTOFALL' | column -t
73 |
74 | $ openssl ciphers -V 'HIGH' | column -t
75 |
76 | $ openssl ciphers -V 'MEDIUM' | column -t
77 |
78 | $ openssl ciphers -V 'LOW' | column -t
79 |
80 | $ openssl ciphers -V 'TLSv1.0' | column -t
81 |
82 | $ openssl ciphers -V 'AES+SHA256' | column -t
83 |
84 | $ openssl ciphers -V 'AES:SHA256' | column -t
85 |
86 | $ openssl ciphers -V 'eNULL:SHA384' | column -t
87 |
88 | $ openssl ciphers -V 'DEFAULT:!CHACHA20:CHACHA20' | column -t
89 |
90 | $ openssl ciphers -V 'DEFAULT:-AESGCM:AESGCM' | column -t
91 |
92 | $ openssl ciphers -V 'DEFAULT:+3DES' | column -t
93 |
94 | $ openssl ciphers -V 'AES:+SHA256' | column -t | wc -l
95 |
96 | $ openssl ciphers -V 'AES+SHA256' | column -t | wc -l
97 |
98 | $ openssl ciphers -v 'AES:@STRENGTH'
99 | ```
100 |
101 | 3:9.2 小节
102 |
103 | 文档、工具地址如下:
104 |
105 | | 网站 | 文档或工具名称|地址|说明|
106 | | :-------------:|:-------------:|:-------------:|:-------------:|
107 | |SSL Labs| TLS Deployment Best Practices | https://www.ssllabs.com/projects/best-practices/index.html | 最佳部署文档,读者应该比较文档每次更新的内容|
108 | | SSL Labs| SSL Server Test | https://www.ssllabs.com/ssltest| 对服务器的 HTTPS 配置进行测试,指出潜在的问题,并对安全级别打分|
109 | |SSL Labs| SSL Client Test | https://www.ssllabs.com/ssltest/viewMyClient.html | HTTPS 网站也会涉及到客户端,该工具可以测试客户端的配置情况 |
110 | |SSL Labs| SSL Pulse | https://www.ssllabs.com/ssltest/viewMyClient.html | 对全球顶尖 HTTPS 网站进行长期跟踪,统计和 HTTPS 有关的一些数据|
111 | | Mozilla | 最佳部署文档| https://wiki.mozilla.org/Security/Server_Side_TLS | 重点介绍密码套件配置、HTTPS 潜在的攻击、最佳部署的一些指导|
112 | |Mozilla | Mozilla SSL Configuration Generator| https://mozilla.github.io/server-side-tls/ssl-config-generator/| 用于自动化为服务器配置 HTTPS 协议|
113 | | RFC | Summarizing Known Attacks on TLS|https://tools.ietf.org/html/rfc7457 | 详细描述 TLS/SSL 协议历史上出现过的漏洞 |
114 | | RFC | Recommendations for Secure Use of TLS | https://tools.ietf.org/html/rfc7525 | 描述如何更好的部署 HTTPS 网站|
115 |
116 | 4:9.3.1 小节
117 |
118 | ```
119 | # 查看是否启用窗口缩放
120 | $ sysctl net.ipv4.tcp_window_scaling
121 |
122 | # 设置启用窗口缩放
123 | $ sysctl -w net.ipv4.tcp_window_scaling=1
124 | ```
125 |
126 | 查看初始拥塞窗口大小的方法如下:
127 |
128 | ```
129 | $ ss -nli|fgrep cwnd
130 |
131 | # 输出
132 | rto:1000 mss:536 cwnd:10
133 | ```
134 |
135 | 修改初始拥塞窗口大小
136 | ```
137 | # 修改某个网卡的 cwnd
138 | ip route change 127.0.0.1 initcwnd 10
139 | ```
140 |
141 | 控制满启动:
142 |
143 | ```
144 | # 查看是否禁止慢启动重启
145 | $ sysctl net.ipv4.tcp_slow_start_after_idle
146 |
147 | # 设置慢启动重启
148 | sysctl -w net.ipv4.tcp_slow_start_after_idle=0
149 | ```
150 |
151 | 5:9.3.3 小节
152 |
153 | 编译 openssl 和 nginx:
154 | ```
155 | # 下载较新的 Nginx 版本
156 | $ wget http://nginx.org/download/nginx-1.13.5.tar.gz
157 |
158 | # 下载 OpenSSL 库
159 | $ wget https://www.openssl.org/source/openssl-1.1.0f.tar.gz
160 |
161 | $ wget http://zlib.net/zlib-1.2.11.tar.gz
162 | $ wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.41.tar.gz
163 |
164 | # 解压缩
165 | $ tar xvf nginx-1.13.5.tar.gz
166 | $ tar xvf openssl-1.1.0f.tar.gz
167 | $ tar xvf zlib-1.2.11.tar.gz
168 | $ tar xvf pcre-8.41.tar.gz
169 |
170 | $ cd nginx-1.13.5
171 | $ ./configure --help
172 |
173 | $ ./configure \
174 | --prefix=/usr/local/nginx1.13 \
175 | --with-pcre=../pcre-8.41 \
176 | --with-zlib=../zlib-1.2.11 \
177 | --with-http_ssl_module \
178 | --with-http_v2_module \
179 | --with-stream \
180 | --with-openssl=../openssl-1.1.0f
181 | $ make
182 | $ make install
183 | $ make clean
184 | ```
185 |
186 | 配置 HTTP/2 网站:
187 |
188 | ```
189 | server {
190 | listen 443 ssl http2;
191 | server_name www.example.com;
192 |
193 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
194 | ssl_certificate cert.pem;
195 | ssl_certificate_key cert.key;
196 | ssl_ciphers HIGH:!aNULL:!MD5;
197 |
198 | location / {
199 | root html;
200 | index index.html index.htm;
201 | }
202 | }
203 | ```
204 |
205 | 编译curl支持http/2:
206 |
207 | ```
208 | $ apt-get install build-essential libnghttp2-dev libssl-dev
209 |
210 | $ git clone https://github.com/tatsuhiro-t/nghttp2.git
211 | $ cd nghttp2
212 | $ autoreconf -i
213 | $ automake
214 | $ autoconf
215 | $ ./configure
216 | $ make
217 | $ make install
218 |
219 | $ wget https://curl.haxx.se/download/curl-7.56.0.tar.gz
220 | $ tar -xvf curl-7.56.0.tar.gz
221 |
222 | $ cd curl-7.58.0
223 | $ ./configure --with-nghttp2 --prefix=/usr/local --with-ssl
224 | $ make
225 | $ make install
226 |
227 | $ /usr/local/bin/curl -V
228 | ```
229 |
230 | 测试网站是否支持 HTTP/2:
231 |
232 | ```
233 | $ curl --http2 -k -I "https://www.example.com"
234 | ```
--------------------------------------------------------------------------------
/示例/chapter6.md:
--------------------------------------------------------------------------------
1 | 1:6.3.5 小节
2 |
3 | 获取 Let’s Encrypt ISRG 中间证书公钥:
4 |
5 | ```
6 | # 下载 Let’s Encrypt ISRG 中间证书
7 | $ wget https://letsencrypt.org/certs/letsencryptauthorityx3.pem.txt -O isrg.pem
8 |
9 | # 显示证书包含的公钥摘要值,该公钥用来验证服务器实体证书的签名
10 | $ openssl x509 -in isrg.pem -subject_hash -noout
11 |
12 | # 输出值
13 | 4f06f81d
14 | ```
15 |
16 | 获取 Let’s Encrypt DST 中间证书公钥:
17 |
18 | ```
19 | # 下载 Let’s Encrypt DST 中间证书
20 | $ wget https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt -O dst.pem
21 |
22 | # 显示证书包含的公钥摘要值,该公钥用来验证服务器实体证书的签名
23 | $ openssl x509 -in dst.pem -subject_hash -noout
24 |
25 | # 输出值
26 | 4f06f81d
27 | ```
28 |
29 | 2:6.7.2 小节
30 |
31 | (1)PKCS#12 格式
32 |
33 | 通过 OpenSSL pkcs12 子命令将密钥对(privkey.pem)、服务器实体证书(cert.pem)、中间证书(chain.pem)转换成一个文件:
34 |
35 | ```
36 | $ openssl pkcs12 \
37 | -export -out cert.pfx \
38 | -inkey privkey.pem -in cert.pem -certfile chain.pem
39 | ```
40 |
41 | 从 cert.pfx 导出密钥对和证书:
42 |
43 | ```
44 | # 导出密钥对
45 | $ openssl pkcs12 -in cert.pfx -nodes -nocerts -out new_privkey.pem
46 |
47 | # 导出服务器实体证书
48 | $ openssl pkcs12 -in cert.pfx -nodes -clcerts -out new_cert.pem
49 |
50 | # 导出中间证书
51 | $ openssl pkcs12 -in cert.pfx -nodes -cacerts -out new_chain.pem
52 | ```
53 |
54 | (2)PKCS#7 格式
55 |
56 | 生成 cert.p7b 文件:
57 |
58 | ```
59 | $ openssl crl2pkcs7 -nocrl -certfile cert.pem -certfile chain.pem -out cert.p7b
60 | ```
61 | 从 cert.p7b 文件中导出服务器证书文件和中间证书文件:
62 |
63 | ```
64 | # 导出完整证书链文件,服务器实体证书在文件顶部,中间证书在文件底部
65 | $ openssl pkcs7 -print_certs -in cert.p7b -out fullchain.cer
66 | ```
67 |
68 | 3:6.7.3 小节
69 |
70 | 使用 s_client 获取线上证书:
71 |
72 | ```
73 | $ openssl s_client -connect www.example.com:443 -showcerts 2>&1 &1 www_fullchain.pem
82 |
83 | $ cat www_fullchain.pem | awk 'split_after==1{n++;split_after=0} \
84 | /-----END CERTIFICATE-----/ {split_after=1} \
85 | {print > "www_cert" n ".pem"}'
86 |
87 | # 重命名中间证书,在本列中中间证书只有一个.
88 | $ mv www_cert1.pem www_chain.pem
89 |
90 | # 查看生成的各个文件
91 | $ tree
92 | ```
93 |
94 | 获取根证书:
95 |
96 | ```
97 | $ openssl x509 -in www_chain.pem -noout -text | grep "CA Issuers"
98 |
99 | #下载根证书文件
100 | $ wget http://apps.identrust.com/roots/dstrootcax3.p7c -O DST_ROOT.p7c
101 |
102 | # 转换成 PEM 格式
103 | $ openssl pkcs7 -inform der -in DST_ROOT.p7c -print_certs -out DST_ROOT.pem
104 |
105 | # 检查证书签发者
106 | $ openssl x509 -in DST_ROOT.pem -issuer
107 | ```
108 |
109 | 4:6.7.4 小节
110 |
111 | 下载 Mozilla 根证书库:
112 |
113 | ```
114 | $ wget https://raw.githubusercontent.com/curl/curl/master/lib/mk-ca-bundle.pl
115 |
116 | $ chmod 0777 mk-ca-bundle.pl
117 |
118 | $ ./mk-ca-bundle.pl
119 | ```
120 |
121 | 更新系统的证书库:
122 |
123 | ```
124 | $ update-ca-certificates
125 | ```
126 |
127 | 自签名证书同步到系统根证书库中:
128 |
129 | ```
130 | $ mkdir /usr/local/share/ca-certificates/extra
131 |
132 | # 拷贝自签名证书,文件后缀 crt
133 | $ cp self-ertificate.crt /usr/local/share/ca-certificates/extra
134 |
135 | $ update-ca-certificates
136 | ```
137 |
138 | 5:6.7.5 小节
139 |
140 | 生成 CSR:
141 |
142 | ```
143 | $ openssl req \
144 | -new -sha256 -newkey rsa:2048 -nodes \
145 | -subj '/CN=www1.example.com,www2.example.com/O=Test, Inc./C=CN/ST=Beijing/L=Haidian' \
146 | -keyout example_key.pem -out example_csr.pem
147 | ```
148 |
149 | 查看 CSR:
150 |
151 | ```
152 | $ openssl req -in example_csr.pem -noout -text
153 | ```
154 |
155 | 校验 CSR 签名:
156 |
157 | ```
158 | $ openssl req -in myreq.pem -noout -verify -key example_csr.pem
159 | ```
160 |
161 | CSR 格式转换:
162 |
163 | ```
164 | # PEM 格式转换为 DER 格式
165 | $ openssl req -in example_csr.pem -out example_csr.der -outform DER
166 |
167 | # DER 格式转换为 PEM 格式
168 | $ openssl req -in example_csr.der -inform DER -out example_csr.pem -outform PEM
169 | ```
170 |
171 | 6:6.7.6 小节
172 |
173 | 生成自签名证书
174 |
175 | ```
176 | $ echo "subjectAltName=DNS:www1.example.com,DNS:www1.example.com" >>certext.ext
177 |
178 | $ openssl x509 -req -days 365 -in example_csr.pem \
179 | -signkey example_key.pem -out example_cert.pem \
180 | -extfile certext.ext
181 | ```
182 |
183 | 7:6.7.7 小节
184 |
185 | 证书内部结构:
186 |
187 | ```
188 | # 查看证书完整信息
189 | $ openssl x509 -text -in cert.pem -noout
190 |
191 | # 查看证书包含的公钥
192 | $ openssl x509 -in cert.pem -pubkey
193 |
194 | # 查看那个 CA 机构签发了证书
195 | $ openssl x509 -in cert.pem -issuer
196 |
197 | # 查看证书的有效期
198 | $ openssl x509 -in cert.pem -enddate
199 | ```
200 |
201 | 查看服务器实体证书:
202 |
203 | ```
204 | $ openssl x509 -in cert.pem -text -noout
205 | ```
206 |
207 | 查看 Let's Encrypt 中间证书:
208 |
209 | ```
210 | $ openssl x509 -in cert.pem -text -noout
211 | ```
212 |
213 | 查看根证书:
214 |
215 | ```
216 | $ openssl x509 -in DST_ROOT.pem -noout -text
217 | ```
218 |
219 | 8:6.7.8 小节
220 |
221 | 手动校验:
222 |
223 | ```
224 | # 下载服务器实体证书
225 | $ openssl s_client -connect www.sina.com.cn:443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' > www_cert.pem
226 |
227 | # 找到服务器实体证书的 CRL 分发点
228 | $ openssl x509 -in www_cert.pem -noout -text | grep "crl"
229 |
230 | # 输出 CRL 分发点地址
231 | URI:http://gn.symcb.com/gn.crl
232 |
233 | # 下载 CRLs 文件
234 | $ wget "http://gn.symcb.com/gn.crl"
235 |
236 | # 查看 CRLs 文件内容
237 | $ openssl crl -inform DER -text -noout -in gn.crl
238 | ```
239 |
240 | 自动校验:
241 |
242 | ```
243 | # 下载证书链文件
244 | $ openssl s_client -connect www.sina.com.cn:443 -showcerts 2>&1 www_fullchain.pem
247 |
248 | # 拆分证书文件,www_cert.pem 是服务器实体证书,www_chain1.pem 是中间证书
249 | $ cat www_fullchain.pem | awk 'split_after==1{n++;split_after=0} \
250 | /-----END CERTIFICATE-----/ {split_after=1} \
251 | {print > "www_cert" n ".pem"}'
252 |
253 | # 重命名中间证书,在该例中,中间证书只有一个。
254 | $ mv www_cert1.pem www_chain.pem
255 |
256 | # 找到服务器实体证书的 CRL 分发点
257 | $ openssl x509 -in www_cert.pem -noout -text | grep "crl"
258 |
259 | # 输出 CRL 分发点地址
260 | URI:http://gn.symcb.com/gn.crl
261 |
262 | # 下载 CRLs 文件
263 | $ wget "http://gn.symcb.com/gn.crl"
264 |
265 | # 将 CRLs 文件转换为 PEM 格式
266 | $ openssl crl -inform DER -in gn.crl -outform PEM -out crl.pem
267 |
268 | # 合并中间证书和 CRLs 文件
269 | $ cat www_chain.pem crl.pem > crl_chain.pem
270 |
271 | # 校验,-CAfile 表示完整证书链
272 | $ openssl verify -crl_check -CAfile crl_chain.pem www_cert.pem
273 |
274 | # 输出 ok 表示服务器实体证书没有被吊销
275 | www_cert.pem: OK
276 | ```
277 |
278 | 比较:
279 |
280 | ```
281 | # 查询服务器实体证书的签发者
282 | $ openssl x509 -in www_cert.pem -issuer -pubkey
283 | # 输出
284 | issuer=C = US, O = GeoTrust Inc., CN = GeoTrust SSL CA - G3
285 |
286 | # 查询 CRLs 的签发者
287 | $ openssl crl -inform DER -noout -in gn.crl -issuer
288 | # 输出
289 | issuer=C = US, O = GeoTrust Inc., CN = GeoTrust SSL CA - G3
290 | ```
291 |
292 | 9:6.7.9 小节
293 |
294 | (1)校验 Let's Encrypt 的 OCSP 服务
295 |
296 | ```
297 | # 从服务器实体证书中获取 OCSP 的地址
298 | $ openssl x509 -in cert.pem -noout -ocsp_uri
299 |
300 | # 输出 OCSP URL 地址
301 | http://ocsp.int-x3.letsencrypt.org
302 |
303 | # 校验 OCSP
304 | $ openssl ocsp -issuer chain.pem -cert cert.pem -CAfile chain.pem \
305 | -no_nonce --text -url http://ocsp.int-x3.letsencrypt.org \
306 | -header Host=ocsp.int-x3.letsencrypt.org
307 | ```
308 |
309 | (2)校验 GeoTrust 的 OCSP 响应
310 |
311 | ```
312 | $ openssl ocsp -issuer www_chain.pem -cert www_cert.pem \
313 | -url http://gn.symcd.com -CAfile www_chain.pem --text -no_nonce
314 | ```
315 |
316 | 10:6.7.10 小节
317 |
318 | 使用不支持 OCSP 封套的 HTTPS 网站进行演示:
319 |
320 | ```
321 | $ openssl s_client -connect letsencrypt.org:443 -status -tlsextdebug < /dev/null 2>&1 \
322 | | grep -i "OCSP response"
323 | ```
324 |
325 | 使用支持 OCSP 封套的 HTTPS 网站进行演示
326 |
327 | ```
328 | $ openssl s_client -connect www.baidu.com:443 -status -tlsextdebug < /dev/null 2>&1
329 | ```
330 |
331 | 11:6.8.2 小节
332 |
333 | 查看 github 的 SCT
334 |
335 | ```
336 | $ openssl x509 -in github.cer -noout -text
337 | ```
338 |
339 | 在线查看支持 OCSP 封套的网站
340 | ```
341 | $ openssl s_client -connect www.example.com:443 -status -tlsextdebug < /dev/null 2>&1
342 | ```
--------------------------------------------------------------------------------
/示例/chapter10.md:
--------------------------------------------------------------------------------
1 | 1:10.1.1 小节
2 |
3 | Modern 配置:
4 |
5 | ```
6 | ssl_protocols TLSv1.2;
7 |
8 | ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:
9 | ECDHE-RSA-AES256-GCM-SHA384:
10 | ECDHE-ECDSA-CHACHA20-POLY1305:
11 | ECDHE-RSA-CHACHA20-POLY1305:
12 | ECDHE-ECDSA-AES128-GCM-SHA256:
13 | ECDHE-RSA-AES128-GCM-SHA256:
14 | ECDHE-ECDSA-AES256-SHA384:
15 | ECDHE-RSA-AES256-SHA384:
16 | ECDHE-ECDSA-AES128-SHA256:
17 | ECDHE-RSA-AES128-SHA256';
18 | ```
19 |
20 | Intermediate 配置:
21 |
22 | ```
23 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
24 |
25 | ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:
26 | ECDHE-RSA-CHACHA20-POLY1305:
27 | ECDHE-ECDSA-AES128-GCM-SHA256:
28 | ECDHE-RSA-AES128-GCM-SHA256:
29 | ECDHE-ECDSA-AES256-GCM-SHA384:
30 | ECDHE-RSA-AES256-GCM-SHA384:
31 | DHE-RSA-AES128-GCM-SHA256:
32 | DHE-RSA-AES256-GCM-SHA384:
33 | ECDHE-ECDSA-AES128-SHA256:
34 | ECDHE-RSA-AES128-SHA256:
35 | ECDHE-ECDSA-AES128-SHA:
36 | ECDHE-RSA-AES256-SHA384:
37 | ECDHE-RSA-AES128-SHA:
38 | ECDHE-ECDSA-AES256-SHA384:
39 | ECDHE-ECDSA-AES256-SHA:
40 | ECDHE-RSA-AES256-SHA:
41 | DHE-RSA-AES128-SHA256:
42 | DHE-RSA-AES128-SHA:
43 | DHE-RSA-AES256-SHA256:
44 | DHE-RSA-AES256-SHA:
45 | ECDHE-ECDSA-DES-CBC3-SHA:
46 | ECDHE-RSA-DES-CBC3-SHA:
47 | EDH-RSA-DES-CBC3-SHA:
48 | AES128-GCM-SHA256:
49 | AES256-GCM-SHA384:
50 | AES128-SHA256:
51 | AES256-SHA256:
52 | AES128-SHA:
53 | AES256-SHA:
54 | DES-CBC3-SHA:
55 | !DSS';
56 | ```
57 |
58 | Old 配置:
59 |
60 | ```
61 | ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
62 |
63 | ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:
64 | ECDHE-RSA-CHACHA20-POLY1305:
65 | ECDHE-RSA-AES128-GCM-SHA256:
66 | ECDHE-ECDSA-AES128-GCM-SHA256:
67 | ECDHE-RSA-AES256-GCM-SHA384:
68 | ECDHE-ECDSA-AES256-GCM-SHA384:
69 | DHE-RSA-AES128-GCM-SHA256:
70 | DHE-DSS-AES128-GCM-SHA256:
71 | kEDH+AESGCM:
72 | ECDHE-RSA-AES128-SHA256:
73 | ECDHE-ECDSA-AES128-SHA256:
74 | ECDHE-RSA-AES128-SHA:
75 | ECDHE-ECDSA-AES128-SHA:
76 | ECDHE-RSA-AES256-SHA384:
77 | ECDHE-ECDSA-AES256-SHA384:
78 | ECDHE-RSA-AES256-SHA:
79 | ECDHE-ECDSA-AES256-SHA:
80 | DHE-RSA-AES128-SHA256:
81 | DHE-RSA-AES128-SHA:
82 | DHE-DSS-AES128-SHA256:
83 | DHE-RSA-AES256-SHA256:
84 | DHE-DSS-AES256-SHA:
85 | DHE-RSA-AES256-SHA:
86 | ECDHE-RSA-DES-CBC3-SHA:
87 | ECDHE-ECDSA-DES-CBC3-SHA:
88 | EDH-RSA-DES-CBC3-SHA:
89 | AES128-GCM-SHA256:
90 | AES256-GCM-SHA384:AES128-SHA256:
91 | AES256-SHA256:
92 | AES128-SHA:
93 | AES256-SHA:
94 | AES:
95 | DES-CBC3-SHA:
96 | HIGH:SEED:!aNULL:!eNULL:!EXPORT:
97 | !DES:!RC4:!MD5:!PSK:!RSAPSK:
98 | !aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:
99 | !KRB5-DES-CBC3-SHA:!SRP';
100 | ```
101 |
102 | nginx配置:
103 |
104 | ```
105 | server {
106 | listen 80 default_server;
107 | listen [::]:80 default_server;
108 |
109 | # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
110 | return 301 https://$host$request_uri;
111 | }
112 |
113 | server {
114 | listen 443 ssl http2;
115 | listen [::]:443 ssl http2;
116 |
117 | # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
118 | ssl_certificate /path/to/signed_cert_plus_intermediates;
119 | ssl_certificate_key /path/to/private_key;
120 | ssl_session_timeout 1d;
121 | ssl_session_cache shared:SSL:50m;
122 | ssl_session_tickets off;
123 |
124 | # modern configuration. tweak to your needs.
125 | ssl_protocols TLSv1.2;
126 | ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
127 | ssl_prefer_server_ciphers on;
128 |
129 | # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
130 | add_header Strict-Transport-Security max-age=15768000;
131 |
132 | # OCSP Stapling ---
133 | # fetch OCSP records from URL in ssl_certificate and cache them
134 | ssl_stapling on;
135 | ssl_stapling_verify on;
136 |
137 | ## verify chain of trust of OCSP response using Root CA and Intermediate certs
138 | ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;
139 |
140 | resolver ;
141 |
142 | ....
143 | }
144 | ```
145 |
146 | 2:10.1.2 小节
147 |
148 | ```
149 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
150 | ssl_ecdh_curve X25519:P-256:P-384:P-224:P-521;
151 |
152 | ssl_ciphers '[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]:
153 | ECDHE+AES128:
154 | RSA+AES128:
155 | ECDHE+AES256:
156 | RSA+AES256:
157 | ECDHE+3DES:
158 | RSA+3DES';
159 |
160 | ssl_prefer_server_ciphers on;
161 | ```
162 |
163 | ```
164 | ssl_prefer_server_ciphers off;
165 | ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-CHACHA20-POLY1305' ;
166 | ```
167 |
168 | 等价加密算法组:
169 |
170 | ```
171 | ssl_prefer_server_ciphers on;
172 | ssl_ciphers '[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]' ;
173 | ```
174 |
175 | sslconfig 配置:
176 |
177 | ```
178 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
179 | ssl_ecdh_curve X25519:P-256:P-384:P-224:P-521;
180 |
181 | ssl_ciphers '[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]:
182 | ECDHE+AES128:
183 | RSA+AES128:
184 | ECDHE+AES256:
185 | RSA+AES256:
186 | ECDHE+3DES:
187 | RSA+3DES';
188 |
189 | ssl_prefer_server_ciphers on;
190 | ```
191 |
192 | 3:10.3.1 小节
193 |
194 | (1)s_client
195 |
196 | ```
197 | $ man s_client
198 |
199 | $ openssl s_client -connect www.example.com:443
200 | ```
201 |
202 | 获取服务器证书并查看:
203 |
204 | ```
205 | $ openssl s_client -connect www.example.com:443 2>&1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' >cert.pem
206 |
207 | $ openssl x509 -text -in cert.pem -noout
208 | ```
209 |
210 | 测试是否支持 smtp:
211 |
212 | ```
213 | $ openssl s_client -connect smtp.sina.net:25 -starttls smtp
214 | ```
215 |
216 | 测试是否支持特定协议版本:
217 |
218 | ```
219 | $ openssl s_client -connect www.example.com:443 -ssl3
220 | ```
221 |
222 | 指定本地根证书地址:
223 |
224 | ```
225 | $ openssl s_client -connect www.example.com:443 -CApath /etc/ssl/certs
226 | ```
227 |
228 | 指定本地 CA 根证书:
229 |
230 | ```
231 | $ openssl s_client -connect www.example.com:443 -CAfile /etc/ssl/certs/ca-certificates.crt
232 |
233 | $ openssl s_client -connect www.example.com:443 -CAfile /usr/share/ca-certificates/mozilla/DigiCert_Global_Root_CA.crt
234 |
235 | $ openssl s_client -connect www.example.com:443 -no-CAfile
236 | ```
237 |
238 | 查看状态:
239 |
240 | ```
241 | $ openssl s_client -connect www.example.com:443 -state
242 | ```
243 |
244 | SNI:
245 |
246 | ```
247 | $ openssl s_client -connect www.example.com:443 -servername www.example.com
248 | ```
249 |
250 | 测试:
251 |
252 | ```
253 | $ openssl s_client -connect www.example.com:443 -tlsextdebug
254 | ```
255 |
256 | reconnect:
257 |
258 | ```
259 | $ openssl s_client -connect www.example.com:443 2>&1 -reconnect | grep "New\|Reuse"
260 | ```
261 |
262 | debug:
263 |
264 | ```
265 | $ openssl s_client -connect www.example.com:443 2>&1 -debug
266 |
267 | $ openssl s_client -connect www.example.com:443 2>&1 -msg -msgfile https.cap
268 | ```
269 |
270 | 查看 ecc 命名曲线:
271 |
272 | ```
273 | $ openssl ecparam -list_curves
274 | ```
275 |
276 | (2)s_server
277 |
278 | 启动 443 HTTPS 网站:
279 |
280 | ```
281 | $ openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes
282 |
283 | $ openssl s_server -key key.pem -cert cert.pem -accept localhost:4433 -www -WWW
284 |
285 | $ openssl s_server -key key.pem -cert cert.pem -accept localhost:4433 \
286 | -cipher "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305"
287 | ```
288 |
289 | 4:10.3.3 小节
290 |
291 | (1)O-Saft
292 |
293 | ```
294 | # 了解简短的使用说明
295 | $ ./o-saft.pl -h
296 |
297 | # 了解详细的使用说明
298 | $ ./o-saft.pl --help
299 | ```
300 |
301 | 通过几个例子描述使用:
302 |
303 | ```
304 | # 显示网站证书
305 | $ ./o-saft.pl +certificate www.example.com
306 |
307 | # 显示本地支持的所有密码套件
308 | $ ./o-saft.pl +list
309 |
310 | # 仅仅显示网站支持的密码套件
311 | $ ./o-saft.pl +cipher --enabled www.example.com
312 |
313 | # 测试网站是否支持特定的密码套件
314 | $ ./o-saft.pl +cipher --cipher=ADH-AES256-SHA www.example.com
315 |
316 | # 对网站的握手进行调试
317 | $ ./o-saft.pl +info www.example.com --trace
318 |
319 | # 显示证书链信息
320 | $ ./o-saft.pl www.example.com +chain_verify +verify +error_verify +chain
321 | ```
322 |
323 | (2)RFC 5077 工具
324 |
325 | 安装该工具:
326 |
327 | ```
328 | $ git clone https://github.com/vincentbernat/rfc5077.git
329 | $ cd rfc5077/
330 | $ git submodule init
331 | $ git submodule update
332 | $ make
333 | ```
334 |
335 | 运行 rfc5077-client 工具,对网站会话恢复进行测试:
336 |
337 | ```
338 | $ ./rfc5077-client -s www.example.com 139.129.23.162
339 | ```
340 |
341 | 5:10.4.1 小节
342 |
343 | (1)nginx 安装
344 |
345 | ```
346 | # 下载较新的 Nginx 版本
347 | $ wget http://nginx.org/download/nginx-1.13.5.tar.gz
348 |
349 | # 下载 OpenSSL 库
350 | $ wget https://www.openssl.org/source/openssl-1.1.0f.tar.gz
351 |
352 | $ wget http://zlib.net/zlib-1.2.11.tar.gz
353 | $ wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.41.tar.gz
354 |
355 | # 解压缩
356 | $ tar xvf nginx-1.13.5.tar.gz
357 | $ tar xvf openssl-1.1.0f.tar.gz
358 | $ tar xvf zlib-1.2.11.tar.gz
359 | $ tar xvf pcre-8.41.tar.gz
360 |
361 | $ cd nginx-1.13.5
362 |
363 | # 详细了解配置参数
364 | $ ./configure --help
365 |
366 | $ ./configure \
367 | --prefix=/usr/local/nginx1.13 \
368 | --with-pcre=../pcre-8.41 \
369 | --with-zlib=../zlib-1.2.11 \
370 | --with-http_ssl_module \
371 | --with-stream \
372 | --with-openssl=../openssl-1.1.0f \
373 | --with-openssl-opt="enable-ec_nistp_64_gcc_128"
374 |
375 | $ make
376 | $ make install
377 | $ make clean
378 |
379 | # Nginx 的配置文件
380 | /usr/local/nginx1.13/conf/nginx.conf
381 |
382 | # Nginx 二进制运行文件
383 | /usr/local/nginx1.13/sbin/nginx
384 |
385 | # 测试配置是否正确
386 | $ /usr/local/nginx1.13/sbin/nginx -t
387 |
388 | # 启动 Nginx
389 | $ /usr/local/nginx1.13/sbin/nginx
390 |
391 | $ nginx -V
392 | ```
393 |
394 | (2)基本 https 指令配置
395 |
396 | ```
397 | http {
398 | include mime.types;
399 | default_type application/octet-stream;
400 |
401 | log_format main '$remote_addr - $remote_user [$time_local] "$request" '
402 | '$status $body_bytes_sent "$http_referer" '
403 | '"$http_user_agent" "$http_x_forwarded_for"';
404 |
405 | access_log logs/access.log main;
406 |
407 | sendfile on;
408 |
409 | # HTTPS server
410 | server {
411 | listen 443 ssl;
412 | server_name www.example.com;
413 |
414 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
415 | ssl_certificate cert.pem;
416 | ssl_certificate_key cert.key;
417 | ssl_ciphers HIGH:!aNULL:!MD5;
418 |
419 | location / {
420 | root html;
421 | index index.html index.htm;
422 | }
423 | }
424 | ```
425 |
426 | (3)双证书支持
427 |
428 | ```
429 | server {
430 | listen 443 ssl;
431 | server_name www.example.com;
432 |
433 | ssl_certificate www.example.com.rsa.crt;
434 | ssl_certificate_key www.example.com.rsa.key;
435 |
436 | ssl_certificate www.example.com.ecdsa.crt;
437 | ssl_certificate_key www.example.com.ecdsa.key;
438 | }
439 | ```
440 |
441 | 测试是否支持双证书:
442 |
443 | ```
444 | $ openssl s_client -connect www.example.com:443 -cipher 'aECDSA'
445 |
446 | $ openssl s_client -connect www.example.com:443 -cipher 'aRSA'
447 | ```
448 |
449 | (4)Nginx+Openssl patch
450 |
451 | ```
452 | # 下载 OpenSSL 库
453 | $ wget https://www.openssl.org/source/openssl-1.1.0f.tar.gz
454 |
455 | # 下载 patch
456 | $ wget "https://gitlab.com/buik/openssl/repository/openssl-patch/archive.zip"
457 |
458 | # 解压缩 patch 和 OpenSSL 库
459 | $ unzip openssl-openssl-patch-fee83cc1a9d1a1d2e35a1da18d3af5af4af32ca8.zip
460 | $ tar xvf openssl-1.1.0f.tar.gz
461 |
462 | $ cd openssl-1.1.0f
463 |
464 | # 打 patch
465 | $ patch -p1 < ../openssl-openssl-patch-fee83cc1a9d1a1d2e35a1da18d3af5af4af32ca8/openssl-1.1/OpenSSL1.1g-equal-preference-cipher-groups.patch
466 | ```
467 |
468 | 配置等价加密算法组:
469 |
470 | ```
471 | #nginx 配置
472 |
473 | ssl_ciphers '[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]' ;
474 | ```
475 |
476 | (5)通配符证书
477 |
478 | ```
479 | http {
480 |
481 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
482 | ssl_certificate cert.pem;
483 | ssl_certificate_key cert.key;
484 |
485 | server {
486 | listen 443 ssl;
487 | server_name www.example.com;
488 | }
489 |
490 | server {
491 | listen 443 ssl;
492 | server_name www.example.cn;
493 | }
494 | }
495 | ```
496 |
497 | (6)Session ID 会话恢复
498 |
499 | ```
500 | ssl_session_cache builtin:1000 shared:TLS:10m;
501 | ```
502 |
503 | (7)Session Ticket 会话恢复
504 |
505 | ```
506 | ssl_session_tickets ticket.key;
507 | ```
508 |
509 | 配置:
510 |
511 | ```
512 | ssl_session_tickets on ;
513 | ssl_session_tickets newticket.key ;
514 | ssl_session_tickets ticket.key;
515 | ```
516 |
517 | (8)OCSP 封套
518 |
519 | ```
520 | ssl_stapling on;
521 | ssl_stapling_verify on;
522 | ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;
523 | ```
524 |
525 | (9)动态调整 TLS 记录层协议大小
526 |
527 | ```
528 | # 下载 patch
529 | $ wget https://raw.githubusercontent.com/cloudflare/sslconfig/master/patches/nginx__dynamic_tls_records.patch
530 |
531 | # 下载 OpenSSL 库
532 | $ wget https://www.openssl.org/source/openssl-1.1.0f.tar.gz
533 |
534 | $ tar xvf openssl-1.1.0f.tar.gz
535 |
536 | # 合并
537 | $ cd openssl-1.1.0f
538 | $ patch -p1 < nginx__dynamic_tls_records.patch
539 | ```
540 |
541 | (10)证书透明度支持
542 |
543 | ```
544 | $ sudo apt-get install golang
545 | $ wget -O ct-submit.zip -c https://github.com/grahamedgecombe/nginx-ct/archive/master.zip
546 | $ unzip ct-submit.zip
547 | $ cd ct-submit-master
548 | $ go build
549 |
550 | $ ./ct-submit-master ct.googleapis.com/aviator /www/scts/aviator.sct
551 | $ ./ct-submit-master ct1.digicert-ct.com/log /www/scts/digicert.sct
552 | ```
553 |
554 | Nginx 支持 SCT:
555 |
556 | ```
557 | # 下载 nginx-ct
558 | $ wget -O nginx-ct.zip -c https://github.com/grahamedgecombe/nginx-ct/archive/master.zip
559 | $ unzip nginx-ct.zip
560 |
561 | # 下载 OpenSSL 库
562 | $ wget https://www.openssl.org/source/openssl-1.1.0f.tar.gz
563 | $ tar xvf nginx-1.13.5.tar.gz
564 | $ cd nginx-1.13.5
565 |
566 | $ ./configure \
567 | --prefix=/usr/local/nginx1.13 \
568 | --with-pcre=../pcre-8.41 \
569 | --with-zlib=../zlib-1.2.11 \
570 | --with-http_ssl_module \
571 | --with-stream \
572 | --with-openssl=../openssl-1.1.0f \
573 | --with-openssl-opt="enable-ec_nistp_64_gcc_128" \
574 | --add-module=../nginx-ct-master
575 |
576 | $ make
577 | $ make install
578 | ```
579 |
580 | 配置:
581 |
582 | ```
583 | server {
584 | listen 443 ssl;
585 | server_name www.example.com;
586 | ssl_ct on;
587 | # 加载目录
588 | ssl_ct_static_scts /www/scts/;
589 | }
590 | ```
591 |
592 | 6:10.4.2 小节
593 |
594 |
--------------------------------------------------------------------------------
/示例/chapter2.md:
--------------------------------------------------------------------------------
1 | 1:2.1.3 小节
2 |
3 | 基本命令:
4 |
5 | ```
6 | # 查看 openssl 版本号
7 | $ openssl version
8 |
9 | # 查看 openssl 帮助
10 | $ openssl help
11 |
12 | # 查看某个命令的帮助
13 | $ openssl rsa --help
14 | ```
15 |
16 | 构建特定版本的 OpenSSL
17 |
18 | ```
19 | #下载二进制包并解压缩
20 | $ wget https://www.openssl.org/source/openssl-1.1.0f.tar.gz
21 |
22 | $ tar xvf openssl-1.1.0f.tar.gz
23 | $ cd openssl-1.1.0f
24 |
25 | #查看安装手册
26 | $ more INSTALL
27 |
28 | #查看config
29 | ./config --help
30 |
31 | #安装并编译,安装目录不要和系统目录冲突
32 | $ ./config --prefix=/usr/local/openssl --openssldir=/usr/local/openssl
33 |
34 | $ make
35 | $ make test
36 | $ make install
37 | $ make clean
38 |
39 | #运行安装的 OpenSSL
40 | $ /usr/local/openssl/bin/openssl version
41 | OpenSSL 1.1.0f 25 May 2017
42 | ```
43 |
44 | 2:2.2.3 小节
45 |
46 | shell 命令生成随机数:
47 |
48 | ```
49 | # 使用外部熵生成随机数
50 | $ head -c 32 /dev/urandom | openssl enc -base64
51 |
52 | # openssl 工具生成随机数
53 | $ openssl rand -base64 24
54 | ```
55 |
56 | PHP 函数生成随机数:
57 |
58 | ```
59 | //初始化种子
60 | mt_srand();
61 | $randval = mt_rand();
62 | echo $randval;
63 | ```
64 |
65 | 3:2.4.4 小节
66 |
67 | (1)OpenSSL 命令行应用 AES 算法:
68 |
69 | ```
70 | //显示 enc 子命令帮助
71 | $ openssl enc --help
72 |
73 | # 采用 3des 算法
74 | $ openssl enc des3
75 |
76 | #采用 3des 算法
77 | $ openssl des3
78 |
79 | #显示系统支持的加密算法
80 | $ openssl list -cipher-algorithms
81 |
82 | $ echo "hello" >> file.txt
83 | #执行加密参数
84 | $ openssl enc -aes-256-cbc -salt -in file.txt -out file.enc -pass pass:mypassword -p
85 | #执行解密操作
86 | $ openssl enc -d -aes-256-cbc -in file.enc
87 | ```
88 |
89 | (2)PHP 语言应用 AES 算法
90 |
91 | ```
92 | class AES128Encryptor
93 | {
94 | // 128 表示的是分组长度,可以用 MCRYPT_RIJNDAEL_128 表示 AES 算法
95 | private $_cipher = MCRYPT_RIJNDAEL_128;
96 |
97 | // 分组模式
98 | private $_mode = MCRYPT_MODE_CBC;
99 |
100 | // 密钥
101 | private $_key;
102 |
103 | // 初始化向量长度
104 | private $_ivSize;
105 |
106 | // 构造函数
107 | public function __construct($key)
108 | {
109 | $this->_key = $key;
110 |
111 | // 可以从算法计算出初始化向量长度
112 | $this->_ivSize = mcrypt_get_iv_size($this->_cipher, $this->_mode);
113 |
114 | // 获取特定算法和分组模式对应的密钥长度
115 | $keyMaxLen = mcrypt_get_key_size($this->_cipher, $this->_mode);
116 |
117 | // 如果输入的密钥长度不合法,则直接报错
118 | if (strlen($key) > $keyMaxLen) {
119 | throw new Exception("error");
120 | }
121 | }
122 |
123 | // 加密数据
124 | public function encrypt($data)
125 | {
126 | // 获取特定算法和分组模式的分组长度
127 | $blockSize = mcrypt_get_block_size($this->_cipher, $this->_mode);
128 |
129 | // PKCS#7 填充标准
130 | $pad = $blockSize - (strlen($data) % $blockSize);
131 |
132 | // 生成随机的初始化向量
133 | $iv = mcrypt_create_iv($this->_ivSize, MCRYPT_DEV_URANDOM);
134 |
135 | // 密文包含初始化向量,而且是不加密的
136 | return $iv . mcrypt_encrypt(
137 | $this->_cipher,
138 | $this->_key,
139 | $data . str_repeat(chr($pad), $pad),
140 | $this->_mode,
141 | $iv
142 | );
143 | }
144 |
145 | // 解密
146 | public function decrypt($encryptedData)
147 | {
148 | // 从密文中获取初始化向量,初始化向量的长度等于分组长度
149 | $iv = substr($encryptedData, 0, $this->_ivSize);
150 |
151 | $data = mcrypt_decrypt(
152 | $this->_cipher,
153 | $this->_key,
154 | substr($encryptedData, $this->_ivSize),
155 | $this->_mode,
156 | $iv
157 | );
158 |
159 | // 去除填充
160 | $pad = ord($data[strlen($data) - 1]);
161 | return substr($data, 0, -$pad);
162 | }
163 | }
164 |
165 | // 密钥基于口令使用 Hash 算法生成,后续章节会介绍口令和 Hash 算法的概念。
166 | $hash = hash('SHA256', "password", true);
167 |
168 | // 密钥长度是 128 比特
169 | $key = substr($hash, 0, 16);
170 |
171 | $obj = new AES128Encryptor($key);
172 | // 加密
173 | $d = $obj->encrypt("hello");
174 |
175 | // 解密
176 | echo $obj->decrypt($d);
177 | ```
178 |
179 | 4:2.5.3 小节
180 |
181 | (1)通过 PHP 演示如何使用 HMAC 算法
182 |
183 | ```
184 | //在消息上附加 MAC 值
185 | function hmacSign($message, $key){
186 | return hash_hmac('sha256', $message, $key) . $message;
187 | }
188 |
189 | function hmacVerify($bundle, $key){
190 | //取出 HMAC 值
191 | $mac = mb_substr($bundle, 0, 64, '8bit');
192 |
193 | //取出原始消息
194 | $message = mb_substr($bundle, 64, null, '8bit');
195 |
196 | //进行比较
197 | return hash_equals(
198 | hash_hmac('sha256', $message, $key),
199 | $mac
200 | );
201 | }
202 |
203 | $ciphertext = "hello";
204 | $key = "000102030405060708090a0b0c0d0e0f";
205 | $message = hmacSign($ciphertext, $key);
206 | var_dump(hmacVerify($message, $key));
207 | ```
208 |
209 | (2)OpenSSL 演示 HMAC 算法
210 |
211 |
212 | 操作 Hash 算法:
213 |
214 | ```
215 | $ echo "hello" >>file.txt
216 | # 对文件 file.txt 通过 SHA-1 算法计算摘要值
217 | $ openssl dgst -sha1 file.txt
218 |
219 | # 对文件 file.txt 通过 SHA-1 算法计算摘要值 ,并将摘要值保存到文件 digest.txt
220 | $ openssl sha1 -out digest.txt file.txt
221 | ```
222 |
223 | 使用 OpenSSL 生成 HMAC 值:
224 |
225 | ```
226 | # 使用 HMAC-SHA-1 算法,结合密钥 "mykey" 对文件内容进行运算并生成 HMAC 值
227 | $ echo "hello" >>file.txt
228 | $ openssl dgst -sha1 -hmac "mykey" file.txt
229 | ```
230 |
231 | 5:2.5.4 小节
232 |
233 | (1)举例说明加密算法不能保证消息完整性,下面是破解代码
234 |
235 | ```
236 | // 密钥
237 | $key = "000102030405060708090a0b0c0d0e0f";
238 | $obj = new AES128Encryptor($key);
239 | $ciphertext = $obj->encrypt(1);
240 |
241 | // 对生成的密文值进行 Base64 编码
242 | $ciphertext = base64_encode($ciphertext) ;
243 |
244 | //构建替代字符,通过暴力破解方式去修改密文
245 | for ($i=41;$i<=90;$i++) {
246 | //a-z 字符
247 | $s[] =sprintf("%c",$i);
248 | }
249 |
250 | //构建替代字符
251 | for ($i=97;$i<=122;$i++) {
252 | //A-Z 字符
253 | $s[] =sprintf("%c",$i);
254 | }
255 | // = 和 + 两个字符
256 | $s[] = "=";
257 | $s[] = "+";
258 |
259 | for ($i=0;$i<54;$i++) {
260 | for ($j=0;$j<23;$j++) {
261 | $rd = $ciphertext;
262 | // 对密文进行篡改,每次修改一位
263 | $rd[$j] = $s[$i];
264 |
265 | if ($obj->decrypt(base64_decode($rd)) == 1) {
266 | echo "成功篡改:" . $ciphertext . "_" . $rd . "\n" ;
267 | exit;
268 | }
269 | }
270 | }
271 | ```
272 |
273 | (2)保证消息同时具备机密性和完整性
274 |
275 | ```
276 | // 加密密钥
277 | $key = "000102030405060708090a0b0c0d0e0f";
278 |
279 | // MAC 算法密钥,一般不同于加密密钥
280 | $mackey = "2510c39011c5be704182423e3a695e91";
281 |
282 | $obj = new AES128Encryptor($key);
283 |
284 | $plaintext = "hello";
285 |
286 | // 加密值
287 | $ciphertext = $obj->encrypt($plaintext);
288 |
289 | // MAC 值
290 | $mac = hash_hmac("sha256",$plaintext,$mackey);
291 |
292 | //通信的消息包含加密值和 MAC 值
293 | $message = base64_encode($ciphertext . $mac) ;
294 | echo $message;
295 | ```
296 |
297 | 6:2.6.4 小节
298 |
299 | (1)使用 OpenSSL 演示 RSA 算法
300 |
301 | 使用 genrsa 子命令生成密钥对,密钥对是一个文件:
302 |
303 | ```
304 | # 生成的密钥长度是 2048 比特
305 | $ openssl genrsa -out mykey.pem 2048
306 |
307 | # 口令结合 3DES 算法保护密钥对
308 | $ openssl genrsa -des3 -out mykey2.pem 2048
309 | ```
310 |
311 | 从密钥对中分离出公钥:
312 |
313 | ```
314 | $ openssl rsa -in mykey.pem -pubout -out mypubkey.pem
315 |
316 | # 需要输入口令才能分离公钥
317 | $ openssl rsa -in mykey2.pem -pubout -out mypubkey2.pem
318 | ```
319 |
320 | 校验密码对文件是否正确:
321 |
322 | ```
323 | $ openssl rsa -in mykey.pem -check -noout
324 | ```
325 |
326 | 显示公钥信息:
327 |
328 | ```
329 | $ openssl rsa -pubin -in mypubkey.pem -text
330 | ```
331 |
332 | 使用 rsautl 子命令进行数据加解和解密 :
333 |
334 | ```
335 | $ echo "hello" >>plain.txt
336 |
337 | # 使用密钥对加密,rsautl 命令默认的填充机制是 PKCS#1 v1.5
338 | $ openssl rsautl -encrypt -inkey mykey.pem -in plain.txt -out cipher.txt
339 |
340 | # 使用公钥加密,务必有 -pubin 参数表明 -inkey 参数输入的是公钥文件
341 | $ openssl rsautl -encrypt -pubin -inkey mypubkey.pem -in plain.txt -out cipher.txt
342 |
343 | # 解密
344 | $ openssl rsautl -decrypt -inkey mykey.pem -in cipher.txt
345 | ```
346 |
347 | (2)使用 PHP 演示 RSA 算法
348 |
349 | ```
350 | // 原始值
351 | $data = "hello";
352 |
353 | // 加载公钥文件
354 | $pkeyid = openssl_pkey_get_public("file://mypubkey.pem");
355 |
356 | // 使用 PKCS#1 v1.5 标准加密数据
357 | $bool = openssl_public_encrypt( $data, $encdata, $pkeyid, OPENSSL_PKCS1_PADDING );
358 | openssl_free_key($pkeyid);
359 |
360 | // 加载私钥文件
361 | $pkeyid = openssl_pkey_get_private("file://mykey.pem");
362 |
363 | // 遵循同样的标准解密文件
364 | openssl_private_decrypt($encdata, $descdata, $pkeyid, OPENSSL_PKCS1_PADDING);
365 | openssl_free_key($pkeyid);
366 |
367 | // 输出原始值和解密值
368 | echo $data."_".$descdata;
369 | ```
370 |
371 | 7:2.7.2 小节
372 |
373 | (1)PHP 演示如何使用 PBKDF2 函数
374 |
375 | ```
376 | $password = 'yOuR-pAs5w0rd-hERe';
377 | // 随机的盐值
378 | $salt = openssl_random_pseudo_bytes(12);
379 | $keyLength = 40;
380 | $iterations = 10000;
381 | $generated_key = openssl_pbkdf2($password, $salt, $keyLength, $iterations, 'sha256');
382 | //转换为 16 进制
383 | echo bin2hex($generated_key)."\n";
384 | echo base64_encode($generated_key)."\n";
385 | ```
386 |
387 | (2)OpenSSL 演示口令和 Salt
388 |
389 | ```
390 | $ echo "hello">>file.txt
391 | $ openssl enc -aes-256-cbc -salt -in file.txt -out file.enc -pass pass:password -p
392 |
393 | # 口令保护 RSA 密钥对
394 | $ openssl genrsa -des3 -out mykey2.pem 2048
395 | ```
396 |
397 | 8:2.8.4 小节
398 |
399 | (1)dhparam 和 genpkey 子命令介绍
400 |
401 | ```
402 | #生成一个 1024 比特的参数文件
403 | $ openssl dhparam -out dhparam.pem -2 1024
404 |
405 | #查看参数文件内容
406 | $ openssl dhparam -in dhparam.pem -noout -C
407 |
408 | #基于参数文件生成密钥对
409 | $ openssl genpkey -paramfile dhparam.pem -out dhkey.pem
410 |
411 | #查看密钥对文件内容
412 | $ openssl pkey -in dhkey.pem -text -noout
413 | ```
414 |
415 | (2)完整的 DH 协商例子
416 |
417 | ```
418 | # 通信双方的任何一方生成 DH 的参数文件,可以对外公开
419 | $ openssl genpkey -genparam -algorithm DH -out dhp.pem
420 |
421 | # 查看参数文件的内容,包括 p 和 g 等参数
422 | $ openssl pkeyparam -in dhp.pem -text
423 |
424 | # 发送方 A 基于参数文件生成一个密钥对
425 | $ openssl genpkey -paramfile dhp.pem -out akey.pem
426 | # 查看密钥对内容
427 | $ openssl pkey -in akey.pem -text -noout
428 |
429 | # 发送方 B 基于参数文件生成一个密钥对
430 | $ openssl genpkey -paramfile dhp.pem -out bkey.pem
431 | # 查看密钥对内容
432 | openssl pkey -in bkey.pem -text -noout
433 |
434 | # 发送方 A 拆出公钥文件 akey_pub.pem ,私钥自己保存
435 | $ openssl pkey -in akey.pem -pubout -out akey_pub.pem
436 |
437 | # 发送方 B 拆出公钥文件 bkey_pub.pem ,私钥自己保存
438 | $ openssl pkey -in bkey.pem -pubout -out bkey_pub.pem
439 |
440 | # 发送方 A 收到 B 发送过来的公钥,将协商出的密钥保存到 data_a.txt 文件
441 | $ openssl pkeyutl -derive -inkey akey.pem -peerkey bkey_pub.pem -out data_a.txt
442 |
443 | # 发送方 B 收到 A 发送过来的公钥,将协商出的密钥保存到 data_b.txt 文件
444 | $ openssl pkeyutl -derive -inkey bkey.pem -peerkey akey_pub.pem -out data_b.txt
445 | ```
446 |
447 | 9:2.9.2 小节
448 |
449 | 了解 ECC 曲线:
450 |
451 | ```
452 | # 查看系统有多少椭圆曲线,通信双方需要选择一条都支持的命名曲线
453 | $ openssl ecparam -list_curves
454 |
455 | # 生成一个参数文件,通过 -name 指定命名曲线
456 | $ openssl ecparam -name secp256k1 -out secp256k1.pem
457 |
458 | # 默认的情况下,查看参数文件只会显示曲线的名称
459 | $ openssl ecparam -in secp256k1.pem -text -noout
460 | ASN1 OID: secp256k1
461 |
462 | # 显示参数文件参数
463 | $ openssl ecparam -in secp256k1.pem -text -param_enc explicit -noout
464 | ```
465 |
466 | 10:2.9.3 小节
467 |
468 | ECDH 算法演示:
469 |
470 | ```
471 | # 生成参数文件
472 | $ openssl ecparam -name secp256k1 -out secp256k1.pem
473 |
474 | # A 和 B 各自生成一个 ECDH 私钥对文件
475 | $ openssl genpkey -paramfile secp256k1.pem -out akey.pem
476 | $ openssl genpkey -paramfile secp256k1.pem -out bkey.pem
477 |
478 | # A 和 B 分解出公钥,将公钥发送给对方
479 | $ openssl pkey -in akey.pem -pubout -out akey_pub.pem
480 | $ openssl pkey -in bkey.pem -pubout -out bkey_pub.pem
481 |
482 | # A 和 B 计算出同样的会话密钥
483 | $ openssl pkeyutl -derive -inkey akey.pem -peerkey bkey_pub.pem -out data_a.txt
484 | $ openssl pkeyutl -derive -inkey bkey.pem -peerkey akey_pub.pem -out data_b.txt
485 | ```
486 |
487 | 11:2.9.4 小节
488 |
489 | 显示系统存在的命名曲线:
490 |
491 | ```
492 | $ openssl ecparam -list_curves
493 | ```
494 |
495 | 12:2.10.4 小节
496 |
497 | (1)使用 OpenSSL 演示数字签名算法
498 |
499 | 使用 RSAES-PKCS1-V1_5 标准:
500 |
501 | ```
502 | # 生成一个 RSA 密钥对,密钥长度 1024 比特
503 | $ openssl genrsa -out rsaprivatekey.pem 1024
504 |
505 | # 从密钥对中分离出公钥
506 | $ openssl rsa -in rsaprivatekey.pem -pubout -out rsapublickey.pem
507 |
508 | # 对 plain.txt 文件使用 sha256 Hash 算法和签名算法生成签名文件 signature.txt
509 | $ echo "hello" >>plain.txt
510 | $ openssl dgst -sha256 -sign rsaprivatekey.pem -out signature.txt plain.txt
511 |
512 | # 用相同的摘要算法和签名算法校验签名文件,需要对比签名文件和原始文件
513 | $ openssl dgst -sha256 -verify rsapublickey.pem -signature signature.txt plain.txt
514 | ```
515 |
516 | 使用 RSASSA-PSS 标准:
517 |
518 | ```
519 | # 生成 RSA 密钥对
520 | $ openssl genrsa -out rsaprivatekey.pem 1024
521 | $ openssl rsa -in rsaprivatekey.pem -pubout -out rsapublickey.pem
522 |
523 | # 指定 RSASSA-PSS 标准
524 | $ openssl dgst -sha256 -sign rsaprivatekey.pem -sigopt rsa_padding_mode:pss -out signature.txt plain.txt
525 |
526 | # 验证签名
527 | $ openssl dgst -sha256 -verify rsapublickey.pem -sigopt rsa_padding_mode:pss -signature signature.txt plain.txt
528 | ```
529 |
530 | (2)PHP 演示数字签名
531 |
532 | ```
533 | // 签名和验签函数
534 | // $data 表示原始信息
535 | // $privatekeyFile 表示私钥文件,$publickeyFile 表示公钥文件
536 | function sign_verify($data, $privatekeyFile, $publickeyFile)
537 | {
538 | //口令,有的时候密钥对文件被口令和对称加密算法保护了
539 | $passphrase = '';
540 |
541 | //摘要算法
542 | $digestAlgo = 'sha512';
543 |
544 | //加载私钥文件
545 | $privatekey = openssl_pkey_get_private(file_get_contents($privatekeyFile), $passphrase);
546 |
547 | //最终生成的签名值
548 | $signature = '';
549 |
550 | //生成签名
551 | openssl_sign($data, $signature, $privatekey, $digestAlgo);
552 |
553 | //释放资源
554 | openssl_free_key($privatekey);
555 |
556 | //对签名值 base64 编码,以便在网络上传输
557 | $signature = base64_encode($signature);
558 |
559 | //加载公钥
560 | $publickey = openssl_pkey_get_public(file_get_contents($publickeyFile));
561 |
562 | //验签
563 | $verify = openssl_verify($data, base64_decode($signature), $publickey, $digestAlgo);
564 |
565 | //释放资源
566 | openssl_free_key($publickey);
567 |
568 | return $verify;
569 | }
570 |
571 | //RSA 私钥和公钥文件位置
572 | $rsaprivatekey = dirname(__FILE__) . "/rsaprivatekey.pem";
573 | $rsapublickey = dirname(__FILE__) . "/rsapublickey.pem";
574 |
575 | //假如返回 1 表示验证成功
576 | var_dump(sign_verify("hello", $rsaprivatekey, $rsapublickey));
577 |
578 | ```
579 |
580 | 13:2.11.2 小节
581 |
582 | 生成参数文件和密钥对文件:
583 |
584 | ```
585 | # 生成参数文件,类似于 DH 参数文件一样
586 | $ openssl dsaparam -out dsaparam.pem 1024
587 |
588 | # 通过参数文件生成密钥对 dsaprivatekey.pem
589 | $ openssl gendsa -out dsaprivatekey.pem dsaparam.pem
590 |
591 | # 对私钥使用 des3 算法进行加密
592 | $ openssl gendsa -out dsaprivatekey2.pem -des3 dsaparam.pem
593 |
594 | # 通过密钥对文件拆分出公钥
595 | $ openssl dsa -in dsaprivatekey.pem -pubout -out dsapublickey.pem
596 | ```
597 |
598 | 显示文件的信息:
599 |
600 | ```
601 | # 包括三个公共参数、公钥、私钥
602 | $ openssl dsa -in dsaprivatekey.pem -text
603 |
604 | # 公钥信息
605 | $ openssl dsa -pubin -in dsapublickey.pem -text
606 | ```
607 |
608 | 生成和验证签名:
609 |
610 | ```
611 | $ echo "hello" >plain.txt
612 |
613 | # 进行签名,可以查看 signature.txt 可以发现有原始信息 hello
614 | $ openssl dgst -sha256 -sign dsaprivatekey.pem -out signature.txt plain.txt
615 |
616 | # 验证签名
617 | $ openssl dgst -sha256 -verify dsapublickey.pem -signature signature.txt plain.txt
618 | Verified OK
619 | ```
620 |
621 | 14:2.11.4 小节
622 |
623 | (1)OpenSSL 演示 ECDSA 算法
624 |
625 | 直接生成 ECDSA 私钥:
626 |
627 | ```
628 | $ openssl ecparam -name secp256k1 -genkey -out ecdsa_priv.pem
629 | ```
630 |
631 | 显示私钥信息:
632 |
633 | ```
634 | $ openssl ec -in ecdsa_priv.pem -text -noout
635 | ```
636 |
637 | 拆分密钥对获取公钥:
638 |
639 | ```
640 | # 生成私钥对应的公钥
641 | $ openssl ec -in ecdsa_priv.pem -pubout -out ecdsa_pub.pem
642 |
643 | # 显示公钥信息
644 | $ openssl ec -in ecdsa_pub.pem -pubin -text -noout
645 | ```
646 |
647 | 生成签名值:
648 |
649 | ```
650 | $ echo "hello" >>plain.txt
651 |
652 | # Hash 算法使用 sha256 算法
653 | $ openssl dgst -sha256 -sign ecdsa_priv.pem -out signature.txt plain.txt
654 | ```
655 |
656 | 校验签名:
657 |
658 | ```
659 | $ openssl dgst -sha256 -verify ecdsa_pub.pem -signature signature.txt plain.txt
660 | Verified OK
661 | ```
662 |
663 | (2)PHP 演示 ECDSA 算法
664 |
665 | 使用 PHP 语言生成 ECDSA 密钥对和签名 :
666 |
667 | ```
668 | //对于 ECDSA 来说,增加了 curve_name 命名曲线参数
669 | $config = array(
670 | "private_key_bits" => 1024,
671 | "private_key_type"=>OPENSSL_KEYTYPE_EC,
672 | "curve_name"=>openssl_get_curve_names()[0],
673 | );
674 |
675 | //生成密钥对
676 | $new_key_pair = openssl_pkey_new($config);
677 |
678 | //从密钥对中导出私钥
679 | openssl_pkey_export($new_key_pair, $ecdsaprivate_key);
680 |
681 | //从密钥对中导出公钥
682 | $details = openssl_pkey_get_details($new_key_pair);
683 | $ecdsapublic_key = $details['key'];
684 |
685 | //将私钥写入文件
686 | $ecdsaprivatekey = dirname(__FILE__) . "/ecdsaprivatekey.pem";
687 | file_put_contents($ecdsaprivatekey, $ecdsaprivate_key);
688 |
689 | //将公钥写入文件
690 | $ecdsapublickey = dirname(__FILE__) . "/ecdsapublickey.pem";
691 | file_put_contents($ecdsapublickey, $ecdsapublic_key);
692 | ```
693 |
694 | 校验签名:
695 |
696 | ```
697 | var_dump(sign_verify("hello", $ecdsaprivatekey, $ecdsapublickey));
698 | ```
699 |
700 | 15:2.12.2 小节
701 |
702 | (1)OpenSSL speed 子命令参数
703 |
704 |
705 | ```
706 | $ openssl speed aes-128-cbc
707 | $ openssl speed -evp aes-128-cbc
708 |
709 | 显示非 evp 模式可以运行的密码学算法
710 | $ openssl list -cipher-commands
711 |
712 | # evp 模式
713 | $ openssl speed -evp aes-128-gcm
714 |
715 | $ openssl speed -multi 2
716 | ```
717 |
718 | (2)对称加密算法性能测试
719 |
720 | ```
721 | $ openssl speed -evp aes-128-gcm
722 | ```
723 |
724 | 比较不同对称加密算法的运算速度:
725 |
726 | ```
727 | $ openssl speed -evp rc4
728 | $ openssl speed -evp des-ede3-cbc
729 | $ openssl speed -evp seed-cbc
730 | $ openssl speed -evp camellia-128-cbc
731 | $ openssl speed -evp aes-128-cbc
732 | ```
733 |
734 | (3)AES 不同密钥长度的性能测试
735 |
736 | ```
737 | $ openssl speed -evp aes-128-cbc
738 | $ openssl speed -evp aes-192-cbc
739 | $ openssl speed -evp aes-256-cbc
740 | ```
741 |
742 | (4)AES-NI 指令集测试
743 |
744 | 查看机器是否支持 AES-NI 指令集:
745 |
746 | ```
747 | $ cat /proc/cpuinfo | grep aes
748 | ```
749 |
750 | 测试:
751 |
752 | ```
753 | # 禁止使用 AES-NI 指令集
754 | $ OPENSSL_ia32cap="~0x200000200000000" openssl speed -evp aes-128-cbc
755 |
756 | # 使用 AES-NI 指令集
757 | $ openssl speed -evp aes-128-cbc
758 | ```
759 |
760 | (5)加密模式的性能测试
761 |
762 | ```
763 | $ openssl speed -evp aes-128-cbc
764 | $ openssl speed -evp aes-128-gcm
765 | $ openssl speed -evp chacha20-poly1305
766 | ```
767 |
768 | (6)公开密钥算法性能测试
769 |
770 | ```
771 | $ openssl speed rsa1024
772 | ```
773 |
774 | (7)不同密钥长度的 RSA 加密解密测试
775 |
776 | ```
777 | $ openssl speed rsa
778 | ```
779 |
780 | (8)不同数字签名算法性能测试
781 |
782 | ```
783 | $ openssl speed dsa
784 | $ openssl speed rsa
785 | $ openssl speed ecdsa
786 | ```
787 |
788 | (9)密钥协商算法性能测试
789 |
790 | ```
791 | $ openssl speed ecdh
792 | ```
793 |
794 | (10)测试不同 Hash 算法性能
795 |
796 | ```
797 | $ openssl speed -evp md5
798 | $ openssl speed -evp sha1
799 | $ openssl speed -evp sha256
800 | $ openssl speed -evp sha384
801 | $ openssl speed -evp sha512
802 | ```
--------------------------------------------------------------------------------