SSL/TLS协议详解 - https为什么比http更安全

这篇具有很好参考价值的文章主要介绍了SSL/TLS协议详解 - https为什么比http更安全。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概述

  • SSL/TLS是世界上应用最广泛的密码通信方法。比如,在网上商城输入信用卡卡号时,Web浏览器就会使用SSL/TLS进行密码通信。使用SSL/TLS可以对通信对象进行认证,还可以确保通信内容的机密性。TLS相当于SSL的后续版本。
  • SSL (Secure Sockets Layer)安全套接层协议 :由Netscape公司开发。协议的第一个版本从未发布过,第二个版于1994年11月发布,但是存在严重漏洞,最终退出历史舞台。1995年年底,第三个版本SSL 3.0发布,此版本是完全重新设计的协议,因此该设计一直沿用到今天。
  • TLS(Transport Layer Security)安全传输层协议:1996年5月,TLS工作组成立,开始将SSL从Netscape迁移至IETF。最终,TLS 1.0于1999年1月问世,与SSL 3.0版本相比修改并不大,但还是改名为TLS。2006年4月,TLS 1.1发布,修复了一些关键的安全性问题。2008年8月,TLS 1.2发布,该版本添加了对已验证加密的支持,并且基本上删除了协议说明中所有硬编码的安全基元,使协议完全弹性化。

SSL/TLS、HTTP、HTTPS关系

  • HTTPS是安全版本的HTTP,简单理解 HTTPS = HTTP + SSL/TLS,即HTTPS就是使用SSL/TLS协议对HTTP报文进行了加密处理。
    SSL/TLS协议详解 - https为什么比http更安全

SSL/TLS单向认证和双向认证

  • 单向认证指的是通信双方只校验一方发送过来的数字证书,另一方不校验。通常是客户端根据服务器传过来的证书信息校验服务器的合法性。
  • 双向认证指的是在通信双方都要校验对方发送过来的数字证书,一般应用于对安全性要求更高的领域。

