织梦CMS - 轻松建站从此开始!

罗索实验室

当前位置: 主页 > 基础技术 > 高性能服务器 >

openssl 学习之SSL/TLS

jackyhwei 发布于 2016-07-13 10:59 点击:次 
之前在微博上看到一个分享,关于HTTPS的,原文链接The First Few Milliseconds of an HTTPS Connection,加上最近也在学习openssl 的相关知识。所以也进行简单的实验,并整理一些资料,以加深对SSL、TLS的了解。
TAG: TLS  OpenSSL  

之前在微博上看到一个分享,关于HTTPS的,原文链接The First Few Milliseconds of an HTTPS Connection,加上最近也在学习openssl 的相关知识。所以也进行简单的实验,并整理一些资料,以加深对SSL、TLS的了解。

一,基本概念

SSL 是安全套接层(Secure Socket Layer)的缩写,而TLS表示传输层安全(Transport Layer Security)的缩写。SSl最初由网景公司提出,最初目的是为了保护web安全,然而现在用来提高传输层的安全。TLS是IETF基于SSLv3制 定的标准,两者基本一致,只有少许的差别。首先我们来看一下SSLv3 /TLS协议在TCP/IP协议栈中的位置,通常我们认为SSLv3 /TLS处于传输层和应用层之间。而将SSLv3/TLS通常又分为握手层和记录层,如下图所示:


图片1

1,Handshake 握手协议的基本功能

(1)服务器认证

(2)客户端认证(可选)

(3)算法协商

(4)密钥生成

2,Change Cipher Spec 更改密码规范协议

在安全协商后,服务器和客户端会交互这条消息,来提示使用协商好的安全参数

3,Alert 警告协议

(1)提供报错机制

(2)安全断连机制

二,WireShark 实验

首先来了解一下SSLv3/TLS协议流程,如下图所示,而4,6这两个过程通常不会出现在我们的浏览器访问过程中。下面我们以WireShark来分析浏览器访问https://github.com 来了解一下TLS建链路的过程。


图片1

1 Client  Hello  

从下图中,可以看出,采用的TLS协议版本为1.1,握手协议为Client hello,主要包含以下信息:32字节的随机数random;Session ID;客户端支持的密码套件Cipher Suites 以及压缩算法Compression Methods。

  1. //RFC中Random的定义 
  2. struct 
  3. uint32gmt_unix_time;//格林威治时间 
  4. opaquerandom_bytes[28]; 
  5. }Random; 
  6. //RFC中ClientHello的定义 
  7. struct
  8. ProtocolVersionclient_version; 
  9. Randomrandom; 
  10. SessionIDsession_id; 
  11. CipherSuitecipher_suites<2..2^16-1>; 
  12. CompressionMethodcompression_methods<1..2^8-1>; 
  13. }ClientHello; 

图片1

2 Server Hello

服务器端消息定义如下同clientHello的区别是,服务器端选择双方支持的密码套件及压缩算法,在下图中可以看到选择的密码套件为:TLS_RSA_WITH_RC4_128_SHA,而压缩算法为NULL即不支持压缩。

  1. struct { 
  2.     ProtocolVersion server_version; 
  3.     Random random; 
  4.     SessionID session_id; 
  5.     CipherSuite cipher_suite; 
  6.     CompressionMethod compression_method; 
  7. } ServerHello; 

图片1

 

3~6  Send certificate and Server Hello Done

服务气短讲证书链发送给客户端。证书链中证书的顺序是每个证书的签名都由随后证书的公 钥进行验证。紧接着是一个Sever Hello Done的消息,因为这边包含可选的认证,发送Server Hello Done表明服务器端hello 信息结束。因为服务器没有要求验证客户端身份故4和6步骤没有。


图片1

7~13 key exchange and change cipher spec

至此链路建立


图片1

三,Openssl 中相关函数

 

SSL协议源码位于ssl目录下。它实现了sslv2、sslv3、TLS以及DTLS(Datagram TLS,基于UDP的TLS实现)。ssl实现中,对于每个协议,都有客户端实现(XXX_clnt.c)、服务端实现(XXX_srvr.c)、加密实现(XXX_enc.c)、记录协议实现(XXX_pkt.c)、METHOD方法(XXX_meth.c)、客户端服务端都用到的握手方法实现(XXX_both.c),以及对外提供的函数实现(XXX_lib.c)。

 

四,Polarssl 中的SSL实例

