1. http通信有什么问题? #

1.1 可能被窃听 #

1.2 认证问题 #

2. HTTPS如何解决上述三个问题? #

HTTPS是在通信接口部分用 TLS(Transport Layer Security)协议。

3. SSL 和 TLS 的区别 #

3. SSL 协议 #

HTTPS 协议的主要功能基本都依赖于 TLS/SSL 协议,TLS/SSL 的功能实现主要依赖于三类基本算法:散列函数 、对称加密和非对称加密,其利用非对称加密实现身份认证和密钥协商,对称加密算法采用协商的密钥对数据加密,基于散列函数验证信息的完整性。

3.1 对称加密 #

3.2 非对称加密技术 #

3.3 完整性验证算法 #

3.4 工作方式 #

结合三类算法的特点,TLS 的基本工作方式是

3.5 SSL协议构成 #

3.6 HTTPS协议改进过程 #

3.6.1 针对窃听风险 #

黑客可以嗅探通信内容

对称加密算法的特点是加密和解密是使用同一个密钥,加解密速度快,典型的对称加密算法有DES、AES等。使用对称加密,客户端和服务端双方拥有相同的密钥,信息得到安全传输。 此种方式的缺点是:

3.6.2 安全传递密钥 #

非对称加密算法的特点加密和解密分别使用不同的密钥, 相对来说加解密速度较慢,典型的非对称加密算法有RSA、DSA等。客户端用公钥对请求内容加密,服务器使用私钥对内容解密,反之亦然。 此种方式的缺点是:

客户端C和服务器S进行通信,中间节点M截获了二者的通信; 节点M自己计算产生一对公钥pub_M和私钥 pri_M; C向S请求公钥时,M把自己的公钥pub_M发给了C; C 使用公钥pub_M加密的数据能够被M解密,因为M掌握对应的私钥 pri_M,而 C 无法根据公钥信息判断服务器的身份,从而 C 和 M 之间建立了“可信”加密连接; 中间节点 M 和服务器S之间再建立合法的连接,因此 C 和 S 之间通信被M完全掌握,M 可以进行信息的窃听、篡改等操作。

3.6 SSL密钥协商的过程如下 #

3.6.1. client_hello过程 #

客户端发起请求,以明文传输请求信息,包含版本信息,加密套件候选列表,压缩算法候选列表,随机数,扩展字段等信息,相关信息如下:

3.6.2. server_hello 过程 #

3.6.3. 证书校验,协商最后通信密钥 #

a. 客户端验证服务端证书的合法性,如果验证通过才会进行后续通信,否则根据错误情况不同做出提示和操作,合法性验证包括如下:

3.6.4. 验证协商密钥 #

a. Client发送ChangeCipherSpec,指示Server从现在开始发送的消息都是加密过的 b. Client发送Finishd,包含了前面所有握手消息的hash,可以让server验证握手过程是否被第三方篡改 c. 服务端发送ChangeCipherSpec,指示Client从现在开始发送的消息都是加密过的 d. Server发送Finishd,包含了前面所有握手消息的hash,可以让client验证握手过程是否被第三方篡改,并且证明自己是Certificate密钥的拥有者,即证明自己的身份

3.6.5 HTTPS完整建立连接过程,如下图 #

3.7 证书 #

证书的作用就是,我和服务端通信,我怎么知道这个服务端是我要真正通信的服务端呢

3.7.1 申请和发放证书流程如下 #

3.7.2 证书链 #

2. https服务器 #

2.1 创建私钥 #

openssl genrsa -out privatekey.pem 1024

2.2 创建证书签名请求 #

openssl req -new -key privatekey.pem -out certrequest.csr

2.3 获取证书,线上证书需要经过证书授证中心签名的文件;下面只创建一个学习使用证书 #

openssl x509 -req -in certrequest.csr -signkey privatekey.pem -out certificate.pem

2.4 创建pfx文件 #

openssl pkcs12 -export -in certificate.pem -inkey privatekey.pem -out certificate.pfx

2.5 创建服务器 #

创建HTTPS服务器同HTTP服务器大致相同,需要增加证书,创建HTTPS服务器时通过options参数设置。

https.createServer(options,[requestListener]);
import https from 'https';
import fs from 'fs';

var pk = fs.readFileSync('privatekey.pem'),
    pc = fs.readFileSync('certificate.pem');

var opts = {
    key: pk,
    cert: pc
};

var server = https.createServer(opts);

opts参数为一个对象,用于指定创建HTTPS服务器时配置的各种选项,下面只描述几个必要选项:

属性名 说明
pff 用于指定从pfx文件读取出的私钥、公钥以及证书(指定该属性后,无需再指定key、cert、ca)
key 用于指定后缀名为pem的文件,读出私钥
cert 用于指定后缀名为pem的文件,读出公钥
ca 用于指定一组证书,默认值为几个著名的证书授证中心

2.6 创建HTTPS客户端 #

在https模块中,可以使用request方法向其它使用HTTPS协议的网站请求数据

let req = https.request(options,callback);
const options = {
        hostname: 'localhost',
        port: 1443,
        path: '/',
        method: 'post',
        key: fs.readFileSync('privatekey.pem'),
        cert: fs.readFileSync('certificate.pem'),
        rejectUnhauthorized: false,
        agent: false // 从连接池中指定挑选一个当前连接状态为关闭的https.Agent
    },
    req = https.request(options);

// 或者
const options = {
        hostname: 'localhost',
        port: 1443,
        path: '/',
        method: 'post',
        key: fs.readFileSync('privatekey.pem'),
        cert: fs.readFileSync('certificate.pem'),
        rejectUnhauthorized: false,
    };
// 显示指定https.Agent对象
options.agent = new https.Agent(options);
var req = https.request(options);

3.8 让你的网站支持https #

git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt
chmod 777 ./letsencrypt-auto
./letsencrypt-auto certonly --standalone --email zhang_renyang@126.com -d itnewhand.com

/etc/letsencrypt/live/itnewhand.com/fullchain.pem
/etc/letsencrypt/live/itnewhand.com/privkey.pem

生成证书时要先停掉nginx