SSL/TLS握手过程

  • 这里先重点介绍下SSL/TLS双向认证的握手过程,SSL/TLS单向认证后面也会提到,并进行比对。
  • TLS握手涉及到加密算法和数字证书的知识。不了解的可参考我的另外两篇文章。加密算法简介 数字证书简介
  • 握手图示 图中虚线部分是双向认证时需要额外发送的消息。
  • 备注:不同的密钥协商算法计算预备主密钥的方法不一样,这里展示的是RSA密钥协商算法计算预备主密钥的方法。
  • 握手详解
    • [1] Client Hello
      • 客户端发送TLS版本,支持的加密套件列表给服务端,并生成客户端随机数发送给服务端。
      • Version : 表示客户端支持的SSL/TLS协议版本
      • Random : 客户端随机数
      • Session ID : 和会话恢复有关
      • Cipher Suites : 客户端支持的密码套件列表
        SSL/TLS协议详解 - https为什么比http更安全SSL/TLS协议详解 - https为什么比http更安全
      • Compression Methods : 客户端支持的压缩方法
      • Extension : 扩展项
    • [2] Server Hello
      • 服务端确认TLS版本,选择使用的加密套件,生成服务端随机数发送给客户端。
      • Version : 服务端根据客户端传递的版本号,选择一个双方都支持的版本
      • Random : 服务端随机数
      • Session ID : 和会话恢复有关
      • Cipher Suite : 根据客户端传递过来的密码套件列表,选择一个双方都支持的密码套件
      • Compression Method : 压缩算法
      • Extension : 扩展项
    • [3] Server Certificate
      • 该消息是可选的。根据协商出来的密码套件,服务端选择是否发送证书消息。在HTTPS网站中一般服务器会发送证书,如果协商出的密码套件是DH_anon或者ECDH_anon,则服务器不发送该消息,可能会遇到中间人攻击。
      • 服务器发送证书一般有两个目的:一是进行身份验证,二是证书中包含服务器的公钥,该公钥结合密码套件的密钥协商算法协商出预备主密钥。
    • [4] Server Key Exchange
      • 该消息是有条件才发送的。如果证书包含的信息不足以进行密钥交换,那么必须发送该消息。
      • 下列的密码套件,服务端会发送Server Key Exchange消息
        • DHE DSSDHE RSAECDHE ECDSAECDHE RSA
        • 上述密码套件都是使用临时DH/ECDH密码协商算法,客户端每次连接服务器的时候,服务器会发送动态DH信息,这些信息不存在服务端证书中,需要通过Server Key Exchange消息传递,传递的DH信息需要使用服务器的私钥进行签名,该私钥和证书中包含的服务器公钥是一对。
      • 下列的密钥套件,服务端也会发送Server Key Exchange消息
        • DH_anonECDH_anon
        • 使用的是静态DH/ECDH协商算法,但由于没有证书,所以需要Server Key Exchange消息传递相关DH信息,传递的DH消息需要使用服务器的私钥进行签名
      • 下列的密码套件不允许服务器发送Server Key Exchange消息
        • RSADH_DSSDH_RSA
        • 对于RSA密码套件,客户端计算出预备主密钥,然后使用服务器RSA公钥加密发送给服务端,服务端反解出预备主密钥即可,没有Server Key Exchange子消息也能完成密钥协商。
        • 对于DH_DSS/DH_RSA密钥套件,证书中已经包含静态DH信息,无须服务端额外发送Server Key Exchange子消息,客户端和服务端各协商出预备主密钥的一半密钥,结合起来就是预备主密钥。目前已经很少看到这样的密码套件,CA机构也不会在签发证书时包含静态DH信息。
    • [5] Certificate Request
      • 该消息表示想要收到客户端的证书,一般是双向认证时有该消息。
    • [6] Server Hello Done
      • 表示服务端发送了足够的消息,接下来等待和客户端协商出预备主密钥。
    • [7] Client Certificate
      • 发送客户端证书,一般是双向认证时会发送。
    • [8] Client Key Exchange
      • 消息结构
      •   struct {
          		select(KeyExchangeAlgorithm){
          			case rsa:
          				EncryptedPreMasterSecret;
          			case dhe_dss:
          			case dhe_rsa:
          			case df_dss:
          			case dh_rsa:
          			case dh_anon:
          				ClientDiffieHellmanPublic;
          			case ec_diffie)hellman:
          				ClientECHiffieHellmanPublic;
          		}exchange_keys;
          } ClientKeyExchange;
        
      • 针对不同的密码套件,该消息一般有三种处理逻辑
      • EncryptedPreMasterSecret
        • 如果 RSA算法用于身份验证和密钥交换,客户端会生成一个48字节的预备主密钥,然后用服务器证书中的公钥加密并发送给服务器端。最终发送的消息就是Encrypted PreMaster。
      • ClientDiffieHellmanPublic
        • 如果密码套件中密钥协商算法是 DH算法,客户端必须发送 DH公钥给服务器端。
      • ClientECDiffieHellmanPublic
        • 如果协商出的密码套件密钥协商算法是 ECDHE,客户端需要发送 ECDH公钥。
    • [9] 计算主密钥和密钥块
      • 计算预备主密钥,不同的密钥协商算法,计算方法不同。
      • RSA密钥协商算法
        • RSA密钥协商算法,生成预备主密钥比较简单,直接生成预备主密钥。
        • 然后使用服务端证书中的公钥加密预备主密钥,将加密后的预备主密钥发送给服务端。
        • 服务端接收到加密后的预备主密钥后,使用私钥解密,得到预备主密钥。
      • DH密钥协商算法
        • 服务器端生成DH参数和服务器DH密钥对,用RSA私钥签名DH参数和服务器DH公钥,最后将签名值、DH参数、服务器DH公钥发送给客户端。
        • 客户端通过服务器发送的证书中的RSA的公钥验证签名,获取到DH参数和服务器DH公钥。
        • 客户端通过DH参数生成客户端的DH密钥对,并将客户端DH公钥发送给服务器端。
        • 客户端通过客户端DH私钥和服务器端DH公钥计算出预备主密钥。
        • 服务器端接收到客户端的DH公钥,结合服务器的DH私钥计算出预备主密钥。
        • 最终客户端和服务器端计算出的预备主密钥能够保持一致。
      • 双方都拿到预备主密钥后,就可以根据以下公式计算出主密钥
      • master_secret = PRF(pre_master_secret, “master secret”, ClientHello.random + ServerHello.random)
      • 主密钥的长度固定是48字节。而预备主密钥的长度取决于密码套件算法,如果 RSA算法用来协商密钥,预备主密钥的长度是 48字节;如果 DH/ECDH算法用来协商密钥,长度取决于 DH /ECDH算法的公钥。
      • 计算出主密钥后,还需要根据主密钥计算出密钥块。密钥块主要有六个
      • Client MAC Key
      • Server MAC Key
      • Client Key
      • Server Key
      • Client IV
      • Server IV
      • MAC Key主要用于数据的完整性校验,Key用于加密数据。IV作为加密算法的初始化向量。
    • [10] Certificate verify
      • 证书验证。双向认证时有该消息,这个时候客户端已经把证书发送给服务端了,但客户端还要向服务器证明证书中对应的私钥的正确和自己是会话持有者。
    • [11] Change Cipher Spec
      • 通知对方,可以用协商好的密钥进行通信了。
    • [12] Finished [Encrypted Handshake Message]
      • 确认所有握手消息没有被篡改。

