实验环境:RHEL5.8 32Bit

SSL协议、OpenSSL以及创建私有CA详解

·如果通信双方其中某一方的私钥丢失了该怎么办?

    在通信的过程中,收发双反任何一方的私钥丢失,都会导致它们的数字证书失效,所以任何基于此证书建立的通信都应该宣布失效,那么我们应该如何在互联网上实现这种失效的功能呢?这种功能其实还是得依靠CA来实现,事实上一个完整的CA,还应该维护一个列表,叫做CRL(证书吊销列表)。

·CRL

    CRL中保存的是此前CA所发出的所有证书,这些证书还没有过期,只不过由于各种原因证书已经被吊销了,证书也是有有效期的,所以说有了CRL之后,收发双方进行通信的机制是这样的:

    首先,接收方为了能够和发送方进行通信,会去申请获得发送方的证书,接着发送方就会将自己的证书发送给接收方,接收方在得到证书之后,先去验证该证书的有效性,即该证书上的数字签名是不是自己所信任的证书颁发机构所颁发的,也就是验证是否能够使用发证机构的公钥对该证书的数字签名进行解密,如果可以解密并且解密完成之后,接着就会去验证该证书信息的数据的完整性,通过数据的特征码来验证,验证完了数字证书数据信息的数据完整性之后,如果完整的话就可以获得发送方的公钥信息了,事实上真正可靠的做法是,接收方在获得发送方的数字证书之后,先去验证该证书是否是自己所信任的证书颁发机构所颁发的,接着再去查看该证书是否在CRL这个列表里面,如果该证书在CRL里面,那么也应该拒绝使用该证书,但是在互联网的通信中,大部分用户都会忽略这一点,所以有证书的通信也不一定是安全的,故CRL是保证证书安全性的一个非常重要的措施,并且我们在每一次使用证书之前都应该去验证它的有效性,数字证书的验证流程:

wKiom1hwo_nxgsXWAABDLyFTvEI413.png    

    因此一个证书颁发机构,包括其CRL,以及CA间的信任关系的组合构成了整个PKI系统的核心。

·CA(Certificate Authority)

    证书颁发机构,PKI的核心就是CA。

·一个数字证书当中都应该包含什么样的信息呢?

    不同标准下的数字证书的格式是不同的,目前比较流行的证书的格式是x509格式,这种格式是标准格式最通行的格式,x509格式的证书中主要包含了以下几个方面的信息:

    1,公钥及其使用期限

    2,证书的合法拥有者

    3,证书该如何被使用

    证书的用途是有限定的,不能随便的去使用。

    4,CA的信息

    5,CA签名的校验码(CA的公钥,CA颁发的数字证书的签名是被CA的私钥所加密的)

·TLS/SSL

    这是互联网上著名的安全机制,它们使用的证书的格式正是x509的格式,TLS/SSL就是一种PKI的实现,还有一种PKI的实现叫做OpenGPG,这两种PKI实现的证书管理机制是不同的或者这两种PKI实现的CA间信任关系的传递机制略有不同,而在我们的Linux操作系统上,OpenGPG也是一种PKI的实现架构,意思就是如果我们想要在互联网的通信过程当中实现数据的加密,数字证书的签名、身份的验证等各种功能得依赖于PKI,而PKI的实现却有两种形式,一种是基于TLS/SSL的PKI实现,另一种是基于OpenGPG的PKI的实现,OpenGPG的证书格式和x509的证书格式是差不多的,那么TLS/SSL到底是什么?它是如何实现握手认证(Handshake)以及密钥交换等各种功能的:

    TCP/IP四层模型中的应用层是否能够加密传输数据依赖的是具体的传输协议,http、smtp以及ftp协议在进行数据传输的时候都是明文传输的,但是https协议使得我们在访问互联网web服务器的时候数据可以进行加密传输,https使用的443端口,而http使用的是80端口,二者是完全不同的两个协议。

