Owen的酒楼

--酒楼上渡过的人生--
生命太短,人生太长,但愿别喝醉了。

导航

SSL协议的分析及实现 ZT

Posted on 2008-01-25 11:57  Hicome  阅读(1518)  评论(1编辑  收藏  举报
SSL协议的分析及实现
来源:中国IT实验室整理 时间:2007-4-18 作者:佚名

1.引言   
   
    SSL是一种在客户端和服务器端之间建立安全通道的协议。SSL一经提出,就在Internet上得到广泛的应用。SSL最常用来保护Web的安全。为了保护存有敏感信息Web的服务器的安全,消除用户在Internet上数据传输的安全顾虑。

    OpenSSL是一个支持SSL认证的服务器.它是一个源码开放的自由软件,支持多种操作系统。OpenSSL软件的目的是实现一个完整的、健壮的、商业级的开放源码工具,通过强大的加密算法来实现建立在传输层之上的安全性。OpenSSL包含一套SSL协议的完整接口,应用程序应用它们可以很方便的建立起安全套接层,进而能够通过网络进行安全的数据传输。

2.SSL协议概述
    SSL 是Secure socket Layer英文缩写,它的中文意思是安全套接层协议,指使用公钥和私钥技术组合的安全网络通讯协议。SSL协议是网景公司(Netscape)推出的基于 WEB应用的安全协议,SSL协议指定了一种在应用程序协议(如Http、Telenet、NMTP和FTP等)和TCP/IP协议之间提供数据安全性分层的机制,它为TCP/IP连接提供数据加密、服务器认证、消息完整性以及可选的客户机认证,主要用于提高应用程序之间数据的安全性,对传送的数据进行加密和隐藏,确保数据在传送中不被改变,即确保数据的完整性。

    SSL 以对称密码技术和公开密码技术相结合,可以实现如下三个通信目标:

    (1)秘密性: SSL客户机和服务器之间传送的数据都经过了加密处理,网络中的非法窃听者所获取的信息都将是无意义的密文信息。

    (2)完整性: SSL利用密码算法和散列(HASH)函数,通过对传输信息特征值的提取来保证信息的完整性,确保要传输的信息全部到达目的地,可以避免服务器和客户机之间的信息受到破坏。

    (3)认证性:利用证书技术和可信的第三方认证,可以让客户机和服务器相互识别对方的身份。为了验证证书持有者是其合法用户(而不是冒名用户), SSL要求证书持有者在握手时相互交换数字证书,通过验证来保证对方身份的合法性。

3.SSL协议的体系结构

    SSL协议位于TCP/IP协议模型的网络层和应用层之间,使用TCP来提供一种可靠的端到端的安全服务,它是客户/服务器应用之间的通信不被攻击窃听,并且始终对服务器进行认证,还可以选择对客户进行认证。SSL协议在应用层通信之前就已经完成加密算法、通信密钥的协商以及服务器认证工作,在此之后,应用层协议所传送的数据都被加密。SSL实际上是共同工作的两层协议组成,如图1所示。从体系结构图可以看出SSL安全协议实际是SSL握手协议、SSL修改密文协议、SSL警告协议和SSL记录协议组成的一个协议族。

握手
协议
修改密  
文协议
报警
协议
        SSL记录协议
           TCP
           IP


          
         图1  SSL体系结构

    SSL记录协议为SSL连接提供了两种服务:一是机密性,二是消息完整性。为了实现这两种服务, SSL记录协议对接收的数据和被接收的数据工作过程是如何实现的呢? SSL记录协议接收传输的应用报文,将数据分片成可管理的块,进行数据压缩(可选),应用MAC,接着利用IDEA、DES、3DES或其他加密算法进行数据加密,最后增加由内容类型、主要版本、次要版本和压缩长度组成的首部。被接收的数据刚好与接收数据工作过程相反,依次被解密、验证、解压缩和重新装配,然后交给更高级用户。

    SSL修改密文协议是使用SSL记录协议服务的SSL高层协议的3个特定协议之一,也是其中最简单的一个。协议由单个消息组成,该消息只包含一个值为1的单个字节。该消息的唯一作用就是使未决状态拷贝为当前状态,更新用于当前连接的密码组。为了保障SSL传输过程的安全性,双方应该每隔一段时间改变加密规范。

    SSL告警协议是用来为对等实体传递SSL的相关警告。如果在通信过程中某一方发现任何异常,就需要给对方发送一条警示消息通告。警示消息有两种:一种是 Fatal错误,如传递数据过程中,发现错误的MAC,双方就需要立即中断会话,同时消除自己缓冲区相应的会话记录;第二种是Warning消息,这种情况,通信双方通常都只是记录日志,而对通信过程不造成任何影响。SSL握手协议可以使得服务器和客户能够相互鉴别对方,协商具体的加密算法和MAC算法以及保密密钥,用来保护在SSL记录中发送的数据。

    SSL握手协议允许通信实体在交换应用数据之前协商密钥的算法、加密密钥和对客户端进行认证(可选)的协议,为下一步记录协议要使用的密钥信息进行协商,使客户端和服务器建立并保持安全通信的状态信息。SSL握手协议是在任何应用程序数据传输之前使用的。SSL握手协议包含四个阶段:第一个阶段建立安全能力;第二个阶段服务器鉴别和密钥交换;第三个阶段客户鉴别和密钥交换;第四个阶段完成握手协议。

4.SSL协议的实现

    基于OpenSSL的程序可以被分为两个部分:客户机和服务器,使用SSL协议使通信双方可以相互验证对方身份的真实性,并且能够保证数据的完整性和机密性。建立SSL通信的过程如图2所示。


 图2  SSL通信过程
 
    SSL通信模型采用标准的C/S结构,除了在TCP层上进行传输之外,与普通的网络通信协议没有太大的区别,基于OpenSSL的程序都要遵循以下几个步骤:

(1) OpenSSL初始化

    在使用OpenSSL之前,必须进行相应的协议初始化工作,这可以通过下面的函数实现:

    int SSL_library_int(void);

(2) 选择会话协议

    在利用OpenSSL开始SSL会话之前,需要为客户端和服务器制定本次会话采用的协议,目前能够使用的协议包括TLSv1.0、SSLv2、SSLv3、SSLv2/v3。

    需要注意的是,客户端和服务器必须使用相互兼容的协议,否则SSL会话将无法正常进行。

(3) 创建会话环境

    在OpenSSL中创建的SSL会话环境称为CTX,使用不同的协议会话,其环境也不一样的。申请SSL会话环境的OpenSSL函数是:

    SSL_CTX *SSL_CTX_new(SSL_METHOD * method);

    当SSL会话环境申请成功后,还要根据实际的需要设置CTX的属性,通常的设置是指定SSL握手阶段证书的验证方式和加载自己的证书。制定证书验证方式的函数是:

    int SSL_CTX_set_verify(SSL_CTX *ctx,int mode,int(*verify_callback),int(X509_STORE_CTX *));

    为SSL会话环境加载CA证书的函数是:

    SSL_CTX_load_verify_location(SSL_CTX *ctx,const char *Cafile,const char *Capath);

    为SSL会话加载用户证书的函数是:

    SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file,int type);

    为SSL会话加载用户私钥的函数是:

    SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx,const char* file,int type);

    在将证书和私钥加载到SSL会话环境之后,就可以调用下面的函数来验证私钥和证书是否相符:

    int SSL_CTX_check_private_key(SSL_CTX *ctx);