Nginx搭建HTTPS网站

  • 接下来用Nginx搭建一个HTTPS网站,实现SSL/TLS的双向认证。

  • 打开Nginx的配置文件/usr/local/nginx/conf/nginx.conf,HTTPS服务默认是注释的,去掉注释,并且需要再添加两个字段ssl_verify_clientssl_client_certificate

  •   # HTTPS server
      server {
      	listen       10088 ssl;
      	server_name  localhost;
    
      	# 服务端证书
      	ssl_certificate      server.crt;
      	# 服务端证书密钥
      	ssl_certificate_key  server.key;
    
      	ssl_session_cache    shared:SSL:1m;
      	ssl_session_timeout  5m;
      	
      	# 表示开启客户端证书校验
      	ssl_verify_client on;
      	# 放置CA证书
      	ssl_client_certificate ca.crt;
    
      	ssl_ciphers  HIGH:!aNULL:!MD5;
      	ssl_prefer_server_ciphers  on;
    
      	location / {
      		root   html;
      		index  index.html index.htm;
      	}
      }
    
  • 这里需要用到三张证书,CA证书,服务端证书和客户端证书,可以通过OpenSSL命令行工具来生成。

  • CA证书

    • 生成RSA私钥
    • openssl genrsa -out ca.key 2048
    • 生成CA证书
    • openssl req -new -x509 -key ca.key -out ca.crt -days 365
  • 服务端证书

    • 生成服务端密钥
    • openssl genrsa -out server.key 2048
    • 生成证书请求文件
    • openssl req -new -key server.key -out server.csr
    • 使用CA证书签发服务端证书
    • openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt -days 365
  • 客户端证书

    • 生成客户端密钥
    • openssl genrsa -out client.key 2048
    • 生成证书请求文件
    • openssl req -new -key client.key -out client.csr
    • 使用CA证书签发客户端证书
    • openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt -days 365
    • 将客户端证书和私钥合并成pfx证书
    • openssl pkcs12 -export -in client.crt -inkey client.key -out client.pfx
  • 服务端证书以及私钥和CA证书生成后,放到Nginx配置文件所在目录下,然后将客户端的pfx证书拷贝到windows平台下,打开Edge浏览器的设置界面,在隐私、搜索和服务栏找到管理证书,然后把刚才的client.pfx证书导入即可。这里注意下,导入后要关掉浏览器重新打开。
    SSL/TLS协议详解 - https为什么比http更安全
    SSL/TLS协议详解 - https为什么比http更安全

  • 然后去访问对应https网站,浏览器会弹出对话框,让我们选择对应的客户端证书。只有选择证书并确认后,才可以成功访问到对应的https网站。没有客户端证书或者未成功选择证书,都是无法访问的。如果是单向认证的话,就不需要客户端证书了。
    SSL/TLS协议详解 - https为什么比http更安全

