加密解密技术基础、PKI及私有CA

来源:互联网 发布:五笔打字 知乎 编辑:程序博客网 时间:2024/05/17 23:44
一.前言
目前网络已经普及到每个人的生活中,我们的衣食住行全都离不开网络。早期,能买的起个人PC的人还不多,能用PC上网的人就更少了,所以当时设计网络时主要考虑的因素是“是否能通信"的问题,因此早期开发的http,smtp,ftp,pop3等常用的协议都是没有加密传输功能、使用明文传输的。但是现如今,在我们用网银支付时,用明文来传输我们的网银密码是极其不安全的。任何人只要在传输过程中截获了我们的数据包,都可以直接获取我们的银行账号和密码,非常危险!如图
加密解密技术基础、PKI及私有CA

所以我们需要使用密文传输:即将明文的数据加密后传输。而在现有公共协议上添加加密功能是非常复杂的,会修改大量的程序,甚至很多依赖他们的程序也要做修改。为了克服这个问题,起码让最流行的http能实现加密传输,网景公司推出了一个SSL协议,SSL协议会放置一个公共安全库放置在应用层与传输层之间,任何有网络传输功能的程序在编程时都可以调用这个公共安全库来对自己的传输数据进行加密操作。SSL协议的全称是Secure Sockets layer:安全套接字层。
SSL只是一种协议规范,并不是一种实体程序,任何调用SSL库实现SSL功能的程序都可以视为SSL的实现程序,比如http通过调用ssl库,就成为了https协议。
SSL协议包含了很多加密的算法与小的解决方案,囊括的知识很多。

===============================================================
二.加密解密技术基础
如果我们想在网络传输中实现加密安全传输,通常有三点需要保证:
1、保密性:上边已经说过,数据包密文传输,即便被人截获以后,他也无法看懂。
2、完整性:有这么一种情况,数据包被截获以后虽然他看不懂,但是可以随意添加一些字符上去,再放回网络中传到服务器端,这时服务器肯定是看不懂这些数据包的。所以我们还需要保证数据的完整性,防止有人恶意篡改我们的数据报文。
3、可用性:当我们加密了一段数据报文以后,如果服务器端无法解密,那这种加密方式也没有意义。所以我们要有一种通用的加密协议,能让通信双方都可以正常解密。

而网络中常见的攻击类型大致分为以下几种:
威胁保密性的攻击:窃听、通信量分析;
威胁完整性的攻击:篡改、伪装、重放、否认
威胁可用性的服务:拒绝服务攻击(Dos),分布式拒绝服务攻击(DDOS)

目前常用的解决方案有两个大类:专门用于防范攻击的安全服务;加密与解密技术
安全服务通常有以下两种工作方式
1、认证机制
2、访问控制机制

加密与解密服务则是一个重中之重,也是所有安全策略的基础,它包含很多加密方法:
1、传统加密方法:替代加密算法、置换加密算法
2、现代加密方法:现代块加密算法

每种加密方法中又包含很多不同的算法和协议
对称加密
公钥加密
单向加密
认证协议
这些加密算法会在下一节详解。

上述的知识非常的杂,,一般人很难记得这么琐碎,所以linux系统提供了一些安全工具,来简单的实现SSL协议。
最常见的工具有两种:OpenSSL,GPG,这里主要写一下OpenSSL,它是一个开源软件,应用范围非常广泛,主要由三部分组成
1、libencrypt:加密解密的基本库
2、liebssl:用来实现SSL安全通信机制的库 
3、openssl多用途命令行工具

==============================================================
三.加密算法的概念与常用方法

对称加密:
加密和解密使用同一个密钥;很都程序既可以加密又可以解密,你只需要向它提供一个密钥就可以;对称加密包含很多的的算法
1、DES:早些时候由IBM研发,它把数据分成8个字节一组的块,对每个块用56位的密钥计算加密; 这种加密方式已经被破解了,所以现在已经不再使用
2、3DES:
3、AES:它有多种长度的密钥,128位、192位、256位,384位等。比DES要安全的多
除了以上三种外,还有blowfish、twofish、IDEA、RC6、CAST5等对称加密算法。

对称加密有以下几个缺陷:
1、密钥过多:由于加密解密使用同一个密码,所以服务器每一个和用户的连接就要使用一个单独的密钥,防止其他连接到服务器的用户知晓别人的密码。
2、密钥分发困难:连接刚建立的时候,服务器和客户端需要保证彼此密钥的一致性,但是服务器在向客户机传输密钥的时候如何保证安全?


