草庐IT

一文搞懂SSL/TLS

机器学习Zero 2024-05-30 原文

SSL/TLS

1. 概述

安全套接字层(SSL,Secure Sockets Layer)是基于公钥密码体制和X.509数字证书技术,为网络通信提供身份认证以及数据传输保密性、完整性的一种安全协议。

1994年,网景(Netscape)公司提出了SSL1.0,历经多次修改,1996年正式发布SSL3.0。1997年互联网工程任务组(IETF,Internet Engineering Task Force)发布基于SSL协议的互联网草案:传输层安全协议(TLS,Transport Layer Security)。1999年,IETF发布了正式的行业标准RFC2246 ,TLS/SSL直正成为通信安全标准。

SSL/TLS是位于传输层与应用层之间的加密协议(属于Socket层实现),对于应用层来说是透明的,应用层数据通过传递给SSL层进行加密,并增加SSL头,再传递给传输层。

SSL/TLS均可提供身份认证、机密性和完整性服务,虽然SSL系列的所有版本都已经弃用,TLS作为SSL的后续版本,大家依然习惯使用SSL的叫法。

2. 协议组成

SSL协议由三部分组成:

  • 握手协议:协商加密算法、MAC算法以及会话密钥
  • 记录协议:对交换的数据进行加密和签名
  • 警报协议:解决出现的问题

2.1 握手协议(Handshake protocol)

握手协议是客户端和服务端建立SSL连接首先执行的协议,在传输数据之前完成,服务器和客户端使用这个协议相互鉴别对方的身份、协商加密算法、MAC算法以及加密数据使用的会话密钥。

(1)建立安全能力

  • Client Hello:客户端第一次连接到服务端时,将Client Hello作为第一条信息发给服务端,包含了客户端支持的加密组件(cipher_suite):加密算法、压缩算法、摘要算法,以及本次连接客户端生成的随机数。若客户端期望恢复上一次的会话还需发送会话ID。

  • Server HelloServer Hello是服务端对客户端Client Hello的回复,包含了服务端从Client Hello中选择的本次会话使用的加密算法、压缩算法、摘要算法,服务端确定的会话ID(session ID)、服务端的随机数。

(2)服务端认证与密钥交换

客户端利用服务器响应消息完成服务器真是身份的认证。

  • (Server) Certificate:若要求验证服务端,则服务端在Server Hello信息后发送其证书(certificate),通常为X.509v3版的Certificate。

  • Server Key Exchange:该消息补充以前在Server Hello消息声明中的密码组,为客户端提供继续通信所需要的算法变量(依赖于所选定的算法)。

  • Certificate Request:若服务端需要鉴别客户端的身份,它将向客户端发送Certificate Request。该消息包含了服务端可鉴别的证书类型和可信任的CA证书序列。

  • Server Hello Done:该信息表明Server Hello结束,等待客户端响应。客户端收到该信息后检查服务端提供的Certificate 是否有效,以及服务端的Hello参数是否可接受。

(3)客户端认证与密钥交换

  • (Client) Certificate:当服务端请求Certificate时,客户端收到服务端的Server Hello Done后发送该信息。若客户端没有合适的Certificate,则发送”没有证书”的警告信息。

  • Client Key Exchange:该消息内容取决于密钥交换算法类型

    • 若选择RSA算法,则该消息包含经RSA公钥加密的预加密主密钥(pre-master secret),其中RSA公钥为服务器证书中的公钥或Server Key Exchange服务端临时生成的RSA公钥
    • 若选择DH算法,则该消息包含客户端使用服务端传来的DH算法参数生成的公共值,该公共值将被生成预加密主密钥。
  • Certificate Verify:该消息用于提供客户端Certificate验证,仅在具有签名能力的客户端传送 Certificate后传送。

(4)完成握手

客户端与服务器端分别利用pre_master_secret生成真正的主密钥master_secret,再利用主密钥生成会话密钥session_keys,然后相互发送Change Cipher Spec,并确认。

  • Change Cipher Spec:用于发方告知收方,发方已完成加密规范改变,准备使用协商的加密套件件(Cipher Suite)和会话密钥(Session Key)加密数据并传输了,体现在数据包中就是一个字节的数据。

  • Finished:发方使用协商好的加密套件(Cipher Suite)和会话密钥(Session Secret)加密一段Finish数据传送给收方,收方在收到Finishe信息后须检查其内容是否正确,以是否成功建立加解密通道。


客户端和服务端对Finished信息进行验证,确定加密通道已经建立成功,双方就可使用产生的会话密钥(Session keys)加密传输数据了。

警报协议(Alert Protocol)

当客户机和服务器发现错误时,会向对方发送一个警报消息。如果是致命错误,算法立即终止会话并关闭SSL连接,同时删除相关会话记录、秘密和密钥。

2.2 记录协议(Record Protocol)

客户端和服务端完成鉴别并确定安全信息交换使用的算法后,进入SSL记录协议,主要提供两个服务:

  • 数据保密性:使用握手协议定义的秘密密钥对传送的数据加密。
  • 消息完整性:使用握手协议定义的带有MAC的密钥计算消息认证码。