·https

    https协议是由美国网景(Netscape)公司所开发的,网景公司是全球第一款最流行的浏览器生产商,就是我们所熟知的Navigator浏览器,网景公司同时也提供了互联网上第一款web服务器软件,但是后来网景公司被Sun公司收购了,因为当时网景公司已经被微软公司彻底打败了,http协议在传输数据的过程中是明文传输的,但是为了实现基于http的加密传输数据的协议,网景公司在应用层和TCP层之间又加入了半个层,这半个层就叫做SSL层:

    wKiom1haQnnTcswiAAAcaVlsBVw762.png              wKiom1haREvBkt9gAAAZ3_ZXy60802.png

·SSL(Secure Socket Layer)

    安全的套接字层,SSL发展到今天已经有很多的版本了,比如SSLv1、SSLv2以及SSLv3,目前比较流行的版本是v2和v3版,v1版已经不再使用了,SSL只是一个库,因此如果我们想要实现SSL的功能,只需要在我们的系统上提供SSL相关的库文件即可,就能够将http封装成为https,那就意味着我们能够支持https协议了,但是http协议本身是不会经由SSL层封装的,因此http和https是两个完全不同的协议,但是二者在应用层所实现的功能是一样的,只不过底层的协议栈是不同的,因为https协议的封装层次多了一个SSL层的封装,由此导致二者底层的所有封装都会趋于不同,SSL不是一个软件,它只是一个库,在应用层封装好的传输协议,如果在传输数据到传输层之前调用了SSL层的功能的话,那么这个协议在传输数据的过程中就能够实现加密传输的功能了,例如http协议原本在传输数据的过程中是无法实现加密传输的,它在应用层封装完毕之后就会将数据交给传输层,但是由于Netscape在传输层之前又新增了一个SSL层,因此http数据包在传输给传输层之前会在SSL层再做一次封装,而SSL层本身就是实现数据安全通信的,因此http摇身一变就变成了https协议,同理smtp协议就变成了smtps协议,ftp协议就变成了ftps协议,众多应用层的明文协议都可以通过调用SSL层的功能实现数据的安全传输,SSL是由网景公司研发的协议,之后国际标准化组织决定研发一个在全球范围内更加流行且更为开放的另一个层次上的通用性协议,就是TLS协议。

·TLS(Transport Layer Security)

    传输层安全,TLS目前的版本就是它的第一版,叫做TLSv1,事实上TLSv1就相当于是SSLv3,二者所实现的功能的原理和机制是差不多的,以后我们可以不加区别的来说TLS和SSL,因为在有些系统中二者的实现机制是一样的,虽然协议有可能不同。

·在两台主机之间的SSL会话是如何实现的?

    以http协议为例,http协议是基于TCP协议的,因此收发双方在进行http会话之前首先会进行三次握手,但是如果是https协议的话,也会先进行三次握手来保证通信连接的建立,接下来:

    第一步,客户端会向服务端发起会话请求,此时,服务端不会直接向客户端传递http协议包,而是先去和客户端协商建立SSL会话,这个协商的过程不仅要协商使用SSL协议还是TLS协议,还得要协商使用何种对称加密算法,应该选择一个双方共同支持的,而且比较理想的对称加密算法。

    第二步,服务端会将自己的证书发送给客户端,一般而言客户端都没有证书,客户端在收到证书之后,首先会去验证证书是否为自己所信任的CA所颁发的,之后会去验证证书的完整性,如果证书验证通过,客户端就会通过证书得到服务端的公钥。

    第三步,客户端会去建立一个会话密钥,https协议的主要作用在于使得web服务器的数据交换是通过加密的方式进行的,加密使用对称加密的算法,因为非对称加密算法的加密速度太慢,这个对称密码是客户端通过自己主机内部的随机数选择生成的一个随机密钥,并将这个随机密钥通过服务端的公钥加密并且发送给服务端。

    第四步,客户端将加密的密钥发送给服务端,接下来服务端使用该随机密钥加密数据,并将加密后的数据发送给客户端。

