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服务器 #

在创业HTTPS服务器之前,服务器首先需要创建公钥、私钥及证书,步骤如下

2.1 创建私钥 #

openssl genrsa -out privatekey.pem 1024

2.2 创建证书签名请求(Certificate Signing Request)文件 #

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文件。 所谓pfx文件,是指该文件内容必须符合公钥加密技术12号标准。

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

2.5 创建服务器 #

https.createServer(options,[requestListener]);
let https = require('https');
let fs = require('fs');
let path = require('path');
let key = fs.readFileSync(path.join(__dirname, 'privatekey.pem'));
let cert = fs.readFileSync(path.join(__dirname, 'certificate.pem'));
let opts = {
    key,
    cert
};
let server = https.createServer(opts, function (req, res) {
    console.log(req.url);
    if (req.url != '/favicon.ico') {
        res.setHeader('Content-Type', 'text/html');
        res.write(`<html><head><meta charset="utf8"/></head><body>hello</body></html>`);
        res.end();
    }
});
server.listen(443, function () {
    console.log('服务器端开始监听!');
    //server.close();
});
server.on('close', function () {
    console.log('服务器已被关闭!');
});

2.6 创建HTTPS客户端 #

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

let req = https.request(options,callback);
let https = require('https');
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"
let options = {
    hostname: '123.57.77.210',
    port: 443,
    path: '/',
    method: 'GET',
    agent: false
}
let req = https.request(options, function (res) {
    console.log(res.statusCode);
    console.log(res.headers);
    res.setEncoding('utf8');
    res.on('data', function (chunk) {
        console.log(chunk);
    });
});
req.end();