HTTP
Hyper Text Transfer Protocol
使用TCP端口默认为:80
超文本传输协议,是互联网上使用最广泛的一种协议,所有WWW文件必须遵循的标准。HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全。
HTTPS
Hyper Text Transfer Protocol over Secure Socket Layer
使用TCP端口默认为:443
安全的超文本传输协议,Netscape(网景公司)设计了 SSL(Secure Sockets Layer) 协议用于对Http协议传输的数据进行加密,保证会话过程中的安全性。SSL中文为 安全套接层 。
SSL简介
SSL协议位于TCP/IP协议与各种应用层协议(如HTTP)之间。SSL协议可分为两层:
- SSL Record Protocol (SSL记录协议)建立在可靠的传输协议(如TCP)上,为高层协议提供数据封装、压缩、加密等基本功能的支持;
- SSL Handshake Protocol (SSL握手协议)建立在记录协议上,用于在实际数据传输开始前,通讯双方进行身份验证、协商加密算法、交换加密秘钥等。
SSL协议即用到了 对称加密 也用到了 非对称加密(公钥加密),在建立传输链路时,SSL首先对 对称加密 的密钥使用公钥进行 非对称加密 ,链路建立好之后,SSL对传输内容使用 对称加密 。
- 对称加密 速度高,可加密内容大,用来加密会话过程中的消息。
- 公钥加密 加密速度慢,但能提供更好的身份认证技术,用来加密 对称加密 的秘钥。
https单向认证
Https在建立Socket连接之前,需要进行握手,具体过程如下:
客户端 | 单向认证 | 服务端 |
---|---|---|
>>> | 1. 发送客户端SSL版本等信息 | >>> |
<<< | 2. 服务端给客户端返回SSL版本、随机数等信息,以及服务器公钥 | <<< |
CHECK | 3. 客户端校验服务端证书是否合法,合法继续,否则警告 | WAIT |
>>> | 4. 客户端发送自己可支持的对称加密方案给服务端供选择 | >>> |
WAIT | 5. 服务端选择加密程度高的加密方式 | CHECK |
<<< | 6. 将选择好的加密方案以明文方式发送给客户端 | <<< |
>>> | 7. 客户端收到加密方式产生随机码,作为对称加密秘钥,使用服务器公钥加密后发给服务器 | >>> |
WAIT | 8. 服务端使用私钥对加密信息进行解密,获得对称加密秘钥 | CHECK |
--- | 9. 使用对称加密进行通信确保安全 | --- |
https双向认证
双向认证和单向认证原理基本差不多,只是除了客户端需要认证服务端以外,增加了服务端对客户端的认证,具体过程如下:
客户端 | 单向认证 | 服务端 |
---|---|---|
>>> | 1. 发送客户端SSL版本等信息 | >>> |
<<< | 2. 服务端给客户端返回SSL版本、随机数等信息,以及服务器公钥 | <<< |
CHECK | 3. 客户端校验服务端证书是否合法,合法继续,否则警告 | WAIT |
>>> | 4. 客户端校验通过后,将自己的证书和公钥发送至客户端 | >>> |
WAIT | 5. 对客户端校验,校验结束后获得客户端公钥 | CHECK |
>>> | 6. 客户端发送自己可支持的对称加密方案给服务端供选择 | >>> |
WAIT | 7. 服务端选择加密程度高的加密方式 | CHECK |
<<< | 8. 将选择好的加密方案以客户端公钥进行加密后方式发送给客户端 | <<< |
>>> | 9. 客户端收到加密方式,使用私钥进行解密,产生随机码,作为对称加密秘钥,使用服务器公钥加密后发给服务器 | >>> |
WAIT | 10. 服务端使用私钥对加密信息进行解密,获得对称加密秘钥 | CHECK |
--- | 11. 使用对称加密进行通信确保安全 | --- |
使用openssl进行证书生成
由于TLS(SSL)是基于非对称的加密体系,所以在开发前需要准备用于加密解密及验证的私钥及数字证书。这里分别为CA、服务器、客户端分别准备1套密钥及证书。
生成CA证书及秘钥
- 生成一个秘钥为ca-key.pem
openssl genrsa -out ca-key.pem -des 1024
- 根据秘钥ca-key.pem生成一个证书签名请求文件ca-csr.pem,根据这个文件可以签出秘钥对应的证书。在这里会要求填入相关信息,可以用“.”表示为空,但Common Name必须要填入对应域名,否则浏览器检查证书与签名域名不相符会不允许通过。
openssl req -new -key ca-key.pem -out ca-csr.pem
- 另可以不执行第一步,直接执行以下语句,也会自动生成一个private.pem以及ca-csr.pem。
openssl req -new -out ca-csr.pem
- 利用证书签名请求文件ca-csr.pem,并利用ca-key.pem签名生成证书ca-cert.pem。其中x509为证书格式X.509,-days为有效期天数。
openssl x509 -req -days 3650 -in ca-csr.pem -signkey ca-key.pem -out ca-cert.pem
- 当然,也可以拿着ca-csr.pem去权威的第三方申请一个证书,这样的话申请得到的证书是被接收的。现在我们自签自申证书,则如上所示使用证书签名请求文件签一个证书。
生成服务端证书及秘钥
- 生成一个服务器私钥为server-key.pem
openssl genrsa -out server-key.pem 1024
- 生成证书签名请求文件server-csr.pem
openssl req -new -key server-key.pem -out server-csr.pem
- 另,假如我们需要多DNS和多IP的主机使用同一个证书完成验证,则不能通过上面的命令来实现。我们需要一个openssl.cnf配置文件,并执行以下语句
openssl req -new -key server-key.pem -config openssl.cnf -out server-csr.pem
- openssl.cnf配置文件内容格式如下所示:
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = CN
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = BeiJing
localityName = Locality Name (eg, city)
localityName_default = YaYunCun
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = Domain Control Validated
commonName = Internet Widgits Ltd
commonName_max = 64
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = ns1.dns.com
DNS.2 = ns2.dns.com
DNS.3 = ns3.dns.com
IP.1 = 192.168.1.84
IP.2 = 127.0.0.1
IP.3 = 127.0.0.2
- 生成服务器证书为server-sert.pem,具体选项含义查询openssl
openssl x509 -req -days 730 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -in server-csr.pem -out server-cert.pem -extensions v3_req -extfile openssl.cnf
生成客户端证书及秘钥
- 生成客户端秘钥client-key.pem
openssl genrsa -out client-key.pem
- 生成证书签名请求文件client-csr.pem
openssl req -new -key client-key.pem -out client-csr.pem
- 生成服务器证书为server-sert.pem,具体选项含义查询openssl
openssl x509 -req -days 365 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -in client-csr.pem -out client-cert.pem
打包和转换
- 另外的,我们可以将服务器的私钥、证书、CAz证书打包成一个单独的.pfx或.p12文件以便于使用,比如.p12导入浏览器可以让浏览器信任该证书
openssl pkcs12 -export -in server-cert.pem -inkey server-key.pem -certfile ca-cert.pem -out server.pfx
openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem -certfile ca-cert.pem -out client.p12
- 证书的转换,由10打包好的文件,可以经过转换变为其他格式以下提供常见的格式转换方法
openssl pkcs12 -export -inkey test.key -in test.cer -out test.pfx
openssl pkcs12 -in test.pfx -nodes -out test.pem
openssl rsa -in test.pem -out test.key
openssl x509 -in test.pem -out test.crt
单向验证和双向验证的配置
node.js 实现HTTPS的配置
- 导入https, fs
var https = require ('https'); // https服务器
const fs = require("fs"); // 文件输入输出,用来导入证书
- 导入证书,利用fs导出三个证书并存入变量
var privateKey = fs.readFileSync('./cert/ca.key').toString();
var certificate = fs.readFileSync('./cert/ca.crt').toString();
var client_certificate = fs.readFileSync('./cert/client.crt').toString();
- https设置,利用键值对来进行设置,rrequestCert表示是否需要客户端证书,rejectUnauthorized表示如果客户端证书不符合则是否拒绝访问,这两个为true则意味着双向认证,否则为单向认证
var credentials = { key: privateKey,
cert: certificate,
ca: client_certificate,
requestCert: true,
rejectUnauthorized: true};
- 创建服务器对象,比http多了一个参数,即3中所提的credentials
var server = http.createServer(app); // 若http只需要一个参数就行
var server = https.createServer(credentials, app); // https需要参数
- 开启端口监听
server.listen(port); // port即为端口号