公钥加密:密钥分为一对公钥和私钥。用公钥加密的数据只能用私钥解开,用公钥自己都解不开。反之亦然
公钥:可以公开给所有人,从私钥中提取出来
私钥:通过特殊算法生成,使用者自己留存,必须保证其私密性

公钥加密可以实现以下几个功能
数字签名:主要在于让接收方确认发送方的身份
密钥交换:发送方用接收方公钥加密一个对称密钥,然后在发送给接收方
数据加密:公钥直接对数据加密的情景并不多,因为对称加密比公钥加密快3个数量级,所以通常用对称加密。公钥加密主要用来加密“对称加密时的密钥”,解决对称加密中密钥分发困难的问题。

公钥加密常用算法:RSA、DSA、ELGamal。RSA既可以用于加密解密,也可以用来签名;而DSA只能用来签名,所以用的比较少

单向加密:提取数据指纹;只能加密,不能解密
特点:
定长输出:不管多大的文件,加密后长度都一样。
雪崩效应:只要被加密的数据做出一丝改变,加密后的结果将完全不同,防止通过特征码猜测原来的数据。

功能:主要用来验证数据的完整性。

算法:
MD5:消息摘要算法,5位版本号,128位的定长输出;
SHA1:安全哈希算法,1是版本号,160位;
还有SHA224、SHA256、SHA384、SHA512
补充
DH算法,是用于密钥交换的一种算法。公钥加密算法是用公钥把“对称加密的密钥”加密后在互联网上传输给对方。只要在网上传输,就有被破解的可能。而DH算法的优势就在于不需要让密钥在互联网上传输。
简单来讲是这样实现的,A和B双方协商生成一个大素数;
A生成p和g两个数,还有一个x是A自己私下生成的
B也生成p和g,然后自己生成一个y。
A开始做运算:p^x%g。 把这个式子的结果发送给B,这时候都是明文传输,所以C可以通过互联网截获到p,g与“p^x%g”这三个值,但是要用它们反推出一个x次方值是非常困难的。
相应的B也把它的结果p^y%g发给A,A拿到这个结果直接计算x次方的值,即(p^y%g)^x,答案和p^yx%g是一样的;
而B也做相应的运算(p^x%g)^y=p^xy%g;而这个结果就是双方的密钥,不用在网络中传输,而是通过计算得到的。
结论:虽然A和B不知道彼此的x,y值,但是最后也能通过计算得到一致的密钥。

了解了这些算法之后,我们就可以看一下目前数据在传输过程中的主要步骤了!
===============================================================
四.加密传输的大体步骤与PKI体系

当主机A与主机B要通信时(假设已经建立好了SSL连接)
1、A先用MD5把要发送的数据进行单向加密,生成一个特征码(也可以用其他单向加密算法,在SSL连接建立时双方会先敲定)
2、A会用自己的私钥加密这段特征码,并将加密后的结果和数据放在一起。(这么做主要是为了对数据进行签名,如果B能用A的公钥得到特征码,说明数据肯定由A发过来的。)
3、A会用对称加密算法把整段数据进行加密,然后用B的公钥加密“对称算法的密钥",再把整段数据和被加密的密钥发送给B。(因为公钥加密大文件的数据很慢,所以先用对称算法加密文件,最后用公钥加密“对称算法的密钥”就即解决了对称加密密钥分发困难的问题,又解决了公钥加密速度慢的问题)
4、B收到数据后,先用自己的私钥解开“对称算法的密钥”,用这个密钥解开数据和密文特征码,最后用A的公钥解开密文特征码,自己再用MD5对数据本身做单向加密,用得到的特征码和A发过来的特征码比较,如果相同,说明文件没有被人篡改过。
但是这个过程中有一步就非常关键:A和B在第一次通信前如何获得对方的公钥?虽说公钥是公开的,但是有可能会出现这种情况:C跳出来说我就是B并且把自己的公钥发给了A,而A很有可能会相信C,而把数据全部发送给C。所以这个时候就需要有一个第三方的公信机构CA来保证通信双方可靠的交换公钥。
CA叫做证书颁发机构,为了保证通信双方都能可靠的拿到对方公钥而设立的一个双方都信任的可靠第三方公信机构。如果A信任某CA,则可以把自己的公钥和一些信息提交给CA认证,由CA认证通过后,会颁发一个包含A基本信息和A公钥的证书给A。
如果B想跟A做安全通信,A会把自己的证书发给B,B会先去自己信任的CA中查看A的证书是否正确有效,如果查询没问题,则B可以正常和A进行安全通信。(另:通常windows系统在安装好时就会内置了一些世界上根CA的地址,并内置了这些CA的证书。而linux则要自己想办法获取CA的证书。)
加密解密技术基础、PKI及私有CA



