zoukankan      html  css  js  c++  java
  • SSL证书制作并使用NodeJs进行HTTPS认证配置

    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协议可分为两层:

    1. SSL Record Protocol (SSL记录协议)建立在可靠的传输协议(如TCP)上,为高层协议提供数据封装、压缩、加密等基本功能的支持;
    2. SSL Handshake Protocol (SSL握手协议)建立在记录协议上,用于在实际数据传输开始前,通讯双方进行身份验证、协商加密算法、交换加密秘钥等。

    SSL协议即用到了 对称加密 也用到了 非对称加密(公钥加密),在建立传输链路时,SSL首先对 对称加密 的密钥使用公钥进行 非对称加密 ,链路建立好之后,SSL对传输内容使用 对称加密

    1. 对称加密 速度高,可加密内容大,用来加密会话过程中的消息。
    2. 公钥加密 加密速度慢,但能提供更好的身份认证技术,用来加密 对称加密 的秘钥。

    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证书及秘钥

    1. 生成一个秘钥为ca-key.pem
    openssl genrsa -out ca-key.pem -des 1024
    1. 根据秘钥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
    1. 利用证书签名请求文件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去权威的第三方申请一个证书,这样的话申请得到的证书是被接收的。现在我们自签自申证书,则如上所示使用证书签名请求文件签一个证书。

    生成服务端证书及秘钥

    1. 生成一个服务器私钥为server-key.pem
    openssl genrsa -out server-key.pem 1024
    1. 生成证书签名请求文件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  
    1. 生成服务器证书为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

    生成客户端证书及秘钥

    1. 生成客户端秘钥client-key.pem
    openssl genrsa -out client-key.pem 
    1. 生成证书签名请求文件client-csr.pem
    openssl req -new -key client-key.pem -out client-csr.pem
    1. 生成服务器证书为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

    打包和转换

    1. 另外的,我们可以将服务器的私钥、证书、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 
    1. 证书的转换,由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的配置

    1. 导入https, fs
    var https = require ('https');  // https服务器
    const fs = require("fs");       // 文件输入输出,用来导入证书
    1. 导入证书,利用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();
    1. https设置,利用键值对来进行设置,rrequestCert表示是否需要客户端证书,rejectUnauthorized表示如果客户端证书不符合则是否拒绝访问,这两个为true则意味着双向认证,否则为单向认证
    var credentials = { key: privateKey, 
                        cert: certificate, 
                        ca: client_certificate, 
                        requestCert: true, 
                        rejectUnauthorized: true};
    1. 创建服务器对象,比http多了一个参数,即3中所提的credentials
    var server = http.createServer(app);                // 若http只需要一个参数就行
    var server = https.createServer(credentials, app);  // https需要参数
    1. 开启端口监听
    server.listen(port);    // port即为端口号
     

    喜欢这篇文章?欢迎打赏~~

  • 相关阅读:
    spring对返回结果的拦截器
    mysql 8.0.15 的my.ini 配置
    利用apache 的PropertyUtilsBean 实现map和pojo相互转换
    给数字补0
    清空文件的内容 和 统计文件的大小的命令
    MySQL的replace函数的用法
    PHP Warning: Module 'modulename' already loaded in Unknown on line 0 的解决方法
    技术总监Sycx的故事
    编译PHP扩展的通用方法
    给大家推荐几本经典技术书籍
  • 原文地址:https://www.cnblogs.com/cangqinglang/p/14046281.html
Copyright © 2011-2022 走看看