wKioL1hwqimjq4WoAABbkXz2d-Y640.png

    以上就是SSL会话建立的全过程。

    SSL会话建立过程中的对称密钥是由客户端自己选择生成的,而不是基于Deffie-Hellman算法实现的,我们通过之前的学习知道公钥加密算法可以实现身份验证和数据的机密性两种功能,但是这里我们发现,公钥加密算法还可以实现密钥交换的功能。

·常见加密算法的总结

    一,对称加密算法

    对称加密算法的特性是加密和解密使用同一个密钥,常见的对称加密算法主要有以下几种:

      1,DES(Data Encryption Standard)数据加密标准

      这是一个比较早的而且比较成熟的加密算法,是由美国国家安全局在征集加密算法的时候,由IBM公司所提供的一种加密算法,叫做数据加密标准,那时的计算机的运行速度非常的慢,DES使用的密钥长度为56位,到2000年左右,人们已经可以轻而易举的使用当时性能较强的计算机去破解DES加密算法,至此DES加密算法已经很少使用了,因为它不安全,后来人们发明了另外一种加密算法,这个算法的机制是将数据使用DES算法加密3次,即3重DES,叫做3DES。

      2,3DES

      目前使用比较多的对称加密算法,叫做TripleDES。

      3,AES(Advanced Encryption Standard)高级加密标准

      是由美国国家安全局征集的更高级别的对称加密算法,叫做高级加密标准,AES使用128位的密钥长度,安全性比较高,但是AES算法有几个变种,AES192、AES256以及AES512后面的数字表示使用的密钥长度,越长安全性越高,但是密钥越长加密的速度就会越慢,所以合适的加密算法才是最好的。

      4,Blowfish

      这是一种常见的对称加密算法。

      我们数据本身其实都是一个一个的二进制位,但是我们在给数据加密的时候不是一个位一个位加密的,这是不可能的,一般在给数据加密之前,我们会将整个数据分成大小相同的数据块进行加密。

    二,单向加密算法

        1,MD4

        2,MD5

        使用128位的定长输出。

        3,SHA1

        使用160位的定长输出,SHA1还有几种变种,SHA192、SHA256以及SHA384后面的数字不是密钥长度,而是输出长度。

        4,CRC-32

        叫做循环冗余校验码,不是一种加密算法,而是一种校验码的计算机制,使用非常广泛,但是不提供任何安全性,一般的单向加密算法决不允许输入不一样而输出却一样的情况发生,但是CRC-32算法却有可能出现这种情况,因为CRC-32不是为了加密,而是为了提供校验功能。

    三,非对称加密算法

        也叫做公钥加密算法,实现的功能主要有两个:加密和签名,此种算法的密钥是成对出现的,密钥的长度也是可以变化的,但是同理密钥长度越长,加密速度越慢,而且公钥加密主要实现的功能有三个,身份验证(私钥加密)、数据加密(公钥加密)以及密钥交换(公钥加密),公钥加密算法中比较著名的算法有两种:

        1,RSA

         RSA既是一种算法,又是一个公司的名称,而且也是三位创始人的名称,RSA既能实现加密又可以实现签名。

        2,DSA

          DSA只能实现签名,属于美国国家安全局,是公开使用的。

        还有一种商业算法叫做ElGamal。

    众所周知,加密和解密都得通过算法来实现,那因此我们就需要一种工具,能够在我们的主机上给我们提供这种算法的实现,就是具体的能够完成这种算法的一个程序,我们称之为具体的实现,而在Linux上,不同的加密算法,或者不同的加密机制所能够提供的工具是不同的,能够实现加密算法的工具主要有两种:

    1,OpenSSL

    2,gpg