Polarssl 是一个轻量级的ssl 适合用于嵌入式平台中,我简单看了一下其中的代码结构,感觉非常清晰。看其中的代码也便于理解SSL。具体代码可以查看 polarssl/programs/ssl 下的几个文件。下面列出一些客户端关键的代码,服务器端可以自己查看代码,理解如何自己建立SSL链路。

  1. //客户端  
  2.    /* 
  3.      * 1.1. Load the trusted CA 
  4.      */ 
  5. #if defined(POLARSSL_CERTS_C) 
  6. ret = x509parse_crt( &cacert
  7. , (const unsigned char *) test_ca_crt,strlen( test_ca_crt ) ); 
  8. #endif 
  9.  
  10.     /* 
  11.      * 1.2. Load own certificate and private key 
  12.      * 
  13.      * (can be skipped if client authentication is not required) 
  14.      */ 
  15.     printf( "  . Loading the client cert. and key..." ); 
  16. #if defined(POLARSSL_CERTS_C) 
  17. ret = x509parse_crt( &clicert
  18. , (const unsigned char *) test_cli_crt,strlen( test_cli_crt ) ); 
  19. #endif 
  20.  
  21. #if defined(POLARSSL_CERTS_C) 
  22. ret = x509parse_key( &rsa
  23. , (const unsigned char *) test_cli_key,strlen( test_cli_key ), NULL, 0 ); 
  24. #endif 
  25.  
  26.     /* 
  27.      * 2. Start the connection 
  28.      */ 
  29.     printf( "  . Connecting to tcp/%s/%-4d...", opt.server_name, opt.server_port ); 
  30.     if( ( ret = net_connect( &server_fd, opt.server_name,opt.server_port ) ) != 0 ) 
  31.     { 
  32.     .... 
  33.     } 
  34.     /* 
  35.      * 3. Setup stuff 
  36.      */ 
  37.     printf( "  . Setting up the SSL/TLS structure..." ); 
  38.     if( ( ret = ssl_init( &ssl ) ) != 0 ) 
  39.     { 
  40.     .... 
  41.     } 
  42.     ssl_set_endpoint( &ssl, SSL_IS_CLIENT ); 
  43.     ssl_set_authmode( &ssl, opt.auth_mode ); 
  44.     ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg ); 
  45.     ssl_set_dbg( &ssl, my_debug, stdout ); 
  46.     ssl_set_bio( &ssl, net_recv, &server_fd, 
  47.                        net_send, &server_fd ); 
  48.     if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER ) 
  49.         ssl_set_ciphersuites( &ssl, opt.force_ciphersuite ); 
  50.     ssl_set_renegotiation( &ssl, opt.renegotiation ); 
  51.     ssl_legacy_renegotiation( &ssl, opt.allow_legacy ); 
  52.     ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name ); 
  53.     ssl_set_own_cert( &ssl, &clicert, &rsa ); 
  54.     ssl_set_hostname( &ssl, opt.server_name ); 
  55.  
  56.     if( opt.min_version != -1 ) 
  57.         ssl_set_min_version( &ssl, SSL_MAJOR_VERSION_3, opt.min_version ); 
  58.     if( opt.max_version != -1 ) 
  59.         ssl_set_max_version( &ssl, SSL_MAJOR_VERSION_3, opt.max_version ); 
  60.     /* 
  61.      * 4. Handshake 
  62.      */ 
  63.     printf( "  . Performing the SSL/TLS handshake..." ); 
  64.     fflush( stdout ); 
  65.  
  66.     while( ( ret = ssl_handshake( &ssl ) ) != 0 ) 
  67.     { 
  68.         if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE ) 
  69.         { 
  70.         .... 
  71.         } 
  72.     } 
  73.     /* 
  74.      * 5. Verify the server certificate 
  75.      */ 
  76.     printf( "  . Verifying peer X.509 certificate..." ); 
  77.  
  78.     if( ( ret = ssl_get_verify_result( &ssl ) ) != 0 ) 
  79.     { 
  80.         printf( " failed\n" ); 
  81.          ... 
  82.         printf( "\n" ); 
  83.     } 
  84.  
  85.     printf( "  . Peer certificate information    ...\n" ); 
  86.     x509parse_cert_info( (char *) buf, sizeof( buf ) - 1
  87. " ",ssl_get_peer_cert( &ssl ) ); 
  88.     /* 
  89.      * 6. Write the GET request 
  90.      */ 
  91.     len = sprintf( (char *) buf, GET_REQUEST, opt.request_page ); 
  92.     while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 ) 
  93.     { 
  94.      ... 
  95.     } 
  96.     /* 
  97.      * 7. Read the HTTP response 
  98.      */ 
  99.     printf( "  < Read from server:" ); 
  100.     fflush( stdout ); 
  101.  
  102.     do 
  103.     { 
  104.         ret = ssl_read( &ssl, buf, len ); 
  105.         .... 
  106.     }while(1); 
  107.     ssl_close_notify( &ssl ); 