记录协议接收到应用程序传送的消息,将数据分片(切成容易管理的小区块),然后选择是否对这些区块作压缩,再加上此区块的消息认证码,将数据区块与MAC一起做加密处理,加上SSL记录头后通过TCP传送出去。接收数据方对数据进行解密、验证、解压缩、重组,将消息的内容还原,传送给上层应用程序。

  • (1)分段:每个上层应用数据被分成 2 14 2^{14} 214(16K)或更小的数据块。
  • (2)压缩:压缩是可选的,且是无损压缩。
  • (3)增加MAC:使用MD5、SHA等Hash函数产生消息摘要MAC,在压缩数据上增消息认证MAC,用于数据完整性检查。
  • (4)加密:对压缩数据及MAC进行加密,保证数据的机密性。
  • (5)附加SSL报头输出

3. 密码套件与密钥生成

(1)密码套件(cipher_suite)

密码套件是一组选定的加密基元和其他参数,包括密钥交换算法、身份验证算法、数据加密算法和散列算法。

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA156表示:

  • 密钥交换:ECDHE
  • 身份验证:RSA
  • 数据加密算法:AES_128_GCM
  • MAC:SHA156

(2)密钥生成

  • 预主密钥(PreMaster secret):PreMaster Secret由客户在Client Key Exchange环节使用RSA或Diffie-Hellman等加密算法生成,并使用服务端的公钥对其加密后传送给服务端,服务端使用私钥解密得到PreMaster secret。

  • 主密钥(Master secret):主密钥(Master secret)用来生成各类加密算法密钥,由服务端和客户端使用PreMaster secret、客户端在Hello阶段产生的随机数、服务端在Hello阶段产生的随机数按如下规则生成:

Master secret=
MD5(premaster secret + SHA('A'  + premaster secret + ClientHello.random + ServerHello.random))+
MD5(premaster secret + SHA('BB' + premaster secret + ClientHello.random + ServerHello.random))+
MD5(premaster secret + SHA('CCC'+ premaster secret + ClientHello.random + ServerHello.random))


主密钥首先通过一系列散列运算生成一个足够长度的密钥块(Key Block),该密钥块的长度大于或等于SSL所需要的各类加密密钥的长度。随后SSL将该密钥块中的数据切分成各个加密密钥,如果切分完Key block 还有剩余,则直接将剩余抛弃。

客户端发送数据时:

  • 首先对数据附加Client write MAC key
  • 然后对数据包使用Client write encryption key加密
  • 服务端收到密文后使用Client write encryption key解密
  • 服务端使用Client write MAC key对数据的完整性进行验证

服务端发送数据时:

  • 首先对数据附加Server write MAC key
  • 然后对数据包使用Server write encryption key加密
  • 客户端收到密文后使用Server write encryption key解密
  • 客户端使用Server write MAC key对数据的完整性进行验证

4. SSL协议应用模式

(1)匿名SSL连接

这种模式是SSL安全连接的最基本模式,易于使用,常用的浏览器都支持这种方式,很合单向的安全数据传输应用。典型的应用是当用户进行网站注册时,为防止私信息(如信用卡号、口令、电话等)泄露,就采用匿名 SSL连接该网站。

该模式下客户端没有数字证书,用户以匿名方式访问服务器服务器具有数字证书,实现服务器的认证,以使用户能确认是自己要访问的站点。首次SSL连接时客户端需要下载服务器证书,然后随机地生成密钥,再用这个密钥进行SSL握协议,一个会话完成后,这个密钥就丢弃

(2)对等安全服务

这种模式通信双方都可以发起和接收 SSL 连接请求,既做服务器又做客户端,双方具有数字证书,实现服务器和客户端的双向认证,通信双方可以是应用程序或安全协议代务器(安全协议代理服务器相当于一个加密/解密网关,把内部部网络的访问转换为SSL数据包,接收时把 SSL数据包解密。)。