而生产环境中,结构并不是图中这么简单,CA服务器只是PKI体系其中的一环。

PKI(Public Key Infrastructure):公钥基础设施。它包含了如下几个机构
1、签证机构:CA (签发证书信息)
2、注册机构:RA  (主要用来接收证书申请信息)
3、证书吊销列表:CRL 
4、证书存取库:

国际标准化组织定义了X.509证书标准,用来定义证书的结构以及认证协议的标准。证书大体包含以下内容
1、版本号
2、序列号(这是这个CA发的第几个证书)
3、签名算法ID(表示了证书的数字签名使用的单向加密协议)
4、发行者名称(CA自己的域名)
5、有效期限
6、主体名称
7、主体公钥(主体表示证书的拥有者)
8、发行者的唯一标识
9、主体标识
10、发行者的签名(CA会把证书的所有内容用自己的私钥单向加密,结果放在这里。)

A拿到B的证书之后要如何去做验证呢?
1、A会用CA的公钥对B证书上的发行者签名解密,得到特征码,然后自己单向加密,进行比对,来查看证书是否完整
2、检查证书的有效期限,过期的证书不被认可
3、验证主体名称,与通信对端的名称是否一样
4、检查一下这个证书是否被CA吊销了。

===============================================================
五.SSL协议连接创建过程
上面说的传输过程只是一个逻辑上的过程,现实中,加密工作都是由程序依照SSL协议自动完成的,步骤比上面描述的要复杂的多。而目前网上最流行的HTTP协议调用了SSL库后,演化成了HTTPS协议,它虽然和HTTP使用方法很类似,但是数据传输步骤均使用密文传输,实现起来要比HTTP要复杂的多。
下面简单描述一下客户机与服务器创建SSL连接的过程
1、客户端生成一个随机数,然后对服务器发送一个“hello”信息,并把随机数传给服务器
2、服务器也生成一个随机数,并回复一个“hello”信息给客户端,并把服务器随机数传给服务器,这时服务器和客户机各有两个随机数
3、服务器把自己的证书发给客户端,并请求客户端的证书
4、客户端检查服务器的证书,然后把自己的证书发送给服务器,服务器检查客户端证书
5、客户机把前面发送的所有信息,用自己的私钥加密后发送给服务器
6、服务器用客户机的公钥检查客户机的签名
7、客户机生成一个premaster-secret随机数,用服务器的公钥加密后发送给服务器
8、服务器在接收了premaster-secret后,用自己的私钥解密,然后结合之前的两个随机数,计算出一个主密钥master-secret,而客户机也在本地做同样的操作,他们就生成了同样的主密钥。
9、客户机发送Change Cipher Spec消息,通知服务器更改传输编码方式,用之前协商好的密钥开始做加密传输(这时候只是一个请求,并未真正加密)
10、客户机将已交互的握手消息,用自己的私钥进行单向加密,然后通过FINISH消息发送给服务器,服务器收到后,用客户机的公钥解密,并用同样的方法计算一下自己发过的所有消息,然后对比,一样则说明验证成功,证明密钥和加密套件协商成功。
11、服务器端也向客户机发送Change Cipher Spec消息,并重复步骤10,向客户机发送一个finish信息,然后客户机用服务器的公钥解密特征码,再验证服务器发来的finish消息,如果比对相同,则验证成功,证明密钥和加密套件协商成功。并结束安全握手过程。
12、开始密文数据传输。

以上只是一个基本过程,大多数情况下,服务器是不需要客户端提供证书的。所以步骤3时,服务器并不会请求客户机的证书,客户机也不用提供证书。在步骤10,客户机发送特征码时,并不是使用自己的私钥加密,而是使用协商好的master-secret进行加密传给服务器。步骤11时,服务器也使用主密钥来加密握手消息的特征码,传给客户机。

===============================================================
六.TLS与OPENSSL工具的使用
虽然目前ssl是很流行的安全协议,其实它的真身并不是SSL协议本身,SSL协议是网景公司于1994年提出的,一共更新了v1.0 v2.0 v3.0。v3.0版在2008年被谷歌公司指出,有严重漏洞,在谷歌浏览器中强行废弃了SSL协议,转而启用了TLS协议。
TLS协议是由IETF组织于1999年发布,因为SSL刚出现的时候,非常流行,很多公司都在使用,而SSL是网景公司的版权协议,国际电子工程师协会不能坐视网景公司一家独大,在99年推出了TLS协议,一个公共协议,它和SSL是互相兼容的。TLS也有v1.1 v1.2 v1.3,目前1.3还处于草案状态,用的最多的是2008年发布的v1.2版本。
所以,我们平时使用的SSL协议,也有可能是TLS协议,而后者已经几乎成了实际上的标准。

