公钥,私钥:
存在于非对称加密中
密钥:
存在于对称加密中
cer文件里面保存着公钥以及用户的一些信息(其实就是下面说到的数字证书)
P12(pfx)文件(cer的备份,供其它人使用,因其它人没有私钥,所有p12中也把私钥放里面了)= CER文件 + 私钥
公钥密码体制:
分为三部分:
1.公钥
2.私钥
3.加密解密算法
加密解密过程:
加密:
加密算法+公钥+内容(或者说明文)=密文(加密过程需要用到公钥)
解密:
解密算法+私钥+密文=明文(解密过程需要用到解密算法和私钥)
公钥加密的内容,只能由私钥进行解密。
公钥与算法都是公开的;
私钥是保密的。
对称加密算法:
加密和解密都是使用的同一个密钥(区别于公钥密码体制)
密钥需要做好保密,不能对外公开。
密钥:
一般是一个字符串或数字,供加解密算法使用。
非对称加密算法:
加密使用的密钥和解密使用的密钥是不相同的。(例如上面的公钥密码体制)
RSA:
RSA是一种公钥密码体制,公钥公开,私钥保密,它的加密解密算法是公开的。
公钥加密的内容只能由私钥解密;
私钥加密的内容只能由公钥解密。(这两点可以让客户端对服务器的真实性进行确认,如后面的例子)
RSA的这一对公钥、私钥都可以用来加密和解密
并且一方加密的内容可以由并且只能由对方进行解密。
签名和加密:
签名:
在信息后面再加上一段内容,可以证明信息没有被修改过。
做法:
发送方:
对信息做一个hash计算(md5)得到一个hash值加到信息中
把这个hash值加密后作为一个签名和信息一起发出去。
接收方:
对信息附带的hash值进行解密
重新计算信息的hash值,并和上面的hash值对比
如果一致,则内容没有被修改过。(因为不相同的内容计算出来的hash值不会相同)
为了防止别人修改信息内容同时也修改hash值让他们匹配,因此:
hash值一般会加密后再和信息一起发送。
一个加密通信过程的演化:
假设“服务器”和“客户”要在网络上通信,打算使用RSA对通信进行加密以保证谈话内容的安全,
“服务器”需要对外发布公钥(算法不需要公布,RSA的算法大家都知道),自己留着私钥。
“客户”通过某些途径拿到了“服务器”发布的公钥,客户并不知道私钥。
加密演化过程:
1.
正常演示:
“客户”->“服务器”:你好
“服务器”->“客户”:你好,我是服务器
别人冒充是“服务器”后:
“客户”->“黑客”:你好 // 黑客在“客户”和“服务器”之间的某个路由器上截获“客户”发给服务器的信息,然后自己冒充“服务器”
“黑客”->“客户”:你好,我是服务器
因此“客户”在接到消息后,并不能肯定这个消息就是由“服务器”发出的。
解决方法:
因为只有服务器有私钥,所以如果只要能够确认对方有私钥,那么对方就是“服务器”
2.
正常演示:
“客户”->“服务器”:你好
“服务器”->“客户”:你好,我是服务器
“客户”->“服务器”:向我证明你就是服务器
“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]
/*
{} 表示RSA加密后的内容,[ | ]表示用什么密钥和算法进行加密,后面的示例中都用这种表示方式,
例如上面的 {你好,我是服务器}[私钥|RSA] 就表示用私钥对“你好,我是服务器”进行加密后的结果。
*/
这里服务器是如何证明自己是服务器的呢?
1.首先这是使用RSA加密体制
2.用户有服务器发布的公钥
3.服务器保留密钥
4.服务器通过把明文与使用密钥加密后的密文一起发送给用户
5.用户通过使用服务器公布的公钥对收到的密文解密并对比收到的明文,一致则证明该服务器是持有私钥的,并且是自己持有的公钥对应的服务器
6.保证原理:
私钥加密的内容只能由公钥解密
别人冒充是“服务器”后:
“黑客”->“客户”:你好,我是服务器
“客户”->“黑客”:向我证明你就是服务器
“黑客”->“客户”:你好,我是服务器 {你好,我是服务器}[???|RSA]
//这里黑客无法冒充,因为他不知道私钥,无法用私钥加密某个字符串后发送给客户去验证。
“客户”->“黑客”:????
//由于“黑客”没有“服务器”的私钥,因此它发送过去的内容,“客户”是无法通过服务器的公钥解密的,因此可以认定对方是个冒牌货!
3.
通过2,可以确保服务器的真实性,但是在通信期间,内容在网络上还是无法保密的(即时使用了RSA):
正常演示:
“客户”->“服务器”:你好
“服务器”->“客户”:你好,我是服务器
“客户”->“服务器”:向我证明你就是服务器
“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]
“客户”->“服务器”:{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[公钥|RSA]
“服务器”->“客户”:{你的余额是100元}[私钥|RSA]
问题来了:
{你的余额是100元}[私钥],{你的余额是100元}这个是“服务器”用私钥加密后的内容,
由于公钥是发布出去的,所有人都知道公钥,
除了“客户”,其它的人也可以用公钥对{你的余额是100元}[私钥]进行解密,
因此服务器使用私钥向客户发送密文是没有意义的,是无法保密的;
而且服务器也不能用公钥对明文加密发给客户端,因为客户端没有私钥拿到数据也解不开。
一般解决方案:
引入对称加密
4.
正常演示:
“客户”->“服务器”:你好
“服务器”->“客户”:你好,我是服务器
“客户”->“服务器”:向我证明你就是服务器
“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]
“客户”->“服务器”:{我们后面的通信过程,用对称加密来进行,这里是对称加密算法和密钥}[公钥|RSA]
//蓝色字体的部分是对称加密的算法和密钥的具体内容,客户把它们发送给服务器。(相当于项目里面传给后台的key)
“服务器”->“客户”:{OK,收到!}[密钥|对称加密算法]
“客户”->“服务器”:{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[密钥|对称加密算法]
“服务器”->“客户”:{你的余额是100元}[密钥|对称加密算法]
/*
“客户”在确认了“服务器”的身份后,“客户”自己选择一个对称加密算法和一个密钥,把这个对称加密算法和密钥一起用公钥加密后发送给“服务器”。
注意,由于对称加密算法和密钥是用公钥加密的,就算这个加密后的内容被“黑客”截获了,由于没有私钥,“黑客”也无从知道对称加密算法和密钥的内容。
*/
总结:
RSA加密算法在这个通信过程中所起到的作用主要有两个:
1.因为私钥只有“服务器”拥有,因此“客户”可以通过判断对方是否有私钥来判断对方是否是“服务器”。
2.客户端通过RSA的掩护,安全的和服务器商量好一个对称加密算法和密钥来保证后面通信过程内容的安全。
服务器如何对外发布公钥:
有问题的做法:
a)把公钥放到互联网的某个地方的一个下载地址,事先给“客户”去下载。
或
b)每次和“客户”开始通信时,“服务器”把公钥发给“客户”。
对于a:
“客户”无法确定这个下载地址是不是“服务器”发布的
对于b:
任何人都可以自己生成一对公钥和私钥,他只要向“客户”发送他自己的公钥就可以冒充“服务器”了。示意如下:
“客户”->“黑客”:你好
//黑客截获“客户”发给“服务器”的消息
“黑客”->“客户”:你好,我是服务器,这个是我的公钥
//黑客自己生成一对公钥和私钥,把公钥发给“客户”,自己保留私钥
“客户”->“黑客”:向我证明你就是服务器
“黑客”->“客户”:你好,我是服务器 {你好,我是服务器}[黑客自己的私钥|RSA]
//客户收到“黑客”用私钥加密的信息后,是可以用“黑客”发给自己的公钥解密的,从而会误认为“黑客”是“服务器”
问题根源:
大家都可以生成公钥、私钥对,无法确认公钥对到底是谁的
如果收到“黑客”冒充“服务器”发过来的公钥,经过某种检查,如果能够发现这个公钥不是“服务器”的就好了(这个是重点)
解决方案:
引入数字证书:
一个数字证书包含以下内容:
1.证书的发布机构
2.证书的有效期
3.公钥
4.证书所有者(Subject)
5.签名所使用的算法
6.指纹以及指纹算法
数字证书可以保证数字证书里的公钥确实是这个证书的所有者(Subject)的,
或者证书可以用来确认对方的身份
即:
拿到一个数字证书,我们可以判断出这个数字证书到底是谁的
续上加密演化(使用数字证书):
5.
“客户”->“服务器”:你好
“服务器”->“客户”:你好,我是服务器,这里是我的数字证书
//这里用证书代替了公钥
“客户”->“服务器”:向我证明你就是服务器
“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]
/*
“服务器”把自己的证书发给了“客户”,而不是发送公钥
这和上面服务器发布公钥方式b有什么区别呢?
不同在于:
正如上面所希望的,要是客户能知道这个公钥是不是服务器发布的就好了,
“客户”可以根据证书校验这个证书到底是不是“服务器”的,
也就是能校验这个证书的所有者是不是“服务器”,
从而确认这个证书中的公钥的确是“服务器”的(校验方式在下面讲解)
后面的过程和以前是一样:
“客户”让“服务器”证明自己的身份,
“服务器”用私钥加密一段内容连同明文一起发给“客户”,
“客户”把加密内容用数字证书中的公钥解密后和明文对比,
如果一致,那么对方就确实是“服务器”,
然后双方协商一个对称加密来保证通信过程的安全。
到这里,整个过程就完整了
*/
通讯加密完整过程:
1. “客户”向服务端发送一个通信请求:
“客户”->“服务器”:你好
2. “服务器”向客户发送自己的数字证书。证书中有一个公钥用来加密信息,私钥由“服务器”持有
“服务器”->“客户”:你好,我是服务器,这里是我的数字证书
3.“客户”收到“服务器”的证书后,它会去验证这个数字证书到底是不是“服务器”的,数字证书有没有什么问题,数字证书如果检查没有问题,就说明数字证书中的公钥确实是“服务器”的。
(验证方式下面讲解)
4.检查数字证书后,“客户”会明文发送一个随机的字符串给“服务器”,让“服务器”用私钥去加密,服务器把加密的结果返回给“客户”,“客户”用公钥解密这个返回结果,如果解密结果与之前生成的随机字符串一致,那说明对方确实是私钥的持有者,或者说对方确实是“服务器”。
“客户”->“服务器”:向我证明你就是服务器,这是一个随机字符串
//前面的例子中为了方便解释,用的是“你好”等内容,实际情况下一般是随机生成的一个字符串。
“服务器”->“客户”:{一个随机字符串}[私钥|RSA]
5. 验证“服务器”的身份后,“客户”生成一个对称加密算法和密钥,用于后面的通信的加密和解密。这个对称加密算法和密钥,“客户”会用公钥加密后发送给“服务器”,别人截获了也没用,因为只有“服务器”手中有可以解密的私钥。这样,后面“服务器”和“客户”就都可以用对称加密算法来加密和解密通信内容了。
“客户”->“服务器”:{我们后面的通信过程,用对称加密来进行,这里是对称加密算法和密钥}[公钥|RSA]
“服务器”->“客户”:{OK,已经收到你发来的对称加密算法和密钥!有什么可以帮到你的?}[密钥|对称加密算法]
“客户”->“服务器”:{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[密钥|对称加密算法]
“服务器”->“客户”:{你好,你的余额是100元}[密钥|对称加密算法]
…… //继续其它的通信
强化版:
问题1:
对于步骤4来说,其实对于服务器来说是有威胁的,因为4中的字符串是未加任何处理的,黑客也可以发送一些简单有规律的字符串给“服务器”加密,从而寻找加密的规律,有可能威胁到私钥的安全
解决方案:
“服务器”并不是真正的加密这个字符串本身,而是把这个字符串进行一个hash计算,加密这个字符串的hash值(不加密原来的字符串)后发送给“客户”,“客户”收到后解密这个hash值并自己计算字符串的hash值然后进行对比是否一致,同样也能确定对方是否是“服务器”。
问题2:
在双方的通信过程中,“黑客”可以截获发送的加密了的内容,虽然他无法解密这个内容,但是他可以捣乱,例如把信息原封不动的发送多次,扰乱通信过程。
解决方案:
可以给通信的内容加上一个序号或者一个随机的值,如果“客户”或者“服务器”接收到的信息中有之前出现过的序号或者随机值,那么说明有人在通信过程中重发信息内容进行捣乱,双方会立刻停止通信。
问题3:
在双方的通信过程中,“黑客”除了简单的重复发送截获的消息之外,还可以修改截获后的密文修改后再发送,因为修改的是密文,虽然不能完全控制消息解密后的内容,但是仍然会破坏解密后的密文。
解决方案:
在每次发送信息时,先对信息的内容进行一个hash计算得出一个hash值,将信息的内容和这个hash值一起加密后发送。接收方在收到后进行解密得到明文的内容和hash值,然后接收方再自己对收到信息内容做一次hash计算,与收到的hash值进行对比看是否匹配,
如果匹配就说明信息在传输过程中没有被修改过。
如果不匹配说明中途有人故意对加密数据进行了修改,立刻中断通话过程后做其它处理。
证书的构成和原理:
构成的部分(大部分内容):
1.Issuer (证书的发布机构)
指明这个证书是哪个公司创建的(只是创建证书,不是指证书的使用者)
2.Valid from , Valid to (证书的有效期)
过了有效期限,证书就会作废,不能使用了。
3.Public key (公钥)
4.Subject (主题)
这个证书是发布给谁的,或者说证书的所有者,一般是某个人或者某个公司名称、机构的名称、公司网站的网址等
5.Signature algorithm (签名所使用的算法)
这个数字证书的数字签名所使用的加密算法,这样就可以使用证书发布机构的证书里面的公钥,根据这个算法对指纹进行解密。指纹的加密结果就是数字签名
6.Thumbprint, Thumbprint algorithm (指纹以及指纹算法)
保证证书的完整性的,也就是说确保证书没有被修改过,
原理就是在发布证书时,发布者根据指纹算法(一个hash算法)计算整个证书的hash值(指纹)并和证书放在一起,使用者在打开证书时,自己也根据指纹算法计算一下证书的hash值(指纹)
这个指纹会使用"SecureTrust CA"这个证书机构的私钥用签名算法(Signature algorithm)加密后和证书放在一起,因此修改证书内容后一并修改hash值也不管用,因为没有私钥
(就像上面
“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]
这里服务器是如何证明自己是服务器的呢?
1.首先这是使用RSA加密体制
2.用户有服务器发布的公钥
3.服务器保留密钥
4.服务器通过把明文与使用密钥加密后的密文一起发送给用户
5.用户通过使用服务器公布的公钥对收到的密文解密并对比收到的明文,一致则证明该服务器是持有私钥的,并且是自己持有的公钥对应的服务器
6.保证原理:
私钥加密的内容只能由公钥解密
这种RSA方式证明自己就是你想要的服务器一样)
/*
为了保证安全,在证书的发布机构发布证书时,证书的指纹和指纹算法,都会加密后再和证书放到一起发布,以防有人修改指纹后伪造相应的数字证书。(就像上面黑客想伪造自己就是服务器一样)
这里问题又来了,证书的指纹和指纹算法用什么加密呢?他们是用证书发布机构的私钥进行加密的。可以用证书发布机构的公钥对指纹和指纹算法解密,也就是说证书发布机构除了给别人发布证书外,他自己本身也有自己的证书。
证书发布机构的证书是哪里来的呢???
这个证书发布机构的数字证书(一般由他自己生成)在我们的操作系统刚安装好时(例如windows xp等操作系统),这些证书发布机构的数字证书就已经被微软(或者其它操作系统的开发机构)安装在操作系统中了
(这里可以像上面一样理解为操作系统就是客户,证书发布机构就是服务器,操作系统里面的证书就是服务器给客户发送的数字证书让客户验证自己就是正确的服务器,
也就是让操作系统拿系统存在的数字证书(有公钥)验证这个证书发布机构就是真实的证书发布机构(通过拿公钥对指纹解密对比自己计算出来的指纹是否一样而判断该证书真实性))
由于操作系统中有这些机构发布的数字证书,也就是有公钥可以对他们给公司生成的数字证书指纹解密验证该证书的有效性了。
这些证书发布机构自己持有与他自己的数字证书对应的私钥,他会用这个私钥加密所有他发布的证书的指纹作为数字签名。
*/
如何向证书的发布机构去申请证书:
证书发布机构发布证书时,把Issuer,Public key,Subject,Valid from,Valid to等信息以明文的形式写到证书里面,
然后用一个指纹算法计算出这些数字证书内容的一个指纹,
并把指纹和指纹算法用自己的私钥进行加密,然后和证书的内容一起发布,
同时证书发布机构还会给一个我们公司的私钥给到我们
把证书投入使用,我们在通信过程开始时会把证书发给对方,对方如何检查这个证书的确是合法的并且是我们公司的证书呢?
首先应用程序(对方通信用的程序,例如IE、OUTLook等)读取证书中的Issuer(发布机构)为"SecureTrust CA" ,
然后会在操作系统中受信任的发布机构的证书中去找"SecureTrust CA"的证书,
如果找不到,那说明证书的发布机构是个水货发布机构,证书可能有问题,程序会给出一个错误信息。
如果在系统中找到了"SecureTrust CA"的证书,那么应用程序就会从证书中取出"SecureTrust CA"的公钥,
然后对我们"ABC Company"公司的证书里面的指纹和指纹算法用这个公钥进行解密,
然后使用这个指纹算法计算"ABC Company"证书的指纹,将这个计算的指纹与放在证书中的指纹对比,
如果一致,说明"ABC Company"的证书肯定没有被修改过并且证书是"SecureTrust CA" 发布的,证书中的公钥肯定是"ABC Company"的。
对方然后就可以放心的使用这个公钥和我们"ABC Company"进行通信了。
/*这部分需要根据上下文理解清楚*/
证书发布机构:
其实所有的公司都可以发布证书,但是自己发布的证书不被权威机构认可,
微软在它的操作系统中,并不会信任我们这个证书发布机构,
当应用程序在检查证书的合法信的时候,一看证书的发布机构并不是操作系统所信任的发布机构,就会抛出错误信息。
也就是说windows操作系统中不会预先安装好我们这个证书发布机构的证书
iOS对cer操作: