openssl如何做到黑客都无法冒充的安全通信?

小马哥
原创 2261       2017-08-08  

由于金融行业监管越来越趋于严格,证券、基金、银行、期货等等行业对数据通信安全性要求越来越高,而现有大部分客户会要求使用Openssl进行通信,甚至要求使用国密算法。当然,国密算法也可能是基于Openssl来实现,只是把算法嵌入进去而已。但是,在大家使用Openssl的过程中,并不了解其工作过程,往往对其一知半解。


为此笔者经过一番学习,并整理出一篇有关openssl的文章,希望能与大家互相交流。


基础概念】
symmetric key algorithms(对称加密算法)

对称加密算法中,加密和解密使用的是同一个密钥,因而对称加密算法的安全性是依赖密钥的保密性,不能对外公开,只能给使用的人。


asymmetric key algorithms (非对称加密算法)

非对称加密算法中,加密使用的密钥和解密使用的密钥不是同一个,因而称之为非对称加密算法


public-key cryptography(公钥密码体制)
公钥密码体制分为三个部分,公钥、私钥、加密解密算法,它的加密解密过程如下:

加密:通过加密算法和公钥对内容进行加密,得到密文。加密过程需要用到公钥。 

解密:通过解密算法和私钥对密文进行解密,得到明文。解密过程需要用到解密算法和私钥。由公钥加密的内容,只能由私钥进行解密,也就是说,由公钥加密的内容,如果不知道私钥,是无法解密的。


公钥密码体制的公钥和算法都是公开的,私钥是保密的。大家都以使用公钥进行加密,但是只有私钥的持有者才能解密。在实际的使用中,有需要的人会生成一对公钥和私钥,把公钥发布出去给别人使用,自己保留私钥。


RSA就是一种公钥密码体制,公钥公开,私钥保密,并且他的加密解密算法是公开的。 由公钥加密的内容只能由私钥进行解密,并且由私钥加密的内容可以并且只能由公钥进行解密。也就是说,RSA的这一对公钥、私钥都可以用来加密和解密,并且一方加密的内容可以由并且只能由对方进行解密。


Signature and encryption(签名和加密)

加密是对内容加密,密文可以通过解密进行还原。签名就是在信息的后面再加上一段内容,用作保证这个内容是没有被篡改。它的实现一般是对内容做一个hash计算,获取hash值,这个过程不可逆,也就是说无法通过hash值得出原来的内容。当信息发送出去时,把这个hash值加密后作为一个签名和内容一起发出去。 


接收方在收到信息后,会重新计算信息的hash值,并和信息所附带的hash值(解密后)进行对比,如果一致,就说明信息的内容没有被修改过,因为这里hash计算可以保证不同的内容一定会得到不同的hash值,所以只要内容一被修改,根据内容计算的hash值就会变化。当然,也可以修改信息内容的同时也修改hash值,从而让它们可以相匹配,为了防止这种情况,hash值一般都会加密后(也就是签名)再和信息一起发送,以保证这个hash值不被修改。


【Openssl的演化】
假设client和server需要通信,以 RSA使用为例来保证通信安全。由于RSA是公钥密码体制,server需要发布公钥,并且算法是公开的,自己留着私钥。client通过某方法获取到了server发布的公钥,client并不知道私钥。client是通过什么方法获取公钥,我们后面再来说明,下面看一下双方如何进行保密的通信:

数据在网络上传输,hacker完全可以冒充server来向client发送信息。如下:

这样,hacker在client和server之间的某个路由器上截获client发给服务器的信息,然后自己冒充server,因此client在接到消息后,并不能肯定这个消息就是由server发出的,某些hacker也可以冒充server发出这个消息。如何确定信息是由server发过来的呢?有一个解决方法,因为只有server有私钥,所以如果只要能够确认对方有私钥,那么对方就是server。因此通信过程可以改进为如下:

*意 这里约定一下,{} 表示RSA加密后的内容,[ | ]表示用什么密钥和算法进行加密,后面的示例中都用这种表示方式,例如上面的 {你好,我是服务器}[私钥|RSA], 就表示用私钥对“你好,我是服务器”进行加密后的结果。


为了向client证明自己是server,server把一个字符串用自己的私钥加密,把明文和加密后的密文一起发给client。对于这里的例子来说,就是把字符串 “你好,我是服务器”和这个字符串用私钥加密后的内容 {你好,我是服务器}[私钥|RSA] 发给client。


client收到信息后,用自己持有的公钥解密密文,和明文进行对比,如果一致,说明信息的确是由服务器发过来的。也就是说client把 {你好,我是服务器}[私钥|RSA] 这个内容用公钥进行解密,然后和“你好,我是服务器”对比。因为由server用私钥加密后的内容,由并且只能由公钥进行解密,私钥只有server持有,所以如果解密出来的内容是能够对得上的,那说明信息一定是从server发过来的。


假设hacker想冒充server:

*注意 这里黑客无法冒充,因为他不知道私钥,无法用私钥加密某个字符串后发送给客户去验证。

由于hacker没有server的私钥,因此它发送过去的内容,client是无法通过服务器的公钥解密的,因此可以认定对方是个冒牌货!


到这里为止,client就可以确认server的身份了,可以放心和server进行通信,但是这里有一个问题,通信的内容在网络上还是无法保密。为什么无法保密呢?通信过程不是可以用公钥、私钥加密吗?其实用RSA的私钥和公钥是不行的,我们来具体分析下过程,看下面的演示:

*注意 上面的的信息{你的余额是100元}[私钥],这个是server用私钥加密后的内容,但是我们之前说了,公钥是发布出去的,因此所有的人都知道公钥,所以除了client,其它的人也可以用公钥对{你的余额是100元}[私钥]进行解密。所以如果server用私钥加密发给client,这个信息是无法保密的,因为只要有公钥就可以解密这内容。然而server也不能用公钥对发送的内容进行加密,因为client没有私钥,发送个client也解密不了。


这样问题就又来了,那又如何解决呢?


在实际的应用过程,一般是通过引入对称加密来解决这个问题,看下面的演示:

*注意 蓝色字体的部分是对称加密的算法和密钥的具体内容,客户把它们发送给服务器。

在上面的通信过程中,client在确认了server的身份后,client自己选择一个对称加密算法和一个密钥,把这个对称加密算法和密钥一起用公钥加密后发送给server。


*由于对称加密算法和密钥是用公钥加密的,就算这个加密后的内容被hacker截获了,由于没有私钥,hacker也无从知道对称加密算法和密钥的内容。


由于是用公钥加密的,只有私钥能够解密,这样就可以保证只有server可以知道对称加密算法和密钥,而其它人不可能知道(这个对称加密算法和密钥是client自己选择的,所以client自己当然知道如何解密加密)。这样server和client就可以用对称加密算法和密钥来加密通信的内容了。


总结一下,RSA加密算法在这个通信过程中所起到的作用主要有两个:
a)因为私钥只有server拥有,因此client可以通过判断对方是否有私钥来判断对方是否是server。

b)客户端通过RSA的掩护,安全的和服务器商量好一个对称加密算法和密钥来保证后面通信过程内容的安全。


到这里,client就可以确认server的身份,并且双方的通信内容可以进行加密,其他人就算截获了通信内容,也无法解密。的确,好像通信的过程是比较安全了。但是这里还留有一个问题,在最开始我们就说过,server要对外发布公钥,那server如何把公钥发送给client呢?我们第一反应可能会想到以下的两个方法:
a)把公钥放到互联网的某个地方的一个下载地址,事先给client去下载。

b)每次和client开始通信时,server把公钥发给client。


但是这个两个方法都有一定的问题,分析如下:
对于a)方法,client无法确定这个下载地址是不是server发布的,你凭什么就相信这个地址下载的东西就是server发布的而不是别人伪造的呢,万一下载到一个假的怎么办?另外要所有的client都在通信前事先去下载公钥也很不现实。

对于b)方法,也有问题,因为任何人都可以自己生成一对公钥和私钥,他只要向client发送他自己的私钥就可以冒充server了。


为了解决这个问题,数字证书出现了,它可以解决我们上面的问题。先大概看下什么是数字证书,一个证书包含下面的具体内容:
证书的发布机构 
▪ 证书的有效期 
▪ 公钥 
▪ 证书所有者(Subject) 
▪ 签名所使用的算法 
▪ 指纹以及指纹算法


证书的内容这里就不详细解释,这里先只需要搞清楚一点,数字证书可以保证数字证书里的公钥确实是这个证书的所有者(Subject)的,或者证书可以用来确认对方的身份。也就是说,我们拿到一个数字证书,我们可以判断出这个数字证书到底是谁的。现在把前面的通信过程使用数字证书修改为如下:

上面第二次通信中,server把自己的证书发给了client,而不是发送公钥。client可以根据证书校验这个证书到底是不是server的,也就是能校验这个证书的所有者是不是server,从而确认这个证书中的公钥的确是server的。后面的过程和以前是一样,client让server证明自己的身份,server用私钥加密一段内容连同明文一起发给client,client把加密内容用数字证书中的公钥解密后和明文对比,如果一致,那么对方就确实是server,然后双方协商一个对称加密来保证通信过程的安全。到这里,整个过程就完整了,我们一起来


完整过程如下:

step1:client向server发送一个通信请求。
client -> server:你好


step2: server向client发送自己的数字证书,证书中有一个公钥用来加密信息,私钥由server持有。
server -> client:你好,我是服务器,这里是我的数字证书


step3:client收到server的证书后,它会去验证这个数字证书到底是不是server的,数字证书有没有什么问题,数字证书如果检查没有问题,就说明数字证书中的公钥确实是server的。检查数字证书后,client会发送一个随机的字符串给server用私钥去加密,服务器把加密的结果返回给client,client用公钥解密这个返回结果,如果解密结果与之前生成的随机字符串一致,那说明对方确实是私钥的持有者,或者说对方确实是server。

client -> server:向我证明你就是服务器,这是一个随机字符串

*注意 前面的例子中为了方便解释,用的是“你好”等内容,实际情况下一般是随机生成的一个字符串。

server -> client:{一个随机字符串}[私钥|RSA]


step4: 验证server的身份后,client生成一个对称加密算法和密钥,用于后面的通信的加密和解密。这个对称加密算法和密钥,client会用公钥加密后发送给server,别人截获了也没用,因为只有server手中有可以解密的私钥。这样,后面server和client就都可以用对称加密算法来加密和解密通信内容了。

server -> client:{OK,已经收到你发来的对称加密算法和密钥!有什么可以帮到你的?}[密钥|对称加密算法]

client -> server:{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[密钥|对称加密算法]

server -> client:{你好,你的余额是100元}[密钥|对称加密算法]


至此,上面的过程已经十分接近真实通信过程了,完全可以按照这个过程去理解其工作原理。

恒生技术之眼原创文章,未经授权禁止转载。详情见转载须知

联系我们

恒 生 技 术 之 眼