TLS采用了非常精巧的分层设计
1、最底层:基础算法原语的实现
2、到数第二层:各种加密算法的实现
3、倒数第三层:组合算法实现的半成品
4、用各种组件拼装而成的各种成品密码学协议的软件
诸多应用程序可以在不同级别对SSL进行调用,可以直接调用密码学程序,也可以直接调用底层的加密算法

而上面写到的OpenSSL是SSL协议最著名的开源实现工具。这个工具如上面所述包含三块内容,前两个库主要是给程序员开发来调用的。对于运维来讲,最常接触的是第三个,openssl的命令行工具。

openssl命令行工具包括三类命令
1、标准命令:enc,ca,req,genrsa等,这些命令可以直接被使用来实现不同的功能
2、消息摘要命令:主要用于单向加密,要使用dgst来调用不同的方式(比如MD5)进行单向加密
3、加密命令:用于对数据加密解密,要使用enc来调用不同的加密方式。

使用openssl进行对称加密:支持的算法有3des、aes、blowfish、towfish
openssl enc -e -des3 -a -salt -in /etc/fstab -out fstab.bak
-e:表示这是一个加密操作
-des3:使用des3对称加密方式
-a:使用base64编码方式进行输出(base64是文本格式的编码,可以存放进文本文件里)
-salt:加密的时候加入一些杂质
-in:数据输入源
-out:数据输出位置


键入这个命令后,它会提示让我们键入一段密码作为密钥,注意解密的时候同样需要用到这个密钥。
加密解密技术基础、PKI及私有CA
openssl enc -d -des3 -a -salt -in fstab.bak -out /etc/fstab
-d:表示这是一个解密操作

单向加密:
openssl dgst -md5 /etc/fstab
加密解密技术基础、PKI及私有CA

生成用户密码:
openssl passwd -1 -salt 12345678:生成用户密文密码
-1:表示使用md5算法进行单向加密
-salt:指定杂质内容,最多8位
加密解密技术基础、PKI及私有CA
如图,输完命令之后就可以输入密码,最后得到一个加盐后的特征码,和shadow中的密码格式一样,直接复制过去就可以。另,openssl不支持-6加密即sha512算法。

生成随机数
openssl rand -base64 10
-base64 10:使用base64编码生成10位随机数。如果不加这个选项,有可能生成的随机数是二进制格式,无法保存到文本文件中。base64编码表示可以使用任何数字或字母表示,但是最后会生成两个“==”,需要手动删除,所以并不常用。
openssl rand -hex 10:使用16进制生成10位随机数,用0~F来表示
加密解密技术基础、PKI及私有CA
注意由于这里是16进制显示,所以我们输入 -hex 1会输出两位结果。图中输入-hex 10输出了20位的随机数

我们可以使用rand命令来生成passwd需要的盐,如下图
加密解密技术基础、PKI及私有CA
可以看到生成的密码前边的salt是一个随机数,是由rand命令生成的。

openssl genrsa -out /tmp/mykey 1024:生成一个长度为1024的私钥,并保存到/tmp/mykey文件中
由于私钥本身非常重要,不能透漏给任何人,所以通常在命令之前添加(umask 077)让密钥文件默认权限为600.
(umask 077 ; openssl genrsa -out /tmp/mymykey 1024) 
加密解密技术基础、PKI及私有CA
保存私钥的文件权限为600,(命令中小括号的含义是在当前shell进程下另起一个新shell运行这条命令,umask只对子shell生效,而不会影响父shell中的默认umask)
opensll rsa -in /tmp/mymykey -pubout :从一个私钥中提取与它对应的公钥
加密解密技术基础、PKI及私有CA

===============================================================
七.私有CA的建立过程

由于向国际根CA注册证书是要钱的,所以通常在公司内部我们需要用到证书进行安全通信时,可以自己搭建一个公司内部的CA,来满足公司内网的安全传输需求。
openssl 命令行工具就可以搭建私有CA。 但是要想建立一个CA,需要先看一下openssl配置文件中,ca的文件结构定义。
openssl的配置文件为/etc/pki/tls/openssl.cnf,其中有很多控制条目,其中和CA有关的条目如下图
加密解密技术基础、PKI及私有CA
其中42行定义了CA的主目录,并赋值在一个变量中
43行certs为已经签发的有效证书存放目录
44行crl表示已经吊销的证书列表存放目录
45行定义了一个索引数据库文件路径,里边存储了所有已经颁发过证书的索引信息。
50行是CA自己的自签证书存放路径
51行是用来给当前CA中的证书提供序列号的,每个证书都有这么一个唯一的标识
55行是CA自己私钥的存储路径