WireShark抓包分析SSL/TLS握手过程

  • 接下来就用WireShark抓包工具详细分析SSL/TLS双向认证的握手过程。

  • 先看下整体流程,抓包可以看到,在进行SSL/TLS握手前,先要进行TCP的三次握手,建立连接。关于TCP的握手过程,这里就不介绍了,可参考我的这一篇文章 抓包分析TCP协议
    SSL/TLS协议详解 - https为什么比http更安全

  • 接下来对SSL/TLS握手的每条信息,详细看一下

  • Client Hello

    • Client Hello消息中有TLS版本号,客户端生成的随机数,以及客户端支持的密码套件等信息。
      SSL/TLS协议详解 - https为什么比http更安全
  • Server Hello

    • Client Hello消息中有TLS版本号,服务端生成的随机数,以及服务端最终确认要使用的密码套件等信息。
      SSL/TLS协议详解 - https为什么比http更安全
  • Server Certificate

    • 服务端发送自己的证书
      SSL/TLS协议详解 - https为什么比http更安全
  • Server Key Exchange
    SSL/TLS协议详解 - https为什么比http更安全

  • Certificate Request

    • 表示服务端想要收到客户端的证书
      SSL/TLS协议详解 - https为什么比http更安全
  • Server Hello Done

    • 服务端请求结束
      SSL/TLS协议详解 - https为什么比http更安全
  • Client Certificate

    • 客户端发送自己的证书
      SSL/TLS协议详解 - https为什么比http更安全
  • Client Key ExChange

    • 上面选择的加密套件是 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,密钥协商算法是ECDHE,因此这里发送的消息是ClientECDiffieHellmanPublic
      SSL/TLS协议详解 - https为什么比http更安全
    • 如果选择的加密套件密钥协商算法为RSA,比如 TLS_RSA_WITH_AES_128_GCM_SHA256 加密套件,则对应发送的消息就为 EncryptedPreMasterSecret。
      SSL/TLS协议详解 - https为什么比http更安全
  • Certificate Verify

    • 客户端证书验证
      SSL/TLS协议详解 - https为什么比http更安全
  • Change Cipher Spec

    • 通知对方,可以用协商好的密钥进行通信了。
      SSL/TLS协议详解 - https为什么比http更安全
  • Finished [Encrypted Handshake Message]

    • 密钥协商完成
      SSL/TLS协议详解 - https为什么比http更安全
  • Application Data

    • 用协商好的密钥进行加密通信
      SSL/TLS协议详解 - https为什么比http更安全
  • 这就是整个SSL/TLS协议握手的过程。

  • 上面展示的是SSL/TLS双向认证的过程,可以关掉Nginx对客户端的证书校验,实现单向认证。
    SSL/TLS协议详解 - https为什么比http更安全

  • 这是单向认证时抓的包,可以与上面的双向认证比对下,主要少了服务端请求客户端发送证书的消息Certificate Request,客户端发送证书消息Client Certificate,客户端证书校验消息Certificate verify。其他流程和双向认证是一样的。文章来源地址https://www.toymoban.com/news/detail-452570.html