·OpenSSL

    OpenSSL是SSL的开源实现,功能非常强大,几乎实现了目前市面上所有的主流加密算法,而且工作性能也非常的好,作者是两个年轻人,OpenSSL是一个软件,它是由三部分组成的:

    1,libcrpto

      通用加密库,任何软件想要实现加密功能,只要链接到这个库上面即可,这个库提供了各种加密函数。

    2,libssl

      TSL/SSL的实现/库,正是有了它,我们的Linux才能够使用https等协议,这是一个基于连接的,能够实现认证、数据安全传输以及会话完整性的工具,所以SSL本身其实就是一个基于会话来实现的库。

    3,openssl

      这是一个命令行工具,叫做多功能命令行工具,能够实现单向加密、对称加密以及非对称加密,还能够使用它来生成一对密钥,而且还可以用它来模拟实现私有CA,是Linux上最基本的通用工具之一,该命令行工具的命令是由许多子命令组成的,和我们的yum命令相类似,不同的子命令用于实现不同的功能。

    OpenSSL的官方站点是www.openssl.org:

    wKiom1haeg_g06YEAADmqxp7oYk493.png      

    我们使用rpm -q 关键词 命令可以查看我们的系统上有没有安装和关键词相关的软件:

    wKioL1hae-2QpGK_AAAISdXj6mI323.png 

    rpm -ql 关键词 命令可以查看安装的软件生成的文件:

         wKiom1hafFSx4vW8AAATfzc8jl8616.png

    OpenSSL在红帽上的配置文件叫做/etc/pki/tls/openssl.cnf,这个配置文件在让openssl工作成为私有CA时会用到,平时我们在使用openssl命令行的时候是用不到这个文件:

        wKiom1hafQfjQrBfAAAKKUisYr0146.png

    使用openssl version命令也可以看到我们系统上的安装的openssl软件的版本号:

        wKioL1hafYjgNP88AAALz1CsNiU571.png

·openssl命令行工具的子命令

    1,speed子命令

        该子命令用于测试openssl对各种支持的加密算法的加密速度,会测试每一种加密算法在我们主机上的加密速度,这种速度还可以用来评估我们当前系统的加密性能,该子命令默认会计算所有加密算法的速度:

        wKiom1haft6B_DszAABAiK1ym_4303.png

    2,enc子命令

        该子命令用于加密,用法格式:

        openssl enc -加密算法 -in 要加密的文件 -out 加密后的文件名

            -e选项表示加密,但是该命令默认就是加密,不用特地指定该选项

            -d选项表示解密

            -k选项表示指定加密密钥,如果没有该选项,系统会提示我们输入密码

            -salt选项表示实现更高的安全性

            -a选项表示对纯文本进行base64编码

        wKioL1hahlvT28efAAA5DZ8kBOQ020.png

        解密:

            wKioL1haiBbS1KJGAAA5pV4ZsVQ328.png

    3,dgst子命令

        该子命令用于计算数据的特征码,用法格式:

        openssl dgst -单向加密算法 原始数据

        wKioL1haiJHyfdUTAAAQeMEswy0296.png

        md5sum命令也可以用来计算数据的基于md5单向加密算法的数据特征码:

        wKiom1haiSjBtbH-AAAOHsZwgvE886.png

        sha1sum命令也可以用来计算数据基于sha1单向加密算法的数据特征吗:

        wKiom1haiZCj70t6AAAO2Uq6mpQ668.png

    4,passwd子命令

        该子命令用于生成一段密码段。

        openssl passwd -1,表示使用md5算法计算生成的密码段的特征码:

        wKioL1haisfQelNHAAAjbfdqRAc782.png

        生成的密码段和我们保存在shadow文件中的条目的格式很相似:

        wKiom1hai0zzNY3_AAAvTK9tkWM229.png

        头两个$符之间是使用的加密算法,后两个$符之间是salt,有了salt的帮助,我们连续两次生成的特征码就会不同:

        wKiom1hai_fzB84fAAAygPEwn0c232.png

        salt在密码段中的作用就是去搅浑密码的,它存在的意义就是防止有人去反推我们的密码,按照单向加密算法的特性,输入一样,那么输出一定一样,为了保证使用单向加密算法生成的密码不一样,我们就向生成的密码段中加入了salt,但是salt并不影响我们去获取最终的结果,因为我们每次生成密码段的时候都会使用salt,但是有了salt,我们的密码就无法被别人反推,因为每次生成的salt是不一样的。

        还可以使用-salt选项来指定所加的salt:

        wKiom1hajgKB0oNIAAA1BN--5wk431.png

    5,rsautil(RSA utility)子命令

        该子命令用于进行非对称加密,openssl同样支持RSA加密算法,rsa不但支持数据加密而且还支持身份认证,但是dsa只支持身份认证。

        用法格式:openssl rsautil -in 加密文件 -out 加密后的文件名 -inkey(指定密钥)

    6,rand子命令

        该子命令用来生成伪随机数,是一个伪随机数生成工具,用法格式:

        openssl rand -base64 任意数字

        使用该命令就可以生成一堆随机数,我们如果想使用一堆随机数来当做我们的密码就可以使用该命令来实现:

        wKioL1hakH2ieXh0AABKeIXn1-8864.png 