构建CA之前需要先把配置文件中的目录结构调整好,还需要一个CA自己的私钥。
步骤
1、生成CA自己的私钥,这里放置路径要与上面配置文件中指定的路径(55行)保持一致!
(umask 077;openssl genrsa -out /etc/pki/CA/private/cakey.pem 4096)

2、通过私钥生成CA自己的证书,生成的证书要与配置文件50行指定的路径一致。
openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/cacert.pem -days 365
(注意:这个命令实际上只是生成证书请求文件的命令,但由于现在是CA自请自签,所以才直接生成证书)
new:这是一个证书签署请求操作
x509:如果是CA自请自签操作,请添加这个选项
-key:本机的私钥文件路径, openssl会根据私钥文件自动提取公钥放入证书请求中。
-day: 证书的有效时长,默认为天

键入命令后,会提示让用户输入证书中的一些信息,包含:
加密解密技术基础、PKI及私有CA
第一行为国家
第二行为省/州的名称
第三行为城市名称
第四行为公司名称
第五行是部门名称
第六行是证书持有者的名字, 这里是CA自己创建的证书,所以天蝎CA服务器自己的域名
第七行是邮件地址,可以为空
生成的证书会以.pem作为标识结尾
加密解密技术基础、PKI及私有CA

3、为CA提供所需要的目录结构及文件
mkdir /etc/pki/CA {certs,crl,newcerts}
touch /etc/pki/CA {serial,index,txt}
(注:serial文件创建好后,需要先echo 01>/etc/pki/CA/serial生成起始证书序列号,才能正常工作)

到此,一个内网的CA服务器就创建完毕了,如果其他服务器想生成自己的证书,可以来刚建好的CA服务器上认证一下,认证步骤如下:(以web服务器为例)
注:以下操作在web服务器本地进行,和CA服务器无关。
1、和CA一样,要先生成一个自己的私钥文件
(umask 077 ; openssl genrsa -out /etc/httpd/ssl/httpd.key 4096)

2、生成证书签署请求文件
openssl req -new -key /etc/httpd/ssl/httpd.key 4096 -out /etc/httpd/ssl/httpd.csr -days 365
day指的是希望证书的有效期,但是最终有效期是什么还得看CA的决定。
命令键入后,同样要输入地区、公司等信息,由于是公司内部CA,所以公司名要与公司CA保持一致,否则认证时有可能会通过不了。并且由于现在是在web服务器上,所以持有者姓名这一项要与对外域名一致,否则用户访问时会提示证书无效等错误。
输入完毕后会在-out指定的路径生成一个csr请求文件

3、把生成的csr请求文件 想办法弄到CA服务器上,这里使用的scp命令
加密解密技术基础、PKI及私有CA

4、签署csr请求文件,这步操作当然是在CA下进行
openssl ca -in /tmp/httpd.csr -out /etc/pki/CA/certs/httpd.crt -day 365 
这里-out输出的路径要和配置文件中43行指定的路径一样,-day为最终的证书有效期

这时以crt为结尾的证书文件就生成完毕了,可以用下面的命令来查看证书内容
openssl x509 -in /etc/pki/CA/certs/httpd.crt -noout -serial -subject
这里表示只看序列号和证书持有者的信息

crt证书文件生成后,要拷贝回web服务器,之后csr请求文件就没用了,为了防止信息泄露,要及时rm掉。


吊销证书的步骤:不太常用,通常用于测试,知道就可以
1、客户端获取要吊销的证书serial(当前例子在web服务器上执行)
openssl x509 -in /etc/httpd/ssl/httpd.crt -noout -serial -subject

2、CA主机吊销证书
先根据客户端提交的serial和subject信息,对比其与本机数据库index.txt中存储的信息是否一致,如果一致则执行这个命令
openssl ca -revoke /etc/pki/CA/newcerts/证书序列号.pem

3、如果这次吊销操作是第一次吊销,还需要在创建吊销列表操作,指定一个吊销起始编号(这里有点绕,简单来说这个也是个序列号,但是只是吊销的序列号,和之前的证书序列号没有必然联系)
echo 01> /etc/pki/CA/crinumber

4、更新证书吊销列表
openssl crl ca -gencrl -out CA名字.crl

查看crl文件
openssl crl -in /PATH/FROM/CRL_FILE.crl -noout -text