C/C++代码实现SSL/TLS通信

  • 我们还可以使用C/C++代码来实现SSL/TLS的通信
  • 服务端代码
    •   #include <stdio.h>
        #include <stdlib.h>
        #include <memory.h>
        #include <errno.h>
        #include <sys/types.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <arpa/inet.h>
        #include <unistd.h>
        #include <openssl/rsa.h>     
        #include <openssl/crypto.h>
        #include <openssl/x509.h>
        #include <openssl/pem.h>
        #include <openssl/ssl.h>
        #include <openssl/err.h>
        #include <openssl/rand.h>
      
        #define CERTF   "server.crt" /*服务端的证书(需经CA签名)*/
        #define KEYF   "server.key"  /*服务端的私钥(建议加密存储)*/
        #define CACERT "ca.crt" /*CA 的证书*/
        #define PORT   10088   /*准备绑定的端口*/
      
        int main (){
            SSL_load_error_strings();            /*为打印调试信息作准备*/
            OpenSSL_add_ssl_algorithms();        /*初始化*/
      
            SSL_CTX* ctx = SSL_CTX_new(TLSv1_server_method());
            if(ctx == NULL) {
                printf("SSL_CTX_new failed.\n");
                return -1;
            }
      
            SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);   /*是否验证客户端证书,双向认证时开启*/
            SSL_CTX_load_verify_locations(ctx,CACERT,NULL); /*若验证,则放置CA证书*/
      
            if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) {
                ERR_print_errors_fp(stderr);
                return -1;
            }
      
            if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) {
                ERR_print_errors_fp(stderr);
                return -1;
            }
      
            if (!SSL_CTX_check_private_key(ctx)) {
                printf("Private key does not match the certificate public key\n");
                return -1;
            }
      
            SSL_CTX_set_cipher_list(ctx,"RC4-MD5"); 
      
            /*开始正常的TCP socket过程.*/
            printf("Begin TCP socket...\n");
      
            int listenSock = socket(AF_INET, SOCK_STREAM, 0);  
            if(listenSock == -1){
                perror("socket");
                return -1;
            }
      
            struct sockaddr_in sa_serv;
            memset (&sa_serv, 0, sizeof(sa_serv));
            sa_serv.sin_family = AF_INET;
            sa_serv.sin_addr.s_addr = INADDR_ANY;
            sa_serv.sin_port = htons(PORT);         
      
            if(bind(listenSock, (struct sockaddr*) &sa_serv, sizeof (sa_serv)) == -1){
                perror("bind");
                return -1;
            }
      
            /*接受TCP链接*/
            if(listen (listenSock, 5) == -1){
                perror("listen");
                return -1;
            }                   
      
            struct sockaddr_in sa_cli;
            socklen_t client_len = sizeof(sa_cli);
            int connfd = accept (listenSock, (struct sockaddr*) &sa_cli, &client_len);
            if(connfd == -1){
                perror("accept");
                close (listenSock);
                return -1;
            }
      
            printf ("[%s:%d] connected...\n", inet_ntoa(sa_cli.sin_addr), sa_cli.sin_port);
      
            /*TCP连接已建立,进行服务端的SSL过程. */
            printf("Begin server side SSL\n");
      
            SSL* ssl = SSL_new (ctx);
            if(ssl == NULL){
                printf("SSL_new failed.\n");
                return -1;
            }
      
            SSL_set_fd (ssl, connfd);
            
            int sslSock = SSL_accept (ssl);
            if(sslSock == -1){
                ERR_print_errors_fp(stderr);
                return -1;
            }
      
            printf("SSL_accept finished\n");
      
            /*打印所有加密算法的信息(可选)*/
            printf ("SSL connection using %s\n", SSL_get_cipher(ssl));
      
            /*得到客户端的证书并打印些信息(可选) */
            X509* client_cert = SSL_get_peer_certificate (ssl);
            if (client_cert != NULL) {
                printf ("Client certificate:\n");
      
                char* subStr = X509_NAME_oneline(X509_get_subject_name (client_cert), 0, 0);
                if(subStr == NULL){
                printf("X509_NAME_oneline subject failed.\n");
                return -1;
                }
      
                printf ("subject: %s\n", subStr);
                //Free (subStr);
      
                char* issStr = X509_NAME_oneline(X509_get_issuer_name  (client_cert), 0, 0);
                if(issStr == NULL){
                printf("X509_NAME_oneline subject failed.\n");
                return -1;
                }
      
                printf ("issuer: %s\n", issStr);
                //Free (issStr);
      
                X509_free (client_cert);/*如不再需要,需将证书释放 */
            }else{
                printf ("Client does not have certificate\n");
            }
                
            char buf[4096] = {0};  
            /* 数据交换开始,用SSL_write,SSL_read代替write,read */
            int readSize = SSL_read(ssl, buf, sizeof(buf) - 1);  
            if(readSize == -1){
                ERR_print_errors_fp(stderr);
                return -1;
            }
      
            printf ("SSL_read buf[%d] = {%s}\n", readSize, buf);
      
            if(SSL_write (ssl, "Welcome to Connect to Server!", strlen("Welcome to Connect to Server!")) == -1){
                ERR_print_errors_fp(stderr);
                return -1;
            } 
      
            shutdown (connfd, 2);
            SSL_free (ssl);
            SSL_CTX_free (ctx);
            return 0;
        }
      
  • 客户端代码
    •   #include <stdio.h>
        #include <stdlib.h>
        #include <memory.h>
        #include <errno.h>
        #include <sys/types.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <arpa/inet.h>
        #include <unistd.h>
        #include <openssl/rsa.h>     
        #include <openssl/crypto.h>
        #include <openssl/x509.h>
        #include <openssl/pem.h>
        #include <openssl/ssl.h>
        #include <openssl/err.h>
        #include <openssl/rand.h>
      
        /*所有需要的参数信息都在此处以#define的形式提供*/
        #define CERTF  "client.crt"  /*客户端的证书(需经CA签名)*/
        #define KEYF  "client.key"   /*客户端的私钥(建议加密存储)*/
        #define CACERT "ca.crt"      /*CA 的证书*/
        #define PORT   10088          /*服务端的端口*/
        #define SERVER_ADDR "127.0.0.1"  /*服务段的IP地址*/
      
        int main () {
            /*初始化*/
            OpenSSL_add_ssl_algorithms(); 
      
            //载入所有SSL错误消息
            SSL_load_error_strings();     
      
            /*采用什么协议(SSLv2/SSLv3/TLSv1)在此指定*/
            /*申请SSL会话环境*/
            SSL_CTX *ctx = SSL_CTX_new(TLSv1_client_method());
            if(ctx == NULL){
                printf("SSL_CTX_new failed!\n");
                return -1;
            }                       
            
            /*是否验证服务端证书*/
            SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);
      
            /*若验证对方,则放置CA证书*/
            SSL_CTX_load_verify_locations(ctx,CACERT,NULL); 
      
            /*加载自己的证书*/
            if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) {
                ERR_print_errors_fp(stderr);
                return -1;
            }
            
            /*加载自己的私钥,以用于签名*/
            if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) {
                ERR_print_errors_fp(stderr);
                return -1;
            }
      
            /*调用了以上两个函数后,检验一下自己的证书与私钥是否配对*/
            if (!SSL_CTX_check_private_key(ctx)) {
                printf("Private key does not match the certificate public key\n");
                return -1;
            } 
      
            /*以下是正常的TCP socket建立过程*/
            printf("Begin tcp socket...\n");
      
            int sock = socket(AF_INET, SOCK_STREAM, 0);
            if(sock == -1){
                perror("socket");
                return -1;
            }       
      
            struct sockaddr_in sa;
            memset (&sa, 0, sizeof(sa));
            sa.sin_family = AF_INET;
            sa.sin_addr.s_addr = inet_addr(SERVER_ADDR);   /* Server IP */
            sa.sin_port = htons(PORT);          /* Server Port number */
      
            if(connect(sock, (struct sockaddr*) &sa, sizeof(sa)) == -1){
                perror("connect");
                return -1;
            } 
      
            /* TCP 链接已建立.开始 SSL 握手过程 */
            printf("Begin SSL negotiation \n");
      
            /*申请一个SSL套接字*/
            SSL* ssl = SSL_new (ctx);
            if(ssl == NULL){
                printf("SSL_new failed.\n");
                return -1;
            }
      
            /*绑定读写套接字*/
            SSL_set_fd(ssl, sock);
      
            if(SSL_connect(ssl) == -1){
                ERR_print_errors_fp(stderr);
                return -1;
            }
      
            /*打印所有加密算法的信息(可选)*/
            printf ("SSL connection using %s\n", SSL_get_cipher(ssl));
      
            /*得到服务端的证书并打印些信息(可选) */
            X509* server_cert = SSL_get_peer_certificate (ssl); 
            if(server_cert == NULL){
                printf("SSL_get_peer_certificate failed.\n");
                return -1;
            }     
            
            printf ("Server certificate:\n");
      
            char* subStr = X509_NAME_oneline(X509_get_subject_name (server_cert),0,0);
            if(subStr == NULL){
                printf("X509_NAME_oneline subject failed.\n");
                return -1;
            }
      
            printf("subject: %s\n", subStr);
            // Free(subStr);
      
            char* issStr = X509_NAME_oneline (X509_get_issuer_name(server_cert),0,0);
            if(issStr == NULL){
                printf("X509_NAME_oneline issuer failed.\n");
                return -1;
            }
      
            printf ("issuer: %s\n", issStr);
            // Free (issStr);
      
            X509_free(server_cert);  /*如不再需要,需将证书释放 */
      
            /* 数据交换开始,用SSL_write,SSL_read代替write,read */
            printf("Begin SSL data exchange\n");
      
            if(SSL_write(ssl, "Hello, I am client!", strlen("Hello, I am client!")) == -1){
                ERR_print_errors_fp(stderr);
                return -1;
            } 
      
            char buf[4096] = {0};
            int readSize = SSL_read(ssl, buf, sizeof(buf) - 1); 
            if(readSize == -1){
                ERR_print_errors_fp(stderr);
                return -1;
            }
      
            printf ("SSL_read buf[%d] = {%s}\n", readSize, buf);
      
            SSL_shutdown (ssl);  /* send SSL/TLS close_notify */
      
            shutdown (sock, 2);
            SSL_free (ssl);
            SSL_CTX_free (ctx);
      
            return 0;
        }
      
  • Makefile
    •   all: server client
        server: server.cpp
            g++ -o server server.cpp -lssl -lcrypto
        client: client.cpp
            g++ -o client client.cpp -lssl -lcrypto
      
        clean:
            rm server client
      