关键握手协议在ssl_handshake函数中,循环调用ssl_handshake_step,直至握手过程完成。

  1. int ssl_handshake( ssl_context *ssl ) 
  2.     int ret = 0; 
  3.  
  4.     SSL_DEBUG_MSG( 2, ( "=> handshake" ) ); 
  5.  
  6.     while( ssl->state != SSL_HANDSHAKE_OVER ) 
  7.     { 
  8.         ret = ssl_handshake_step( ssl ); 
  9.  
  10.         if( ret != 0 ) 
  11.             break
  12.     } 
  13.  
  14.     SSL_DEBUG_MSG( 2, ( "<= handshake" ) ); 
  15.  
  16.     return( ret ); 

client端最后调用的是ssl_handshake_client_step函数,在library/ssl_cli.c中,代码注释非常清晰,不再复述。

  1. int ssl_handshake_client_step( ssl_context *ssl ) 
  2.     int ret = 0; 
  3.  
  4.     if( ssl->state == SSL_HANDSHAKE_OVER ) 
  5.         return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); 
  6.  
  7.     SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) ); 
  8.  
  9.     if( ( ret = ssl_flush_output( ssl ) ) != 0 ) 
  10.         return( ret ); 
  11.  
  12.     switch( ssl->state ) 
  13.     { 
  14.         case SSL_HELLO_REQUEST: 
  15.             ssl->state = SSL_CLIENT_HELLO; 
  16.             break
  17.  
  18.        /* 
  19.         *  ==>   ClientHello 
  20.         */ 
  21.        case SSL_CLIENT_HELLO: 
  22.            ret = ssl_write_client_hello( ssl ); 
  23.            break
  24.  
  25.        /* 
  26.         *  <==   ServerHello 
  27.         *        Certificate 
  28.         *      ( ServerKeyExchange  ) 
  29.         *      ( CertificateRequest ) 
  30.         *        ServerHelloDone 
  31.         */ 
  32.        case SSL_SERVER_HELLO: 
  33.            ret = ssl_parse_server_hello( ssl ); 
  34.            break
  35.  
  36.        case SSL_SERVER_CERTIFICATE: 
  37.            ret = ssl_parse_certificate( ssl ); 
  38.            break
  39.  
  40.        case SSL_SERVER_KEY_EXCHANGE: 
  41.            ret = ssl_parse_server_key_exchange( ssl ); 
  42.            break
  43.  
  44.        case SSL_CERTIFICATE_REQUEST: 
  45.            ret = ssl_parse_certificate_request( ssl ); 
  46.            break
  47.  
  48.        case SSL_SERVER_HELLO_DONE: 
  49.            ret = ssl_parse_server_hello_done( ssl ); 
  50.            break
  51.  
  52.        /* 
  53.         *  ==> ( Certificate/Alert  ) 
  54.         *        ClientKeyExchange 
  55.         *      ( CertificateVerify  ) 
  56.         *        ChangeCipherSpec 
  57.         *        Finished 
  58.         */ 
  59.        case SSL_CLIENT_CERTIFICATE: 
  60.            ret = ssl_write_certificate( ssl ); 
  61.            break
  62.  
  63.        case SSL_CLIENT_KEY_EXCHANGE: 
  64.            ret = ssl_write_client_key_exchange( ssl ); 
  65.            break
  66.  
  67.        case SSL_CERTIFICATE_VERIFY: 
  68.            ret = ssl_write_certificate_verify( ssl ); 
  69.            break
  70.  
  71.        case SSL_CLIENT_CHANGE_CIPHER_SPEC: 
  72.            ret = ssl_write_change_cipher_spec( ssl ); 
  73.            break
  74.  
  75.        case SSL_CLIENT_FINISHED: 
  76.            ret = ssl_write_finished( ssl ); 
  77.            break
  78.  
  79.        /* 
  80.         *  <==   ChangeCipherSpec 
  81.         *        Finished 
  82.         */ 
  83.        case SSL_SERVER_CHANGE_CIPHER_SPEC: 
  84.            ret = ssl_parse_change_cipher_spec( ssl ); 
  85.            break
  86.  
  87.        case SSL_SERVER_FINISHED: 
  88.            ret = ssl_parse_finished( ssl ); 
  89.            break
  90.  
  91.        case SSL_FLUSH_BUFFERS: 
  92.            SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); 
  93.            ssl->state = SSL_HANDSHAKE_WRAPUP; 
  94.            break
  95.  
  96.        case SSL_HANDSHAKE_WRAPUP: 
  97.            ssl_handshake_wrapup( ssl ); 
  98.            break
  99.  
  100.        default
  101.            SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); 
  102.            return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); 
  103.    } 
  104.  
  105.     return( ret ); 

 

(kkxgx)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www1.rosoo.net/a/201607/17455.html]
本文出处:CSDN博客 作者:kkxgx 原文
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容