├── 示例 ├── 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 | ![《深入浅出HTTPS:从原理到实战》](https://notes.newyingyong.cn/static/image/httpsbook/httpsbook-small.jpg?f) 10 | 11 | 4:如果想了解我,可以查看 [《我是谁》](https://mp.weixin.qq.com/s/ezBrPc5OIjUlHvCBOAVWKg) 12 | 13 | 5:我的公众号(ID:yudadanwx,虞大胆的叽叽喳喳) ,我会持续性更新,包含密码学&HTTPS相关信息。 14 | 15 | ![公众号](https://notes.newyingyong.cn/static/image/wxgzh/qrcode_258.jpg) 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 | ``` --------------------------------------------------------------------------------