·openssl实现私有CA

    带有加密解密过程的互联网通信都得使用到证书,如果我们想要在公司内部模拟实现一个https服务器进行通信的话,那我们就得给我们的web服务器发一个证书才可以,我们可以使用openssl来自己制作一个私有CA,一个CA想要给别人发放证书,那么首先CA自己得先有一个自己的证书,所以使用openssl实现私有CA的步骤如下:

    第一步,先生成一对密钥

       生成一对rsa私钥的命令是:

       openssl genrsa(generate rsa)->该命令用于生成rsa私钥

       因为公钥是从私钥中提取出来的,公钥源自于私钥,只要有了私钥就会有公钥,该命令就是帮助我们生成一个rsa私钥,而且该命令可以跟上数字来指定私钥的长度,默认长度是512位:

        wKiom1haknrgqNg8AABZdhCFLjU737.png

    我们可以使用输出重定向保存生成的rsa私钥:

        wKiom1hwxIWhPA_SAAAWLWFWG4c021.png

        也可以使用-out选项将rsa私钥保存在某个文件中:

        wKiom1hwxOzC75xeAABtv4hsPDM645.png

        私钥文件在我们本机中一般很少加密存放,但是私钥文件的安全性有很重要,所以我们可以通过设置私钥文件权限的方法来保证私钥文件的安全性。

        Tips:

        在当前shell命令行中使用括号括起来的命令,无论多少命令,这些命令都将会在当前shell的子shell中执行,而且执行完成之后,子shell就会退出,我们可以利用shell的这个特点来生成私钥文件的默认权限,而不会改变当前shell环境中的umask:

        wKioL1hwxtfw_19mAAAseiszZVE111.png   

        将公钥从私钥当中提取出来的命令:

        wKiom1hwx_PiTFDUAAArmqpGy6I827.png

    第二步,生成自签署的证书

        使用openssl的req(request)子命令来生成一个自签署的数字证书,命令如下:

        openssl req -new(表示一个新的申请) -x509 -key 密钥文件 -out 证书文件的位置 -days (365=一年)证书的有效期限

        wKioL1hwylexE9ZyAABg9_5U4JU825.png

        生成的证书文件是加密的,要想查看证书文件的信息可以使用命令来查看,使用的命令如下:

        openssl x509(表示使用x509格式进行处理) -text -in 证书文件名        

        wKiom1hwyxeBj3APAADL-gQZtbc529.png

    经过以上两个步骤,我们的私有CA就算是准备好了,就可以给其他用户发放证书了,但是在红帽Linux操作系统上,要想使得搭建好的CA真正能够使用,还得进行一些额外的配置,投入正常工作的CA的秘钥文件和证书文件的路径不是随便的,OpenSSL的配置文件/etc/pki/tls/openssl.cnf里面有CA配置的默认项:

    wKioL1hwzLaQ2vglAAB901QdsTA317.png

    dir->表示CA的工作目录

    certs->表示客户端证书的保存位置

    crl_dir->表示证书吊销列表的保存位置

    database->中保存给哪些人发了证书的信息

    new_certs_dir->表示新生成的证书文件保存在什么地方

    certificate->表示作为CA来讲,自己的证书保存在什么地方

    serial->表示CA签署的所有的证书的序列号(序列号为了方便我们处理证书,一般从01开始)

    crlnumber->表示证书吊销列表的工作号

    crl->表示当前证书吊销列表文件是什么

    private_key->表示CA自己的私钥文件是什么

   RANDFILE->表示随机数文件是什么(随机数文件可以自己生成)

    以上所有的目录和文件我们都得自己准备好。

    wKioL1hw1D_iYrorAABgPJ9ijqE792.png

    default_days->表示如果不指定时间,证书的默认有效时间是多长

    default_crl_days->表示证书吊销列表当中,被吊销证书的存放时间

    default_md->表示单向加密算法默认使用什么算法

    countryName->表示默认的国家代码:CN

    stateOrProvinceName->表示默认的省:Shanxi

    organizationName->表示默认的公司名称:ZhuBoLinux

    organizationalUnitName->表示默认的组织的名称:Tech

    commonName->表示默认的主机名:www.zhubo.com

    emailAddress->表示默认的email地址

    设置好以上的条目之后,我们就得给我们将要搭建的CA生成密钥和证书了,生成的私钥文件默认是要保存在/etc/pki/CA/private目录中的,故我们可以直接在CA目录中生成私钥文件:

    wKioL1hw11Tzv3TAAAAmMjBkp08448.png

    接下来再根据私钥文件生成一个自签署的数字证书,数字证书一般保存在/etc/pki/CA目录下目录中:

    wKioL1hw2D6CUpcMAABlis5ub3w175.png

    私钥文件和数字证书文件准备完成之后,我们还得在/etc/pki/CA目录下准备几个目录,它们分别是certs、newcerts和crl目录,还得准备两个文件,分别是index.txt和serial,我们还得给serial文件一个起始的证书序列号01,如果没有证书吊销列表,那么就不用添加证书吊销号码:

    wKiom1hw2mDRuVi_AAAyMfrFnGQ992.png

    到此为止一个私有CA就算准备完成了,接下来就可以给用户发放证书了。

    任何一个应用想要得到证书,那么首先它必须得有自己的私钥,因为公钥是从私钥中提取出来的每一个应用都得有自己的证书,两种不同的应用最好不要使用同一种证书,我们以http服务为例来介绍应用申请证书的流程:

    第一步:申请生成自己的私钥

        命令:(umask 077;openssl genrsa -out httpd.key 1024)

        wKiom1hw246TqAkRAAAeWVactf0934.png

    第二步:生成证书申请

        命令:openssl req -new -key httpd.key -out httpd.csr(certificate signature request:证书签署请求)

        上述命令不用加入-x509选项,因为该选项是用来生成自签署证书的,接下来所有填写的信息都得喝生成私有CA的自签署证书的一致:

        wKiom1hw3Q7xWhf2AACaw74EcG8113.png

    第三步,CA签名

        使得CA给我们的csr签名,签名之后就会成为正式的数字证书,使用命令:

        openssl ca(表示进入ca模式) -in httpd.csr -out httpd.crt -days 365

        wKiom1hw3dnQgNWKAAAxixdCYuU287.png

        签名之后,数据库就会更新,此时index.txt文件里面就会有相关的信息生成:

        wKiom1hw3lXRiFSJAAAjpEFCx3o595.png

        该条目的号码01是serial文件赋予的,此时serial文件中的号码就会加一,依次类推:

        wKiom1hw3rOQS7N0AAAV7BkZ15Q530.png

·红帽其实给我们提供了另外一个工具

    在/etc/pki/tls目录下有一个子目录叫做certs,该目录中有一个Makefile文件,我们可以在该目录中使用make命令快速生成一个测试用的数字证书,但是不能应用于生产环境,我们可以通过make命令后面的后缀来判断生成的是什么类型的文件:

    wKioL1hw39XjlFNmAABEKjofCrw312.png