参考资料

  • 《HTTPS权威指南》
  • 《深入浅出HTTPS从原理到实战》
  • 《图解密码技术》

到了这里,关于SSL/TLS协议详解 - https为什么比http更安全的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • HTTP/HTTPS、SSL/TLS、WS/WSS 都是什么?

    有同学问我, HTTP/HTTPS 、 SSL/TLS 、 WS/WSS 这都是些什么?那我们就先从概念说起: HTTP 是超文本传输协议,信息是通过明文传输。 HTTPS 是在 HTTP 的基础上信息通过加密后再传输。 SSL 是实现 HTTPS 信息传输加密的算法。 TLS 是 SSL 的经过更新迭代后更安全的版本。 上诉概念可以

    2024年02月05日
    浏览(41)
  • 什么是HTTPS加密协议?HTTPS安全传输原理,SSL和TLS介绍,NGINX如何配置SSL证书

    HTTPS是超文本传输协议(HTTP)的安全版本。它使用SSL(安全套接层)或TLS(传输层安全)加密协议来保护数据传输的安全性和机密性,以防止未经授权的访问和窃听。HTTPS协议通常用于处理敏感信息,如在线支付或登录凭证等。可以通过URL的前缀来识别一个网站是否使用了H

    2024年02月03日
    浏览(59)
  • 为什么 HTTPS 比 HTTP 安全

    HTTP(超文本传输协议)是目前互联网应用最广泛的协议,伴随着人们网络安全意识的加强,HTTPS 被越来越多地采纳。不论是访问一些购物网站,或是登录一些博客、论坛等,我们都被 HTTPS 保护着,甚至 Google Chrome、Firefox 等主流浏览器已经将所有基于 HTTP 的站点都标记为不安全

    2024年02月19日
    浏览(51)
  • 为什么 https 比 http 更安全?

    http 和 https 在许多网站都有用到,但是现在都是极力倡导使用 https ,究其原因就是 http 的安全性不够高,在数据传输过程中可能会遭到黑客窃取。 本篇文章会先讲解 http 缺点,然后再讲解 https 是如何解决这些问题来保证安全的。 一、http 缺点 通信使用明文(不加密),内容

    2024年01月24日
    浏览(47)
  • 为什么客户端和服务器不支持SSL协议

    为什么客户端和服务器不支持SSL协议?这是使用 SSL证书 的用户经常会遇到了一个问题,客户端和服务器不支持SSL协议可能有以下几个原因,大家可以作个参考。 版本不匹配:SSL协议有多个版本,包括过时的SSL 2.0、SSL 3.0和较新的TLS(Transport Layer Security)版本(如TLS 1.0、TLS

    2024年04月25日
    浏览(49)
  • 为什么说HTTPS比HTTP安全? HTTPS是如何保证安全的?

    在上篇文章中,我们了解到 HTTP 在通信过程中,存在以下问题: 通信使用明文(不加密),内容可能被窃听 不验证通信方的身份,因此有可能遭遇伪装 而 HTTPS 的出现正是解决这些问题, HTTPS 是建立在 SSL 之上,其安全性由 SSL 来保证 在采用 SSL 后, HTTP 就拥有了 HTTPS 的加密

    2024年03月19日
    浏览(55)
  • HTTPS工作过程,国家为什么让http为什么要换成https,Tomcat在MAC M1电脑如何安装,Tomcat的详细介绍

    目录 引言 一、HTTPS工作过程 二、Tomcat 在访达中找到下载好的Tomcat文件夹(这个要求按顺序) zsh: permission denied TOMCAT的各部分含义: 在密码中一般是:明文+密钥-密文(加密) ,密文+密钥-明文(解密) 那么为什么大家放弃了原有的http换为https呢? 这我们就要先介绍一下H

    2024年02月08日
    浏览(53)
  • 为什么 HTTPS 协议能保障数据传输的安全性?

    HTTP 协议 在谈论 HTTPS 协议之前,先来回顾一下 HTTP 协议的概念。 HTTP 协议介绍 HTTP 协议是一种基于文本的传输协议,它位于 OSI 网络模型中的应用层。 HTTP 协议是通过客户端和服务器的请求应答来进行通讯,目前协议由之前的 RFC 2616 拆分成立六个单独的协议说明(RFC 7230、

    2024年01月22日
    浏览(52)
  • 为什么如此安全的https协议却仍然可以被抓包呢?(1)

    好了,阅读到了这里,说明你对https已经非常熟悉了,那么你一定知道,https协议是结合了非对称加密和对称加密一起工作,从而保证数据传输的安全性的。 非对称加密用于确保客户端可以安全地获取到服务器的真实公钥。对称加密用于确保客户端和服务器之间的数据传输不

    2024年04月26日
    浏览(41)
  • 为什么有了HTTP,还需要WebSocket协议?

    目录 WebSocket是什么? WebSocket怎样建立连接? WebSocket的实际用途 WebSocket 与 HTTP 的选择 HTTP 是基于 TCP协议 的,同一时间里,客户端和服务器只能有一方主动发数据,是 半双工通信 。 通常,打开某个网页,我们每点击一次网页上的某个选项,前端就会发送一次HTTP请求,网站

    2024年02月11日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包