TLS建立在TCP之上,建立TLS连接前需要TCP4次握手。然后进行TLS连接。在连接中要完成秘钥交换,交换算法不同,握手过程细节也会不同。
至此加密通信所用的秘钥都已生成,在此之前都是明文发送。客户端通知服务器启用加密通信并加密发送之前所发信息的摘要,服务器也做一样的事,用于验证加密通信是否可行。发送的两个消息分别是“Change Cipher Spec”和“Finished”。之后就可使用加密的Http请求和响应。
上述方式验证了服务器的安全性,而服务器验证客户端可用更多方式,比如账号密码,此时已经达到了加密通信的标准。
更深层次的客户端验证,也可Client Hello中出示客户端证书,用以验证。最终实现更为安全的双向验证。比如银行的U盾。
1证书的生成:openssl genrsa -des3 -out host.key 2048 生成签发机构密钥 openssl req -new -x509 -days 7305 -key host.key -out host.crt 生成签发用证书 openssl genrsa -des3 -out applier.pem 1024 请求认证的公司生成私钥 openssl rsa -in applier.pem -out applier.key 生成applier.pem对应的解密密钥applier.key openssl req -new -key applier.pem -out applier.csr 请求认证的证书申请 openssl ca -policy policy_anything -days 1460 -cert host.crt -keyfile host.key -in applier.csr -out applier.crt Ca对applier.csr签名并发布证书applier.crt //认证环境 mkdir -p CA/newcerts touch CA/index.txt touch CA/serial echo "01" >CA/serial 2 Nginx的配置 Server{ Listen 443 ssl default_server Index index.html index.htm Location / { Root /rootdir } Ssl on Ssl_certificate /path/applier.crt #提供证书 Ssl_certificate_key /path/applier.key #提供解密私钥 } 访问时通过https协议直接访问localhost,此时浏览器会与服务器握手并收到证书消息,由于试验中使用的自签名证书,因此浏览器会提示证书不可信,将此证书添加到exception中即可访问。在服务器发给客户机的证书报文段中,包含有服务器证书的公钥;客户机接收到该报文段后,按照协议规定,从报文段的对应位置中读取出服务器证书的公钥存入相关变量中。 与网站建立SSL安全连接时使用https协议,即采用https://ip:port/的方式来访问。浏览器与Web Server之间要经过一个握手的过程来完成身份鉴定与密钥交换,从而建立安全连接。具体过程如下: 1用户浏览器将其SSL版本号、加密设置参数、与session有关的数据以及其它一些必要信息发送到服务器。 服务器将其SSL版本号、加密设置参数、与session有关的数据以及其它一些必要信息发送给浏览器,同时发给浏览器的还有服务器的证书。如果配置服务器的SSL需要验证用户身份,还要发出请求要求浏览器提供用户证书。 2客户端检查服务器证书,如果检查失败,提示不能建立SSL连接。如果成功,那么继续。客户端浏览器为本次会话生成pre-master secret,并将其用服务器公钥加密后发送给服务器。如果服务器要求鉴别客户身份,客户端还要再对另外一些数据签名后并将其与客户端证书一起发送给服务器。 如果服务器要求鉴别客户身份,则检查签署客户证书的CA是否可信。如果不在信任列表中,结束本次会话。如果检查通过,服务器用自己的私钥解密收到的pre-master secret,并用它通过某些算法生成本次会话的master secret。 3客户端与服务器均使用此master secret生成本次会话的会话密钥(对称密钥)。在双方SSL握手结束后传递任何消息均使用此会话密钥。这样做的主要原因是对称加密比非对称加密的运算量低一个数量级以上,能够显著提高双方会话时的运算速度。 客户端通知服务器此后发送的消息都使用这个会话密钥进行加密。并通知服务器客户端已经完成本次SSL握手。 服务器通知客户端此后发送的消息都使用这个会话密钥进行加密。并通知客户端服务器已经完成本次SSL握手。 证书的初始化函数:void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ){ memset( crt, 0, sizeof(mbedtls_x509_crt) )} 证书的空间释放函数 void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) 证书结构: typedef struct mbedtls_x509_crt { mbedtls_x509_buf raw随机数据 mbedtls_x509_buf tbs签名 int version版本 mbedtls_x509_buf serial CA颁发的唯一序列号 mbedtls_x509_buf sig_oid签名算法,比如. sha1RSA * mbedtls_x509_time valid_from证书有效起始时间 mbedtls_x509_time valid_to证书失效时间 mbedtls_pk_context pk公钥容器 int ext_types /**<Bit string containing detected and parsed extensions */ int max_pathlen最大路径长度 mbedtls_x509_buf sig用私钥加密后的签名 mbedtls_md_type_t sig_md信息摘要生成算法名称. MBEDTLS_MD_SHA256mbedtls_pk_type_t sig_pk签名加密算法集的名称MBEDTLS_PK_RSA */ struct mbedtls_x509_crt *next指向下一个证书的指针 } Mbedtls中的握手: 客户端函数 int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) 输入参数为ssl_context为安全连接的配置参数,包含了握手状态、握手参数、会话数据、客户端ID以及相关回调入口等参数。 以下程序摘自ssl_tls.c文件,可以看出mbed根据宏定义分别实现了server端和client端 #if defined(MBEDTLS_SSL_CLI_C) if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) ret = mbedtls_ssl_handshake_client_step( ssl ) #endif #if defined(MBEDTLS_SSL_SRV_C) if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) ret = mbedtls_ssl_handshake_server_step( ssl ) #endif Client端的逻辑: Client发起clienthello请求后,server回serverhello包以及certificate(如果对客户端有认证需求则会跟随发送一个certificate request包来请求客户端的证书),之后client开始分析传来的server证书是否有效合法: 首先确认是否需要证书验证,通过判断ssl->transform_negotiate->ciphersuite_info字段 MBEDTLS_KEY_EXCHANGE_ECJPAKE, MBEDTLS_KEY_EXCHANGE_PSK, MBEDTLS_KEY_EXCHANGE_DHE_PSK, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK 以上四种psk加密套件不需要证书交互,需要证书的加密套件如下: MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 其次验证证书的有效性:mbedtls_x509_crt_verify_with_profile是x509_crt.c中的验证函数,其输入参数是会话的peer证书、证书链、可信ca列表、认证配置文件、以及认证参数等。 1、对比CN字段是否匹配,若不匹配返回CN_MISMATCH错误---x509_memcasecmp函数 2、根据配置文件检查密钥大小和类型是否正确,不正确返回BAD_KEY错误----x509_profile_check_key函数 3、判断CA的签发方以及父签发方(签发链)是否可信-----x509_crt_check_parent函数 验证完毕后,会判断证书使用的是否是EC密钥,如果是的话会使用函数mbedtls_ssl_check_curve来验证椭圆曲线是否正确。欢迎分享,转载请注明来源:夏雨云
评论列表(0条)