1、基础知识
这部分内容主要解释一些概念和术语,最好是先理解这部分内容。
1.1、公钥密码体制(public-key cryptography)
公钥密码体制分为三个部分, 公钥 、 私钥 、加密解密算法,它的加密解密过程如下:
- 加密:通过加密算法和公钥对内容(或者说明文)进行加密,得到密文。加密过程需要用到公钥。
- 解密:通过解密算法和私钥对密文进行解密,得到明文。解密过程需要用到解密算法和私钥。注意,由公钥加密的内容,只能由私钥进行解密,也就是说,由公钥加密的内容,如果不知道私钥,是无法解密的。
公钥密码体制 的 公钥 和算法都是公开的(这是为什么叫公钥密码体制的原因), 私钥 是保密的。大家都以使用 公钥 进行加密,但是只有 私钥 的持有者才能解密。在实际的使用中,有需要的人会生成一对 公钥 和 私钥 ,把 公钥 发布出去给别人使用,自己保留 私钥 。
1.2、对称加密算法(symmetric key algorithms)
在 对称加密算法 中,加密使用的 密钥 和解密使用的 密钥 是相同的。也就是说,加密和解密都是使用的同一个 密钥 。因此对称加密算法要保证安全性的话, 密钥 要做好保密,只能让使用的人知道,不能对外公开。这个和上面的 公钥密码体制 有所不同,公钥密码体制中加密是用 公钥 ,解密使用 私钥 ,而对称加密算法中,加密和解密都是使用同一个 密钥 ,不区分 公钥 和 私钥 。
// 密钥 ,一般就是一个字符串或数字,在加密或者解密时传递给加密/解密算法。前面在 公钥密码体制 中说到的 公钥 、 私钥 就是 密钥 , 公钥 是加密使用的 密钥 , 私钥 是解密使用的 密钥 。
1.3、非对称加密算法(asymmetric key algorithms)
在 非对称加密算法 中,加密使用的 密钥 和解密使用的 密钥 是不相同的。前面所说的 公钥密码体制 就是一种非对称加密算法,他的 公钥 和是 私钥 是不能相同的,也就是说加密使用的 密钥 和解密使用的 密钥 不同,因此它是一个 非对称加密算法 。
1.4、RSA简介
RSA是一种公钥密码体制,现在使用得很广泛。如果对RSA本身有兴趣的,后面看我有没有时间写个RSA的具体介绍。
RSA密码体制是一种公钥密码体制, 公钥 公开, 私钥 保密,它的加密解密算法是公开的。 由 公钥 加密的内容可以并且只能由 私钥 进行解密,并且由 私钥 加密的内容可以并且只能由公钥进行 解密 。也就是说, RSA的这一对公钥、私钥都可以用来加密和解密,并且一方加密的内容可以由并且只能由对方进行解密 。
1.5、签名和加密
我们说 加密 ,是指对某个内容 加密 , 加密 后的内容还可以通过 解密 进行还原。 比如我们把一封邮件进行加密, 加密 后的内容在网络上进行传输,接收者在收到后,通过 解密 可以还原邮件的真实内容。
这里主要解释一下 签名 , 签名 就是在 信息 的后面再加上一段内容,可以证明 信息 没有被修改过,怎么样可以达到这个效果呢?一般是对 信息 做一个hash计算得到一个hash值,注意,这个过程是 不可逆 的,也就是说无法通过hash值得出原来的 信息 内容。在把 信息 发送出去时,把这个hash值加密后做为一个 签名 和 信息 一起发出去。 接收方在收到 信息 后,会重新计算 信息 的hash值,并和 信息 所附带的hash值(解密后)进行对比,如果一致,就说明信息的内容没有被修改过, 因为这里hash计算可以保证不同的内容一定会得到不同的hash值 ,所以只要内容一被修改,根据 信息 内容计算的hash值就会变化。当然,不怀好意的人也可以修改 信息 内容的同时也修改hash值,从而让它们可以相匹配,为了防止这种情况,hash值一般都会加密后(也就是 签名 )再和 信息 一起发送,以保证这个hash值不被修改。至于如何让别人可以解密这个 签名 ,这个过程涉及到 数字证书 等概念,我们后面在说到 数字证书 时再详细说明,这里您先只需先理解 签名 的这个概念。
2、一个加密通信过程的演化
我们来看一个例子,现在假设“服务器”和“客户”要在网络上通信,并且他们打算使用RSA(参看前面的RSA简介)来对通信进行加密以保证谈话内容的安全。由于是使用RSA这种 公钥 密码体制,“服务器”需要对外发布 公钥 (算法不需要公布,RSA的算法大家都知道),自己留着 私钥 。“客户”通过某些途径拿到了“服务器”发布的 公钥 ,客户并不知道 私钥 。“客户”具体是通过什么途径获取 公钥 的,我们后面再来说明,下面看一下双方如何进行保密的通信:
2.1 第一回合:
“客户”->“服务器”:你好
“服务器”->“客户”:你好,我是服务器
“客户”->“服务器”:????
因为消息是在网络上传输的,有人可以冒充自己是“服务器”来向客户发送信息。例如上面的消息可以被黑客截获如下:
“客户”->“服务器”:你好
“服务器”->“客户”:你好,我是服务器
“客户”->“黑客”:你好 // 黑客在“客户”和“服务器”之间的某个路由器上截获“客户”发给服务器的信息,然后自己冒充“服务器”
“黑客”->“客户”:你好,我是服务器
因此“客户”在接到消息后,并不能肯定这个消息就是由“服务器”发出的,某些“黑客”也可以冒充“服务器”发出这个消息。如何确定信息是由“服务器”发过来的呢?有一个解决方法,因为只有服务器有 私钥 ,所以如果只要能够确认对方有 私钥 ,那么对方就是“服务器”。因此通信过程可以改进为如下:
2.2 第二回合:
“客户”->“服务器”:你好
“服务器”->“客户”:你好,我是服务器
“客户”->“服务器”:向我证明你就是服务器
“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]
// 注意这里约定一下,{} 表示RSA加密后的内容,[ | ]表示用什么密钥和算法进行加密,后面的示例中都用这种表示方式,例如上面的 {你好,我是服务器}[ 私钥 |RSA] 就表示用 私钥 对 “你好,我是服务器” 进行加密后的结果。
为了向“客户”证明自己是“服务器”, “服务器”把一个字符串用自己的 私钥 加密,把 明文 和加密后的 密文 一起发给“客户”。对于这里的例子来说,就是把字符串 “你好,我是服务器” 和这个字符串用私钥加密后的内容 {你好,我是服务器}[私钥 |RSA ] 发给客户。
“客户”收到信息后,她用自己持有的 公钥 解密密文,和明文进行对比,如果一致,说明信息的确是由服务器发过来的。也就是说“客户”把 {你好,我是服务器}[私钥 |RSA] 这个内容用 公钥 进行解密,然后和 “你好,我是服务器” 对比。因为由“服务器”用 私钥 加密后的内容, 由并且只能由 公钥 进行解密, 私钥 只有“服务器”持有,所以如果解密出来的内容是能够对得上的,那说明信息一定是从“服务器”发过来的。
假设“黑客”想冒充“服务器”:
“黑客”->“客户”:你好,我是服务器
“客户”->“黑客”:向我证明你就是服务器
“黑客”->“客户”:你好,我是服务器 {你好,我是服务器}[???|RSA] //这里黑客无法冒充,因为他不知道 私钥 ,无法用 私钥 加密某个字符串后发送给客户去验证。
“客户”->“黑客 ”:????
由于“黑客”没有“服务器”的 私钥 ,因此它发送过去的内容,“客户”是无法通过服务器的 公钥 解密的,因此可以认定对方是个冒牌货!
到这里为止,“客户”就可以确认“服务器”的身份了,可以放心和“服务器”进行通信,但是这里有一个问题,通信的内容在网络上还是无法保密。为什么无法保密呢?通信过程不是可以用 公钥 、 私钥 加密吗?其实用RSA的 私钥 和 公钥 是不行的,我们来具体分析下过程,看下面的演示:
2.3 第三回合:
“客户”->“服务器”:你好
“服务器”->“客户”:你好,我是服务器
“客户”->“服务器”:向我证明你就是服务器
“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]
“客户”->“服务器”:{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[公钥|RSA]
“服务器”->“客户”:{你的余额是100元}[私钥|RSA]
注意上面的的信息 {你的余额是100元}[私钥], 这个是“服务器”用 私钥 加密后的内容,但是我们之前说了, 公钥 是发布出去的,因此所有的人都知道 公钥 ,所以除了“客户”,其它的人也可以用 公钥 对 {你的余额是100元}[私钥] 进行解密。所以如果“服务器”用 私钥 加密发给“客户”,这个信息是无法保密的,因为只要有 公钥 就可以解密这内容。然而“服务器”也不能用 公钥 对发送的内容进行加密,因为“客户”没有 私钥 ,发送个“客户”也解密不了。
这样问题就又来了,那又如何解决呢?在实际的应用过程,一般是通过引入对称加密来解决这个问题,看下面的演示:
2.4 第四回合:
“客户”->“服务器”:你好
“服务器”->“客户”:你好,我是服务器
“客户”->“服务器”:向我证明你就是服务器
“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]
“客户”->“服务器”:{我们后面的通信过程,用对称加密来进行,这里是 对称加密算法 和 密钥 }[公钥|RSA] //蓝色字体的部分是对称加密的算法和密钥的具体内容,客户把它们发送给服务器。
“服务器”->“客户”:{OK,收到!}[密钥|对称加密算法]
“客户”->“服务器”:{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[密钥|对称加密算法]
“服务器”->“客户”:{你的余额是100元}[密钥|对称加密算法]
在上面的通信过程中,“客户”在确认了“服务器”的身份后,“客户”自己选择一个 对称加密算法 和一个 密钥 ,把这个 对称加密算法 和 密钥 一起用 公钥 加密后发送给“服务器”。注意,由于 对称加密算法 和 密钥 是用 公钥 加密的,就算这个加密后的内容被“黑客”截获了,由于没有 私钥 ,“黑客”也无从知道 对称加密算法 和 密钥 的内容。
由于是用 公钥 加密的,只有 私钥 能够解密,这样就可以保证只有服务器可以知道 对称加密算法 和 密钥 ,而其它人不可能知道(这个 对称加密算法 和 密钥 是“客户”自己选择的,所以“客户”自己当然知道如何解密加密)。这样“服务器”和“客户”就可以用 对称加密算法 和 密钥 来加密通信的内容了。
总结一下,RSA加密算法在这个通信过程中所起到的作用主要有两个:
- 因为私钥只有“服务器”拥有,因此“客户”可以通过判断对方是否有私钥来判断对方是否是“服务器”。
- 客户端通过RSA的掩护,安全的和服务器商量好一个对称加密算法和密钥来保证后面通信过程内容的安全。
如果这里您理解了为什么不用RSA去加密通信过程,而是要再确定一个 对称加密算法 来保证通信过程的安全,那么就说明前面的内容您已经理解了。(如果不清楚,再看下2.3和2.4,如果还是不清楚,那应该是我们说清楚,您可以留言提问。)
到这里,“客户”就可以确认“服务器”的身份,并且双方的通信内容可以进行加密,其他人就算截获了通信内容,也无法解密。的确,好像通信的过程是比较安全了。
但是这里还留有一个问题,在最开始我们就说过,“服务器”要对外发布 公钥 ,那“服务器”如何把 公钥 发送给“客户”呢?我们第一反应可能会想到以下的两个方法:
a)把 公钥 放到互联网的某个地方的一个下载地址,事先给“客户”去下载。
b)每次和“客户”开始通信时,“服务器”把 公钥 发给“客户”。
但是这个两个方法都有一定的问题,
对于a)方法,“客户”无法确定这个下载地址是不是“服务器”发布的,你凭什么就相信这个地址下载的东西就是“服务器”发布的而不是别人伪造的呢,万一下载到一个假的怎么办?另外要所有的“客户”都在通信前事先去下载 公钥 也很不现实。
对于b)方法,也有问题,因为任何人都可以自己生成一对 公钥 和 私钥 ,他只要向“客户”发送他自己的 私钥 就可以冒充“服务器”了。示意如下:
“客户”->“ 黑客 ”:你好 //黑客截获“客户”发给“服务器”的消息
“ 黑客 ”->“客户”:你好,我是服务器,这个是我的公钥 //黑客自己生成一对 公钥 和 私钥 ,把 公钥 发给“客户”,自己保留 私钥
“客户”->“ 黑客 ”:向我证明你就是服务器
“ 黑客 ”->“客户”:你好,我是服务器 {你好,我是服务器}[黑客自己的私钥|RSA] //客户收到“黑客”用 私钥 加密的信息后,是可以用“黑客”发给自己的 公钥 解密的,从而会误认为“黑客”是“服务器”
因此“黑客”只需要自己生成一对 公钥 和 私钥 ,然后把 公钥 发送给“客户”,自己保留 私钥 ,这样由于“客户”可以用黑客的 公钥 解密黑客的 私钥 加密的内容,“客户”就会相信“黑客”是“服务器”,从而导致了安全问题。 这里问题的根源就在于,大家都可以生成 公钥 、 私钥 对,无法确认 公钥 对到底是谁的 。 如果能够确定 公钥 到底是谁的,就不会有这个问题了。例如,如果收到“黑客”冒充“服务器”发过来的 公钥 ,经过某种检查,如果能够发现这个 公钥 不是“服务器”的就好了。
为了解决这个问题,数字证书出现了,它可以解决我们上面的问题。先大概看下什么是数字证书,一个证书包含下面的具体内容:
- 证书的发布机构
- 证书的有效期
- 公钥
- 证书所有者(Subject)
- 签名所使用的算法
- 指纹以及指纹算法
证书的内容的详细解释会在后面详细解释,这里先只需要搞清楚一点, 数字证书可以保证数字证书里的公钥确实是这个证书的所有者(Subject)的,或者证书可以用来确认对方的身份 。也就是说,我们拿到一个数字证书,我们可以判断出这个数字证书到底是谁的。至于是如何判断的,后面会在详细讨论数字证书时详细解释。现在把前面的通信过程使用数字证书修改为如下:
2.5 第五回合:
“客户”->“服务器”:你好
“服务器”->“客户”:你好,我是服务器,这里是我的数字证书 //这里用证书代替了公钥
“客户”->“服务器”:向我证明你就是服务器
“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]
注意,上面第二次通信,“服务器”把自己的证书发给了“客户”,而不是发送 公钥 。“客户”可以根据证书校验这个证书到底是不是“服务器”的,也就是能校验这个证书的所有者是不是“服务器”,从而确认这个证书中的 公钥 的确是“服务器”的。后面的过程和以前是一样,“客户”让“服务器”证明自己的身份,“服务器”用 私钥 加密一段内容连同明文一起发给“客户”,“客户”把加密内容用数字证书中的 公钥 解密后和明文对比,如果一致,那么对方就确实是“服务器”,然后双方协商一个对称加密来保证通信过程的安全。到这里,整个过程就完整了,我们回顾一下:
2.6 完整过程:
step1 : “客户”向服务端发送一个通信请求
“客户”->“服务器”:你好
step2 : “服务器”向客户发送自己的 数字证书 。证书中有一个 公钥 用来加密信息, 私钥 由“服务器”持有
“服务器”->“客户”:你好,我是服务器,这里是我的 数字证书
step3 : “客户”收到“服务器”的证书后,它会去验证这个 数字证书 到底是不是“服务器”的, 数字证书 有没有什么问题, 数字证书 如果检查没有问题,就说明 数字证书 中的 公钥 确实是“服务器”的。检查 数字证书 后,“客户”会发送一个 随机的字符串 给“服务器”用 私钥 去加密,服务器把加密的结果返回给“客户”,“客户”用 公钥 解密这个返回结果,如果解密结果与之前生成的 随机字符串 一致,那说明对方确实是 私钥 的持有者,或者说对方确实是“服务器”。
“客户”->“服务器”:向我证明你就是服务器,这是 一个随机字符串 //前面的例子中为了方便解释,用的是“你好”等内容,实际情况下一般是随机生成的一个字符串。
“服务器”->“客户”:{ 一个随机字符串 }[私钥|RSA]
step4 : 验证“服务器”的身份后,“客户”生成一个 对称加密算法 和 密钥 ,用于后面的通信的加密和解密。这个 对称加密算法 和 密钥 ,“客户”会用 公钥 加密后发送给“服务器”,别人截获了也没用,因为只有“服务器”手中有可以解密的 私钥 。这样,后面“服务器”和“客户”就都可以用 对称加密算法 来加密和解密通信内容了。
“服务器”->“客户”:{OK,已经收到你发来的对称加密算法和密钥!有什么可以帮到你的?}[密钥|对称加密算法]
“客户”->“服务器”:{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[密钥|对称加密算法]
“服务器”->“客户”:{你好,你的余额是100元}[密钥|对称加密算法]
…… //继续其它的通信
2.7 其它问题:
上面的过程已经十分接近HTTPS的真实通信过程了,完全可以按照这个过程去理解HTTPS的工作原理。但是我为了方便解释,上面有些细节没有说到,有兴趣的人可以看下这部分的内容。可以跳过不看,无关紧要。
【问题1】
上面的通信过程中说到,在检查完证书后,“客户”发送一个随机的字符串给“服务器”去用私钥加密,以便判断对方是否真的持有私钥。但是有一个问题,“黑客”也可以发送一个字符串给“服务器”去加密并且得到加密后的内容,这样对于“服务器”来说是不安全的,因为黑客可以发送一些简单的有规律的字符串给“服务器”加密,从而寻找加密的规律,有可能威胁到私钥的安全。所以说,“服务器”随随便便用私钥去加密一个来路不明的字符串并把结果发送给对方是不安全的。
〖解决方法〗
每次收到“客户”发来的要加密的的字符串时,“服务器”并不是真正的加密这个字符串本身,而是把这个字符串进行一个hash计算,加密这个字符串的hash值(不加密原来的字符串)后发送给“客户”,“客户”收到后解密这个hash值并自己计算字符串的hash值然后进行对比是否一致。也就是说,“服务器”不直接加密收到的字符串,而是加密这个字符串的一个hash值,这样就避免了加密那些有规律的字符串,从而降低被破解的机率。“客户”自己发送的字符串,因此它自己可以计算字符串的hash值,然后再把“服务器”发送过来的加密的hash值和自己计算的进行对比,同样也能确定对方是否是“服务器”。
【问题2】
在双方的通信过程中,“黑客”可以截获发送的加密了的内容,虽然他无法解密这个内容,但是他可以捣乱,例如把信息原封不动的发送多次,扰乱通信过程。
〖解决方法〗
可以给通信的内容加上一个序号或者一个随机的值,如果“客户”或者“服务器”接收到的信息中有之前出现过的序号或者随机值,那么说明有人在通信过程中重发信息内容进行捣乱,双方会立刻停止通信。有人可能会问,如果有人一直这么捣乱怎么办?那不是无法通信了? 答案是的确是这样的,例如有人控制了你连接互联网的路由器,他的确可以针对你。但是一些重要的应用,例如军队或者政府的内部网络,它们都不使用我们平时使用的公网,因此一般人不会破坏到他们的通信。
【问题3】
在双方的通信过程中,“黑客”除了简单的重复发送截获的消息之外,还可以修改截获后的密文修改后再发送,因为修改的是密文,虽然不能完全控制消息解密后的内容,但是仍然会破坏解密后的密文。因此发送过程如果黑客对密文进行了修改,“客户”和“服务器”是无法判断密文是否被修改的。虽然不一定能达到目的,但是“黑客”可以一直这样碰碰运气。
〖解决方法〗
在每次发送信息时,先对信息的内容进行一个hash计算得出一个hash值,将信息的内容和这个hash值一起加密后发送。接收方在收到后进行解密得到明文的内容和hash值,然后接收方再自己对收到信息内容做一次hash计算,与收到的hash值进行对比看是否匹配,如果匹配就说明信息在传输过程中没有被修改过。如果不匹配说明中途有人故意对加密数据进行了修改,立刻中断通话过程后做其它处理。
3. 证书的构成和原理
3.1 证书的构成和原理
之前已经大概说了一个证书由什么构成,但是没有仔细进行介绍,这里对证书的内容做一个详细的介绍。先看下一个证书到底是个什么东西,在windows下查看一个证书时,界面是这样的,我们主要关注一下Details Tab页,其中的内容比较长,我滚动内容后后抓了三个图,把完整的信息显示出来:
里面的内容比较多——Version、Serial number、Signature algorithm 等等,挑几个重要的解释一下。
◆Issuer (证书的发布机构)
指出是什么机构发布的这个证书,也就是指明这个证书是哪个公司创建的(只是创建证书,不是指证书的使用者)。对于上面的这个证书来说,就是指"SecureTrust CA"这个机构。
◆Valid from , Valid to (证书的有效期)
也就是证书的有效时间,或者说证书的使用期限。 过了有效期限,证书就会作废,不能使用了。
◆Public key (公钥)
这个我们在前面介绍公钥密码体制时介绍过,公钥是用来对消息进行加密的,第2章的例子中经常用到的。这个数字证书的公钥是2048位的,它的值可以在图的中间的那个对话框中看得到,是很长的一串数字。
◆Subject (主题)
这个证书是发布给谁的,或者说证书的所有者,一般是某个人或者某个公司名称、机构的名称、公司网站的网址等。 对于这里的证书来说,证书的所有者是Trustwave这个公司。
◆Signature algorithm (签名所使用的算法)
就是指的这个数字证书的数字签名所使用的加密算法,这样就可以使用证书发布机构的证书里面的公钥,根据这个算法对指纹进行解密。指纹的加密结果就是数字签名(第1.5节中解释过数字签名)。
◆Thumbprint, Thumbprint algorithm (指纹(hash值)以及指纹算法(hash算法))
这个是用来保证证书的完整性的,也就是说确保证书没有被修改过,这东西的作用和2.7中说到的第3个问题类似。 其原理就是在发布证书时,发布者根据指纹算法(一个hash算法)计算整个证书的hash值(指纹)并和证书放在一起,使用者在打开证书时,自己也根据指纹算法计算一下证书的hash值(指纹),如果和刚开始的值对得上,就说明证书没有被修改过,因为证书的内容被修改后,根据证书的内容计算的出的hash值(指纹)是会变化的。 注意,这个指纹会使用"SecureTrust CA"这个证书机构的私钥用签名算法(Signature algorithm)加密后和证书放在一起。
注意,为了保证安全,在证书的发布机构发布证书时,证书的指纹和指纹算法,都会加密后再和证书放到一起发布,以防有人修改指纹后伪造相应的数字证书。这里问题又来了,证书的指纹和指纹算法用什么加密呢?他们是用证书发布机构的 私钥 进行加密的。可以用证书发布机构的 公钥 对指纹和指纹算法解密, 也就是说证书发布机构除了给别人发布证书外,他自己本身也有自己的证书 。证书发布机构的证书是哪里来的呢???这个证书发布机构的数字证书(一般由他自己生成)在我们的操作系统刚安装好时(例如windows xp等操作系统),这些证书发布机构的数字证书就已经被微软(或者其它操作系统的开发机构)安装在操作系统中了,微软等公司会根据一些权威安全机构的评估选取一些信誉很好并且通过一定的安全认证的证书发布机构,把这些证书发布机构的证书默认就安装在操作系统里面了,并且设置为操作系统信任的数字证书。这些证书发布机构自己持有与他自己的数字证书对应的 私钥 ,他会用这个 私钥 加密所有他发布的证书的指纹作为数字签名。