HTTPS基础内容
本科期间阅读笔记备份。
HTTP简介
HTTP模型:B/S
HTTP消息包括两部分:HTTP语义与HTML实体
HTTP语义
请求/响应消息示例:
POST /gsorganizationvalsha2g2 HTTP/1.1
Host: ocsp2.globalsign.com
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:67.0) Gecko/20100101 Firefox/67.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/ocsp-request
Content-Length: 79
Connection: close
从中看出HTTP包括三部分:请求行/响应行、HTTP头部、HTML实体(包括请求~与响应~)
其中,请求行包括:URL、HTTP版本。
响应行包括:HTTP版本、状态码、信息提示符。
Cookie与Session:技术设计不严谨,漏洞多
TCP/IP
计网内容:应用层、传输层、网络层、链路层、物理层
DNS解析、ICMP包、TCP包、UDP包、IP包、Frame,Buffer、三次握手、四次握手等。
Socket API
密码学基础
OpenSSL
Message Digest commands (see the `dgst' command for more details)
blake2b512 blake2s256 gost md4
md5 rmd160 sha1 sha224
sha256 sha384 sha512
Cipher commands (see the `enc' command for more details)
aes-128-cbc aes-128-ecb aes-192-cbc aes-192-ecb
aes-256-cbc aes-256-ecb base64 bf
bf-cbc bf-cfb bf-ecb bf-ofb
camellia-128-cbc camellia-128-ecb camellia-192-cbc camellia-192-ecb
camellia-256-cbc camellia-256-ecb cast cast-cbc
cast5-cbc cast5-cfb cast5-ecb cast5-ofb
des des-cbc des-cfb des-ecb
des-ede des-ede-cbc des-ede-cfb des-ede-ofb
des-ede3 des-ede3-cbc des-ede3-cfb des-ede3-ofb
des-ofb des3 desx rc2
rc2-40-cbc rc2-64-cbc rc2-cbc rc2-cfb
rc2-ecb rc2-ofb rc4 rc4-40
seed seed-cbc seed-cfb seed-ecb
seed-ofb
随机数
效率
随机性:不存在统计学偏差
不可预测性:无法推断
不可重现性:不重复
常见随机数生成器
外部熵生成随机数
head -c 32 /dev/urandom |openssl enc -base64
常见伪随机数生成算法:Blum Blum Shub、Mersenne Twister(马特赛特旋转演算法)、Linear congruential generator(线性同余法)
openssl生成伪随机数:
openssl rand -base64 24
密码学随机数生成:块密码算法CTR模式、摘要函数、流密码算法等。用途为密钥、初始化向量(IV)、nonce、salt。
Hash算法
MD5、SHA1、SHA2、SHA3
对称加密算法
流密码
RC4、ChaCha
块密码
推荐AES。
模式:ECB、CBC、CTR(CBC、CTR目前推荐)
MAC(Message Authentication Code)
分类:CBC-MAC与HMAC。
AD加密模式
- Encrypt-and-MAC(E&M)
- MAC-then-Encrypt(MtE)
- Encrypt-then-MAC(EtM)
AEAD加密模式
- CCM模式
- GCM模式
- ChaCha20-Poly1305
公钥密码
RSA
Openssl生成密钥对:
openssl genrsa -out key.pem 2048
3des加密密钥:
openssl genrsa -des3 -out key2.pem 2048
从密钥对中分离出公钥:
openssl rsa -in key.pem -pubout -out pubkey.pem
校验密钥对:
openssl rsa -in key.pem -check -noout
显示公钥信息:
openssl rsa -pubin -in pubkey.pem -text
openssl使用密钥对进行加密:
openssl rsatl -encrypt -inkey key.pem -in plain.txt -out cipher.enc
openssl使用公钥进行加密:
openssl rsatl -encrypt -pubin -inkey pubkey.pem -in plain.txt -out cipher.enc
openssl解密:
openssl rsatl -decrypt -inkey key.pem -in cipher.enc
note:如果需要指定机制,请在最后添加。比如PKCS#1 OAEP,就在句末添加-oaep。
密钥
密钥最重要,最重要的属性为长度。
生成密钥
足够长、不可预测,因此两种方法生成密钥:基于伪随机数生成器生成密钥,基于口令的加密。
口令与PEB算法
口令:弱密钥
PBKDF2算法:PRF(伪随机数函数)、Password、Salt、c(迭代数)、dkLen(密钥长度)
密钥传输与存储
静态密钥、动态密钥
密钥协商
采用动态密钥(也叫会话密钥)。
特点:
- 作用:加密解密通信数据。
- client与server需要协商会话密钥。
- 不用存储
RSA协商
服务器发送RSA公钥->随机数生成->客户端使用公钥加密会话密钥并发送->服务器私钥解密->通信通道完成
缺点:不能向前安全性
DH协商
通信双方生成p、g
->服务器发送参数给客户端
->客户端生成随机数a,计算yc=(g^a) mod p.yc为公钥
->服务器生成随机数b,随机数为私钥,计算ys=(g^b) mod p,ys为公钥
->yc发送给服务器,服务器计算Z=(yc^b) mod p
->ys发送给客户端,计算Z=(ys^a) mod p
->Z相等,完成
DH分类: 静态DH与临时DH(EDH)
DH密钥协商实践:
#生成1024bits参数
$ openssl dhparam -out dhparam.pem -2 1024
#查看参数文件
$ openssl dhparam -in dhparam.pem -noout -C
#基于参数生成密钥对
$ openssl genpkey -paramfile dhparam.pem -out dhkey.pem
#查看密钥对文件内容
$ openssl pkey -in dhkey.pem -text -noout
#通信双方任何一方生成DH参数文件,对外公开
$ openssl genpkey -genparam -algorithm DH -out dhp.pem
#查看参数文件内容
$ openssl pkeyparam -in dhp.pem -text
#发送方A基于参数文件生成一个密钥对
$ openssl genpkey -paramfile dhp.pem -out akey.pem
#发送方B基于参数文件生成一个密钥对
$ openssl genpkey -paramfile dhp.pem -out bkey.pem
#查看密钥对内容
$ openssl pkey -in bkey.pem -text -noout
#发送方A拆出公钥文件akey_pub.pem,私钥自己保存
$ openssl pkey -in akey.pem -pubout -out akey_pub.pem
#发送方B拆出公钥文件bkey_pub.pem,私钥自己保存
$ openssl pkey -in bkey.pem -pubout -out bkey_pub.pem
#发送方A收到B发送过来的公钥,将协商的密钥保存到data_a.txt
$ openssl pkeyutl -derive -inkey akey.pem -peerkey bkey_pub.pem -out data_a.txt
#发送方B收到A发送过来的公钥,将协商的密钥保存到data_b.txt
$ openssl pkeyutl -derive -inkey bkey.pem -peerkey akey_pub.pem -out data_b.txt
椭圆曲线密码学
命名曲线:系统预先设定的曲线标准
查看命名曲线:
openssl ecparam -list_curves
ECDH协商
#生成参数文件
$ openssl ecparam -name secp256k1 -out secp256k1.pem
#A、B生成各自ECDH私钥对文件
$ openssl genpkey -paramfile secp256k1.pem -out akey.pem
$ openssl genpkey -paramfile secp256k1.pem -out bkey.pem
#A、B分解出公钥,将公钥发送给对方
$ openssl pkey -in akey.pem -pubout -out akey_pub.pem
$ openssl pkey -in bkey.pem -pubout -out bkey_pub.pem
#A、B计算出同样的会话密钥
$ openssl pkeyutl -derive -inkey akey.pem -peerkey bkey_pub.pem -out data_a.txt
$ openssl pkeyutl -derive -inkey bkey.pem -peerkey akey_pub.pem -out data_b.txt
RSA数字签名
签名算法:
s=m^d (mod n)
解密签名算法公式:
m=s^e (mod n)
RSA数字签名实践
#生成RSA密钥对
$ openssl genrsa -out rsaprivatekey.pem 1024
#从密钥对分离出公钥
$ openssl rsa -in rsaprivatekey.pem -pubout -out rsapublickey.pem
#sha256数字签名
$ echo “hello”>>plain.txt
$ openssl dgst -sha256 -sign rsaprivatekey.pem -out signature.txt
#用相同摘要算法和签名算法校验文件
$ openssl dgst -sha256 -verify rsapublickey.pem -signature signature.txt plain.txt
其中默认使用RSAES-PKCS1-v1_5填充标准,可以指定RSASSA-PSS标准。
openssl dgst -sha256 -sign rsaprivatekey.pem -sigopt rsa_padding_mode:pss -out signature.txt plain.txt
openssl dgst -sha256 -verify rsapublickey.pem -sigopt rsa_padding_mode:pss -signature signature.txt plain.txt
DSA数字签名
生成参数文件和密钥对文件:
#生成参数文件
$ openssl dsaparam -out dsaparam.pem 1024
#通过参数文件生成密钥对
$ openssl gendsa -out dsakey.pem dsaparam.pem
#对秘钥文件使用dsa3算法加密
$ openssl gendsa -out dsakey.pem -des3 dsaparam.pem
#通过密钥对文件拆分公钥
$ openssl dsa -in dsakey.pem -pubout -out dsapubkey.pem
显示参数、密钥对信息:
#显示私钥三个公共参数
$ openssl dsa -in dsakey.pem -text
#显示公钥参数信息
$ openssl dsa -pubin -in dsapubkey.pem -text
生成和验证签名
$ echo 'hello' >plain.txt
#进行签名,查看signature.txt发现原始信息
$ openssl dgst -sha256 -sign dsakey.pem -out signature.txt plain.txt
#验证签名
$ openssl dgst -sha256 -verify dsapubkey.pem -signature signature.txt plain.txt
ECDSA数字签名
直接生成:
#直接生成ECDSA密钥
$ openssl ecparam -name secp256k1 -genkey -out ecdsakey.pem
#显示密钥信息
$ openssl ec -in ecdsakey.pem -text -noout
#拆分密钥对获取公钥
$ openssl ec -in ecdsakey.pem -pubout -out ecdsapub.pem
#显示公钥信息
$ openssl ec -in ecdsapub.pem -pubin -text -noout
生成签名:
$ echo 'hello'>plain.txt
#hash sha256
$ openssl dgst -sha256 -sign ecdsakey.pem -out signature.txt plain.txt
校验签名:
$ openssl dgst -sha256 -verify ecdsapub.pem -signature signature.txt plain.txt
算法性能与安全性
openssl speed -evp参数子命令
openssl speed aes-128-cbc
openssl speed -evp aes-128-cbc
openssl -decrypt:测试解密时间
openssl -elapsed:测试结果使用实际时间代替CPU用户时间
TLS宏观理解
HTTPS:HTTTP+TLS/SSL
TLS/SSL位于TCP与应用层之间。
TLS/SSL可以构建在TCP上,也能UDP上,称为DTLS协议。
TLS/SSL背后的协议
TLS/SSL协议包含以下几个关键步骤:
- 对称加密算法和HMAC算法保证数据机密性与完整性
- 加密块由主密钥生成(会话秘钥),主密钥由密码衍生算法分成多个密码块。
- 主密钥来自于预备主密钥。预备主密钥采用相同密码衍生算法转换为主密钥,采用DH(ECDH)或RSA算法协商。
核心步骤:认证、密钥协商、数据加密
加密算法和MAC算法
密码套件:决定了本次连接采用哪种加密算法、协商算法、HMAC算法。
密钥协商算法
RSA:客户端生成预备主密钥,用服务器公钥加密传递给服务器。
DH:静态DH与临时DH。
向前安全性
两个都缺乏向前安全性,即如果泄露服务器私钥,之前历史信息如果被拦截后将能解开其加密密钥块,从而所有历史信息都将被破解。
密钥衍生算法
两次运算:
- 预备主密钥转换出固定长度的朱密钥
- 朱密钥转换出任意数量、长度的密钥块
TLS/SSL中密钥衍生算法特点:
- 秘钥块个数、数量依赖于堆成加密算法和HMAC算法
- 需要输入参数包含输入值和salt
中间人攻击
这个其实就是拦截公钥请求,伪装向服务器请求,并中间换包,拦截信息。
PKI
CA认证的过程
网站PKI过程:
服务器实体希望网站HTTPS
->服务器生成公开密钥算法的密钥对
->生成一个CSR(证书签名请求)
->CA收到CSR
->审核通过,CA用自己构建的密钥对的私钥签名,签名值附在CSR中给服务器实体
->服务器部署证书
->客户端请求服务器,服务器接受请求,发送证书与RSA公钥
->浏览器接收判断CA证书,进行签名验证
->验证成功,校验证书申请者身份
->身份校验成功,进行秘钥协商
握手
- 认证
- 密码套件协商
- 密钥协商
- 握手消息完整性校验
全站HTTPS策略
- 301、302重定向技术
- HSTS技术
- 其他HTTP头部,比如Content-Security-Policy
混合内容
HTTPS页面引入非HTTPS元素。浏览器一般显示警示图标。
被动混合内容
包含的HTML标签为:audio、img、video、object。
主动混合内容
script、link(引用的CSS文件)、XMLHttpRequest请求对象、iframe、object对象。
构建HTTPS网站
下面是HTTPS网站部署的基本步骤
HTTPS网站构建分析
- 证书、域名、密钥对
- 迁移还是全新构建
- web应用类型
- 混合内容处理
- 系统架构
获取证书和密钥对
证书获取途径:自签名证书、Let's Encrypt证书、收费CA证书
# 自签名证书
浏览器不一定收集,存在伪造可能性。一般用于企业内部系统。
流程:
生成私钥对和CSR
$ openssl req \
-newkey res:1024 -nodes -keyout key.pem \
-out csr.pem
生成自签名证书
openssl x509 \
-signkey key.pem \
-in csr.pem \
-req -days 365 -out cert.pem
向CA机构申请证书
申请途径:专门CA机构申请或者代理机构申请。
具体方式:发送CSR文件或者同意生成证书与密钥对
CA核实申请者方式:申请者增加域名TXT记录,CA校验TXT记录;或者服务器放置HTTP校验文件,CA访问校验
使用Let's Encrypt证书
Let's Encrypt是免费的,我的博客也是用这个。
官方推荐使用CertBot客户端管理证书,管理基于ACME协议。
详细文档看这个网站:
以Ngnix的Ubuntu 18.04LTS服务器为例。
安装Certbot客户端:
$ sudo apt-get update #更新清单
$ sudo apt-get install software-properties-common
$ sudo add-apt-repository universe
$ sudo add-apt-repository ppa:certbot/certbot #添加源
$ sudo apt-get update
$ sudo apt-get install certbot python-certbot-nginx #安装Certbot客户端
使用Certbot客户端:
如果想自动完成证书安装与Certbot编辑Nginx设置,则输入:
$ sudo certbot --nginx
如果自己去调节Nginx设置,则输入:
$ sudo certbot --nginx certonly
如果想使用新的Let's encrypt ACMEv2服务,则也需要使用Cerbot的DNS模块。
$ sudo certbot -a dns-plugin -i nginx -d "*.example.com" -d example.com --server https://acme-v02.api.letsencrypt.org/directory
以上为CertBot官方提供的安装证书方法。
书中提供的是用git获取CertBot,之后执行:
#生成证书
./certbot-auto certonly --webroot -w /usr/nginx/web -d www.example.com
#example.com为你的域名
部署证书和密钥对
以Nginx为例子(因为我服务器也是Nginx反向代理的)
Nginx配置
安装Nginx,一般免费的够个人使用的了。如果是公司那还是付费比较好。
$ apt-get install nginx #安装nginx
$ nginx -v #检查版本
配置HTTPS:
$ vim /etc/nginx/sites-nginx/example.com-ssl.conf
修改内容如下
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com; #example.com换为你的域名
root /var/www/ghost/system/nginx-root;#web网站的nginx-root
#证书路径
ssl_certificate /etc/letsencrypt/example.com/fullchain.cer;
#密钥路径
ssl_certificate_key /etc/letsencrypt/example.com/example.com.key;
#SSL相关参数设置
include /etc/nginx/snippets/ssl-params.conf;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:2368;
}#反向代理
location ~ /.well-known {
allow all;
}
client_max_body_size 50m;
}
配置完重新启动Nginx
service nginx restart
测试HTTPS
使用Curl命令行:
$ curl "https://www.example.com" --verbose
也可以用开发人员工具。
301重定向
用vim修改nginx的网站config:
$ vim /etc/nginx/sites-nginx/example.com.conf
server{
listen 80;
server_name www.example.com;
rewrite ^ https://$server_name;
#如果是迁移的网站则为: rewrite ^ https://$server_name?request_uri? permanent
}
HSTS
避免默认HTTP连接、引擎HTTP链接、不信任证书继续HTTPS连接不安全等问题。
以Nginx为例,在Nginx的Server配置文件中添加:
add_header Strict-Transport-Security 'max-age=1000;includesSubDomains;Preload;'
CSP
解决混淆内容。
为了防止XSS攻击,由Mozilla制定。
以Nginx为例,添加服务配置文件内容:
add_header Content-Security-Policy "default-src 'self';:;
Let's encrypt证书更新
更新需要先停下Nginx服务:
$ service nginx stop
首先用git下载let's encrypt:
$ git clone https://github.com/letsencrypt/letsencrypt
如果之前git过了,直接进目录。下载之后也要进入目录:
$ cd letsencrypt
最后执行如下格式命令:
$ ./letsencrypt-auto certonly --standalone --email xxxxxxxxx@gmail.com -d www.example.com
更新结束后,启动Nginx服务:
$ service nginx start

浙公网安备 33010602011771号