(4) 建立SSL套接字

    SSL套接字是建立在普通的TCP套接字基础之上,在建立SSL套接字时可以使用下面的一些函数:

    SSL *SSl_new(SSL_CTX *ctx); 

    //申请一个SSL套接字

    int SSL_set_fd(SSL *ssl,int fd);) 

    //绑定读写套接字

    int SSL_set_rfd(SSL *ssl,int fd); 

    //绑定只读套接字

    int SSL_set_wfd(SSL *ssl,int fd);

    //绑定只写套接字

(5) 完成SSL握手

    在成功创建SSL套接字后,客户端应使用函数SSL_connect( )替代传统的函数connect( )来完成握手过程:

    int SSL_connect(SSL *ssl);

    而对服务器来讲,则应使用函数SSL_ accept ( )替代传统的函数accept ( )来完成握手过程:

    int SSL_accept(SSL *ssl);

    握手过程完成之后,通常需要询问通信双方的证书信息,以便进行相应的验证,这可以借助于  下面的函数来实现:

    X509 *SSL_get_peer_certificate(SSL *ssl);

    该函数可以从SSL套接字中提取对方的证书信息,这些信息已经被SSL验证过了。

    X509_NAME *X509_get_subject_name(X509 *a);

    该函数得到证书所用者的名字。

(6) 进行数据传输

    当SSL握手完成之后,就可以进行安全的数据传输了,在数据传输阶段,需要使用SSL_read( )    和SSL_write( )来替代传统的read( )和write( )函数,来完成对套接字的读写操作:

    int SSL_read(SSL *ssl,void *buf,int num);

    int SSL_write(SSL *ssl,const void *buf,int num);

