zoukankan      html  css  js  c++  java
  • HTTPS

    HTTP? S?

    超文本传输安全协议HyperText Transfer Protocol Secure,常称为HTTP over TLS、HTTP over SSL或HTTP Secure)是一种通过计算机网络进行安全通信的传输协议。HTTPS经由HTTP进行通信,但利用SSL/TLS加密数据包。

    为什么要用HTTPS

    在网页上登录私人账号或者使用移动支付时,需要向服务端发送请求进行认证,通过请求头cookie或者token带上凭证,在服务端认证,然而在HTTP协议下,容易遭到中间人攻击,那通信就是在一个不安全信道内进行,也就不能保证交换数据的隐私与完整性。

    所以,

    HTTPS开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性

    主要作用是在不安全的网络上创建一个安全信道,并可在使用适当的加密包和服务器证书可被验证且可被信任时,对窃听中间人攻击提供合理的防护。

    HTTPS为什么是安全的

    HTTPS是如何保证在不安全的网络上信道安全?前面说过HTTPS是通过SSL/TSL加密数据包来实现HTTP的安全通信,所以问题的关键,SSL加密是怎么实现的?

    公钥加密和对称性加密的组合

    密钥是一种参数,它是在明文转换为密文或将密文转换为明文的算法中输入的参数。密钥分为对称密钥与非对称密钥。

    为什么交换密钥?

    客户端通过信道将消息发送给服务端,并对消息进行加密;接收方接收到消息,进行必要的解密,而这应该建立在接收者知道发送者如何加密的基础上;当服务端响应给客户端消息时,显然客户端应该知道服务端是如何加密的。

    所以加密和解密应在密钥交换的基础上进行。

    Symmetric Key Cryptography 对称密钥加密

    即密钥加密。发送方和接收方共享密钥,加密和解密使用相同的密钥,或者两个简单相互推算的密钥。

    1. 发送方发送消息时,加密算法接受密钥和消息作为参数,对消息进行加密,加密完成后,生成密文,并通过信道发送给接收方。
    2. 接收方接收到消息后,解密算法使用同样的密钥将密文解密为明文。
    3. 如果有第三方恶意监听截获密文,没有密钥也很难解密。即使暴力破解,也要消耗巨大算力,这显然不划算。

    在只有发送方和接收方知道密钥的情况下,才可以实现发送的密文可以被唯一解密。解密使用加密时的密钥,接收方和发送方使用同一密钥,这就是对称密钥加密。

    所以,能否实现对称加密,就看能否保证密钥只被接收方和发送方访问。

    如果通信是在一个不安全的信道内进行,如何保证?

    Public-key cryptography 公钥加密

    公钥密钥加密。它需要使用不同的密钥来分别完成加密和解密操作,一个公开发布,即公开密钥,另一个由用户自己秘密保存,即私用密钥。

    1. 发送方发送消息时,加密算法接受公钥和消息作为参数,加密完成后,密文通过不安全的信道发送给接收方。
    2. 接收方接收到消息后,解密算法使用私钥将密文解密。私钥只有接收方知道,所以只有接收方能解密。
    3. 第三方入侵者截获到加密消息,没有私钥也无法解密。

    为什么不能加密解密都使用公钥呢?公钥加密解密的开销太大。对称加密的速度比公钥加密快很多。

    SSL / TLS如何工作

    TSL使用公钥密码术在发送方和接收方之间建立公共密钥,然后使用对称密钥密码术进行进一步通信。

    一旦客户端和服务器都同意使用TLS协议,他们通过使用一个握手过程协商出一个有状态的连接以传输数据。通过握手,客户端和服务器协商各种参数用于创建安全连接:

    1. 客户端连接到服务器,发送Client Hello要求创建安全连接,握手开始

      • Client Hello 消息内容
      1. 支持的TLS协议版本
      2. 并列出受支持的密码组合(加密算法和加密哈希函数)
      3. 客户端生成的随机数RNc(用于之后的session key)
    2. 服务器从列表中决定加密和散列函数,发送Server Hello

      • Server Hello 消息内容
      1. 确认使用的TLS议版本,浏览器与服务器支持的版本不一致,服务器关闭通信
      2. 服务器生成的随机数RNs(用于之后的session key)
      3. 确认使用的加密算法和函数
    3. 服务器发回其数字证书,证书包括

      1. 服务器名称
      2. 授信机构(Certification Authentication)
      3. 服务器公钥(public key server)
    4. 客户端确认证书的有效性

    5. 服务器请求客户端公钥。客户端有证书则双向身份认证,无证书随机生成公钥。

    6. 客户端创建一个随机pre-master密钥,并使用服务端公钥对其加密,之后发给服务端

    7. 服务端接收到pre-master密钥。服务端和客户端基于pre-master密钥各自生成Master密钥和会话密钥(session key)

    8. 客户端发送"Change cipher spec"给服务端,表示客户端已经开始使用session key来对消息散列加密,同时发送"Client finished"消息

    9. 服务端接收到"Change cipher spec",将其记录层状态转换为使用Session key对称加密。发送"Server finished"消息到客户端。

    10. 之后双方可以在建立的安全信道上进行数据交换,所有消息通过Session key进行对称加密。

    任何一个步骤失败,TLS握手过程就会失败并断开连接。握手完毕后的连接是安全的,直到关闭连接。

    对称加密保证了通信的私密性,公钥加密保证数据的完整性。

    在传输层之上,建立了TLS协议,确保客户端和服务器之间的安全通信;在TLS之上,运行HTTP。

    SSL的配置

    如果在生产环境,要向用户提供服务,就要通过认证过程:通过证书颁发机构(Certification Authorities),颁发公共证书。

    这些证书颁发机构将验证你的凭据,确保你符合声明的身份。通过后,CA向你颁发一个公钥和一个私钥,在服务器站点使用。因此,一旦CA发出公钥和私钥,公钥将由CA认证,然后公钥也将携带公钥证书。这个证书也就是你的服务发送给客户端的证书。

    由于大多数浏览器都拥有这些CA的可信根证书,所以,他们将能够通过获取你的证书,然后在已知证书已由CA签名的情况下验证证书,生成你的私钥。这样,客户端建立起认证。

    但在开发环境下,如何配置公钥和私钥?

    使用OpenSSL生成自签名证书

    安装OpenSSL之后,在CMD窗口下

    C:OpenSSL-Win64inopenssl.cfg	// 打开openssl.cfg文件
    OpenSSL> genrsa -out private.key 1024	// 使用rsa算法,生成1024位长的私钥     没有-out,不会自动保存为文件,而是输出在命令行
    OpenSSL> req -new -key private.key -out cert.csr	// 生成certificate signing request文件
    OpenSSL> x509 -req -in cert.csr -signkey private.key -out certificate.pem	// 生成证书,可以分发给客户端
    

    Node配置HTTPS服务

    bin文件夹下,更改www文件如下

    . . . 
    var https = require('https')
    var fs = require('fs')
    
    . . . 
    app.set('secPort', port+443)	// https服务端口一般+443
    . . .
    //	配置HTTPS服务必须的私钥和证书
    var options = {
        key: fs.readFileSync(__dirname+'/private.key'),
        cert: fs.readFileSync(__dirname+'/certificate.pem')
    }
    // 创建HTTPS服务
    var secureServer = https.createServer(options, app)
    
    // 启动服务
    secureServer.listen(app.get('secPort'), () => {
        console.log('Server listening on port', app.get('secPort'))
    })
    secureServer.on('error', onError)
    secureServer.on('listening', onListening)
    

    更改spp.js文件

    app.all('*', (req, res, next) => {
        if (req.secure) {
            return next()
        } else {
            res.redirect(307, 'https://' + req.hostname + ':' + app.get('secPort') + req.url)
        }
    })
    
  • 相关阅读:
    JS中every()和some()的用法
    Git 各指令的本质
    vue登录3D效果
    vue打包后反编译到源代码(reverse-sourcemap)
    CSS Modules
    有了 HTTP 协议,为什么还需要 Websocket?
    微信小程序的实现原理
    JS
    微信小程序的发布流程
    中国地图
  • 原文地址:https://www.cnblogs.com/wydumn/p/12590658.html
Copyright © 2011-2022 走看看