有关一文搞懂SSL/TLS的更多相关文章

  1. Ruby SSL 错误 - sslv3 警报意外消息 - 2

    我正在尝试在ruby​​脚本中连接到服务器https://www.xpiron.com/schedule。但是,当我尝试连接时:require'open-uri'doc=open('https://www.xpiron.com/schedule')我收到以下错误消息:OpenSSL::SSL::SSLError:SSL_connectreturned=1errno=0state=SSLv2/v3readserverhelloA:sslv3alertunexpectedmessagefrom/usr/local/lib/ruby/1.9.1/net/http.rb:678:in`conn

  2. ruby - 如何在非 SSL 或 http 网站上使用 Stripe? - 2

    我正在使用Rails3.2.6和Stipe进行支付。是否有可能在不购买ssl证书的情况下进行付款。我可以使用Stripe页面作为我的支付页面吗? 最佳答案 您可以使用stripe.js在技术上跳过SSL但我强烈建议您设置SSL。它所做的是将信用卡信息直接传递给stripe,然后stripe会给你一个token,用于实际进行收费。这样做意味着信用卡信息永远不会接触您的服务器,您不必担心PCI合规性。但是,您仍应设置SSL以防止中间人攻击。您可以在https://stripe.com/docs/tutorials/forms找到有关如何

  3. ruby - HTTP POST 上的 SSL 错误(未知协议(protocol)) - 2

    尝试通过SSL连接到ImgurAPI时出现错误。这是代码和错误:API_URI=URI.parse('https://api.imgur.com')API_PUBLIC_KEY='Client-ID--'ENDPOINTS={:image=>'/3/image',:gallery=>'/3/gallery'}#Public:Uploadanimage##args-Theimagepathfortheimagetoupload#defupload(image_path)http=Net::HTTP.new(API_URI.host)http.use_ssl=truehttp.verify

  4. ruby - ssl`sysread_nonblock' : end of file reached (EOFError) - 2

    我编写了一个使用ruby​​线程的代码。require'rubygems'require'net/http'require'uri'defget_response()uri=URI.parse('https://..........')http=Net::HTTP.new(uri.host,uri.port)http.use_ssl=true----------endt1=[]15.timesdo|i|t1[i]=Thread.new{hit_mdm(i)sleep(rand(0)/10.0)}endt1.each{|t|t.join}代码工作正常,但是当程序执行到最后时它会抛出以下错

  5. ruby - 使用 Ruby/Puma 的本地 SSL - 2

    我正在运行本地puma服务器,但无法在SSL下加载资源。我有一个本地签名的证书。我正在尝试使用以下配置运行服务器:puma-b'ssl://127.0.0.1:9292?key=/path/to/certs/localhost.unecrypted.key&cert=/path/to/certs/localhost.crt'现在,当我访问https://localhost:9292或https://127.0.0.1:9292时,浏览器只是旋转并且没有来自服务器的响应。不返回任何资源。它两次向我显示HTML标题标签,但几乎总是什么也得不到。有什么想法吗?其他想法?确实需要在本地运行此应

  6. ruby-on-rails - ruby open ssl api for encrypted key (without nodes option) - 2

    在安装了openssllib的linux机器上,当您执行带有“-nodes”选项的“opensslpkcs12”时,您将获得带有未加密私钥的输出,但如果您跳过–nodes选项,则输出将具有加密的私钥。e.g.opensslpkcs12-intest.pfx-outtest.pem你应该看到像下面这样加密的私钥-----BEGINENCRYPTEDPRIVATEKEY-----MIIFDjBABgkqhkiGG7s=-----ENDENCRYPTEDPRIVATEKEY-----如何使用ruby​​的开放ssl库实现上述目标?这就是我用ruby​​生成私钥的方式:@private_key

  7. ruby - 如何获得带有 SSL 客户端证书的 HTTPS 请求以与 Ruby EventMachine 一起使用? - 2

    我正在尝试使用RubyEventMachine访问使用SSL证书身份验证的HTTPSWeb服务,但我没有让它工作。我编写了以下简单代码块来对其进行端到端测试:require'rubygems'require'em-http'EventMachine.rundourl='https://foobar.com/'ssl_opts={:private_key_file=>'/tmp/private.key',:cert_chain_file=>'/tmp/ca.pem',:verify_peer=>false}http=EventMachine::HttpRequest.new(url).g

  8. ruby-on-rails - 萨翁 SSL 问题 - 2

    我正在努力让Savongem连接到我们的一台服务器。我不断收到一条错误消息,指出我无法通过ssl。我已经阅读了许多教程和修复程序,但似乎都没有用。感谢任何帮助-如果我能度过它,这将成为我的星期一:-)。错误:D,[2011-06-20T09:43:02.002993#10328]DEBUG--:RetrievingWSDLfrom:http://path_to_wsdl:4443/sm/services/mailing/2009/03/02?wsdlD,[2011-06-20T09:43:02.129057#10328]DEBUG--:HTTPIexecutesHTTPGETusing

  9. ruby - 如何在 Ruby 中创建双向 SSL 套接字 - 2

    我正在构建一个连接到服务器并等待数据的客户端Ruby库,但也允许用户通过调用方法发送数据。我使用的机制是有一个初始化套接字对的类,如下所示:definitialize@pipe_r,@pipe_w=Socket.pair(:UNIX,:STREAM,0)end我允许开发人员调用以将数据发送到服务器的方法如下所示:defsend(data)@pipe_w.write(data)@pipe_w.flushend然后我在一个单独的线程中有一个循环,我从连接到服务器的socket和@pipe_r中选择:defsocket_loopThread.newdosocket=TCPSocket.new

  10. 更新证书后,Ruby Net::HTTP 响应 OpenSSL::SSL::SSLError "certificate verify failed" - 2

    我们最近更新了我们网站的SSL证书,在MacOSElCapitan10.11.3上出现以下情况:require'net/http'Net::HTTP.getURI('https://www.google.com')#=>"..."#ThesitewhosecertificategotrenewedNet::HTTP.getURI('https://www.example.com')#=>OpenSSL::SSL::SSLError:SSL_connectreturned=1errno=0state=error:certificateverifyfailed我在Google和StackO

随机推荐