(7) 结束SSL通信

    当客户端和服务器之间的数据通信完成之后,调用下面的函数来释放已经申请的SSL资源:

    int SSL_shutdown(SSL *ssl); 

    //关闭SSL套接字

    void SSl_free(SSL *ssl);

    //释放SSL套接字

    void SSL_CTX_free(SSL_CTX *ctx); 

    //释放SSL会话环境

5.结束语

    SSL协议采用数字证书进行双端实体认证,用非对称加密算法进行密钥协商,用对称加密算法将数据加密后进行传输以保证数据的保密性,并且通过计算数字摘要来验证数据在传输过程中是否被篡改和伪造,从而为敏感数据在Internet上的传输提供了一种安全保障手段。

    OpenSSL是一个开放源代码的SSL协议的产品实现,它采用C语言作为开发语言,具备了跨系统的性能。调用OpenSSL  的函数就可以实现一个SSL加密的安全数据传输通道,从而保护客户端和服务器之间数据的安全。





-------------------------================-----------------------------


RSA公钥加密在计算机产业中被广泛使用在认证和加密。可以从RSA Data Security Inc.获得的RSA公钥加密许可证。公钥加密是使用一对非对称的密码加密或解密的方法。每一对密码由公钥和私钥组成。公钥被广泛发布。私钥是隐密的,不公开。用公钥加密的数据只能够被私钥解密。反过来,使用私钥加密的数据只能用公钥解密。这个非对称的特性使得公钥加密很有用。
  
  使用公钥加密法认证
  
  认证是一个身份认证的过程。在下列例子中包括甲和乙,公钥加密会非常轻松地校验身份。符号{数据} key意味着"数据"已经使用密码加密或解密。假如甲想校验乙的身份。乙有一对密码,一个是公开的,另一个是私有的。乙透露给甲他的公钥。甲产生一个随机信息发送给乙。 甲——〉乙:random-message
  
  乙使用他的私钥加密消息,返回甲加密后的消息。 乙——〉甲:{random-message}乙的私钥
  
  甲收到这个消息然后使用乙的以前公开过的公钥解密。他比较解密后的消息与他原先发给乙的消息。如果它们完全一致,就会知道在与乙说话。任意一个中间人不会知道乙的私钥,也不能正确加密甲检查的随机消息。
  
  除非你清楚知道你加密的消息。用私钥加密消息,然后发送给其他人不是一个好主意。因为加密值可能被用来对付你,需要注意的是:因为只有你才有私钥,所以只有你才能加密消息。所以,代替加密甲发来的原始消息,乙创建了一个信息段并且加密。信息段取自随机消息(random-message)并具有以下有用的特性:
  
  1. 这个信息段难以还原。任何人即使伪装成乙,也不能从信息段中得到原始消息;
  
  2. 假冒者将发现不同的消息计算出相同的信息段值;
  
  3. 使用信息段,乙能够保护自己。他计算甲发出的随机信息段,并且加密结果,并发送加密信息段返回甲。甲能够计算出相同的信息段并且解密乙的消息认证乙。
  
  这个技术仅仅描绘了数字签名。通过加密甲产生的随机消息,乙已经在甲产生的消息签名。因此我们的认证协议还需要一次加密。一些消息由乙产生:
  
  甲——〉乙:你好,你是乙么?
  
  乙——〉甲:甲,我是乙
  
  {信息段[甲,我是乙] } 乙的私钥
  
  当你使用这个协议,乙知道他发送给乙的消息,他不介意在上面签名。他先发送不加密的信息,"甲,我是乙。",然后发送信息段加密的消息版本。甲可以非常方便地校验乙就是乙,同时,乙还没有在他不想要的信息上签名。
  
  提交公钥
  
  那么,乙怎样以可信的方式提交他的公钥呢?看看认证协议如下所示:
  
  甲——〉乙:你好
  
  乙——〉甲:嗨,我是乙,乙的公钥
  
  甲——〉乙:prove it
  
  乙——〉甲:甲,我是乙 {信息段[甲,我是乙] } 乙的私钥
  
  在这个协议下,任何人都能够成为"乙"。所有你所要的只是公钥和私钥。你发送给甲说你就是乙,这样你的公钥就代替了乙的密码。然后,你发送用你的私钥加密的消息,证明你的身份。甲却不能发觉你并不是乙。 为了解决这个问题,标准组织已经发明了证书。一个证书有以下的内容:
  
  * 证书的发行者姓名
  
  * 发行证书的组织
  
  * 标题的公钥
  
  * 邮戳
  
  证书使用发行者的私钥加密。每一个人都知道证书发行者的公钥(这样,每个证书的发行者拥有一个证书)。证书是一个把公钥与姓名绑定的协议。通过使用证书技术,每一个人都可以检查乙的证书,判断是否被假冒。假设乙控制好他的私钥,并且他确实是得到证书的乙,就万事大吉了。
  
  这些是修订后的协议:
  
  甲——〉乙:你好
  
  乙——〉甲:嗨,我是乙,乙的校验
  
  甲——〉乙:prove it
  
  乙——〉甲:甲,我是乙 {信息段[甲, 我是乙] } 乙的私钥
  
  现在当甲收到乙的第一个消息,他能检查证书,签名(如上所述,使用信息段和公钥解密),然后检查标题(乙的姓名),确定是乙。他就能相信公钥就是乙的公钥和要求乙证明自己的身份。乙通过上面的过程,制作一个信息段,用一个签名版本答复甲。甲可以校验乙的信息段通过使用从证书上得到的公钥并检查结果。
  
  如果一个黑客,叫H
  
  甲——〉H:你好
  
  H——〉不能建立一个令甲相信的从乙的消息。
  
  交换密码(secret)
  
  一旦甲已经验证乙后,他可以发送给乙一个只有乙可以解密、阅读的消息:
  
  甲——〉乙:{secret}乙的公钥
  
  唯一找到密码的方法只有使用乙的私钥解码上述的信息。交换密码是另一个有效使用密码加密的方法。即使在甲和乙之间的通讯被侦听,只有乙才能得到密码。
  
  使用密码作为另一个secret-key增强了网络的安全性,但是这次这是一个对称的加密算法(例如DES、RC4、IDE甲)。因为甲在发送给乙之前产生了密码,所以甲知道密码。乙知道密码因为乙有私钥,能够解密甲的信息。但他们都知道密码,他们都能够初始化一个对称密码算法,而且开始发送加密后的信息。这儿是修定后的协议:
  
  甲——〉乙:你好
  
  乙——〉甲:嗨,我是乙,乙的校验
  
  甲——〉乙:prove it
  
  乙——〉甲:甲,我是乙 {信息段[甲,我是乙] }乙的私钥
  
  甲——〉乙:ok 乙,here is a secret {secret}乙的公钥
  
  乙——〉甲:{some message}secret-key
  
  黑客窃听
  
  那么如果有一个恶意的黑客H在甲和乙中间,虽然不能发现甲和乙已经交换的密码,但能干扰他们的交谈。他可以放过大部分信息,选择破坏一定的信息(这是非常简单的,因为他知道甲和乙通话采用的协议)。
  
  甲——〉H:你好
  
  H——〉乙:你好
  
  乙——〉H:嗨,我是乙,乙的校验
  
  H——〉甲:嗨,我是乙,乙的校验
  
  甲——〉H:prove it
  
  H——〉乙:prove it
  
  乙——〉H:甲,我是乙 {信息段[甲,我是乙] }乙的私钥
  
  H——〉甲:甲,我是乙 {信息段[甲,我是乙] }乙的私钥
  
  甲——〉H:ok 乙,here is a secret {secret} 乙的公钥
  
  H——〉乙:ok 乙,here is a secret {secret} 乙的公钥
  
  乙——〉H:{some message}secret-key
  
  H——〉甲:Garble[{some message}secret-key ]
  
  H忽略一些数据不修改,直到甲和乙交换密码。然后H干扰乙给甲的信息。在这一点上,甲相信乙,所以他可能相信已经被干扰的消息并且尽力解密。
  
  需要注意的是,H不知道密码,他所能做的就是毁坏使用秘钥加密后的数据。基于协议,H可能不能产生一个有效的消息。但下一次呢?
  
  为了阻止这种破坏,甲和乙在他们的协议中产生一个校验码消息(message authentication code)。一个校验码消息(MAC)是一部分由密码和一些传输消息产生的数据。信息段算法描述的上述特性正是它们抵御H的功能:
  
  MAC= Digest[some message,secret ]
  
  因为H不知道密码,他不能得出正确的值。即使H随机干扰消息,只要数据量大,他成功的机会微乎其微。例如,使用HD5(一个RSA发明的好的加密算法),甲和乙能够发送128位MAC值和他们的消息。H猜测正确的MAC的几率将近1/18,446,744,073,709,551,616约等于零。
  
  这是又一次修改后的协议:
  
  甲——〉乙:你好
  
  乙——〉甲:嗨,我是乙,乙的校验
  
  甲——〉乙:prove it
  
  乙——〉甲:嗨,我是乙,乙的校验
  
  甲,我是乙
  
  {信息段[甲,我是乙] } 乙的私钥
  
  ok 乙,here is a secret {secret} 乙的公钥
  
  {some message,MAC}secret-key
  
  现在H已经无技可施了。他干扰了得到的所有消息,但MAC计算机能够发现他。甲和乙能够发现伪造的MAC值并且停止交谈。H不再能与乙通讯。