大话https演化过程(对称加密、非对称加密、公钥、私钥、数字签名、数字证书)
大话https演化过程(包括概念:对称加密、非对称加密、公钥、私钥、数字签名、数字证书、https访问全过程)
在网络上发送数据是非常不安全的,非常容易被劫持或是被篡改,所以每次定向发送数据你都可以视为在广播,每次定向接收数据都可以视为在广收。而建立安全通道的难度和成本都很高,甚至安全性都不一定靠谱。
在这样的情境下,F需要向S发送一段只有S才能看的信息msg,它要如何做呢?
很容易想到一个最直接的方法:给这段信息加密,只有F和S有密钥(加密与解密采用相同的算法和密钥),这样F广播的信息虽然都能看到,但是只有S才能解密看懂
- 这个方法不用我说也肯定哪儿有问题:F的密钥是怎么传到S手上的呢?(密钥也是一段数据,也有被劫持的风险)
于是这个方法轻易地跌入了死循环的陷阱,那怎么办呢,看起来好像事情陷入了僵局。但牛逼的密码学家想到了一个妙招,他们发明了一种神奇的钥匙,用这种神奇的钥匙打破了僵局
- 神奇的钥匙不是一把,而是一套两把,比如A和B,它们的特点是:A加密的数据只有B能解密,B加密的数据只有A能解密(这是怎么实现的又是另外一回事,可以另外看相关的数学资料)
- 是这样通过神奇钥匙来解决问题的:(如果F需要向S发送一段只有S才能看的信息msg)
- 先分配给接收者S一套神奇钥匙,然后S留一把给自己,叫做私钥,比如sA,这把钥匙不公开,只给自己使用,另一把钥匙S通过广播发送给F(甚至是所有人),比如sB,这把钥匙不仅随便你怎么劫持,甚至干脆公开,所有人都可以使用,叫做公钥
- 然后F收到公钥sB后,把要发送的msg用sB加密,再把密文msg通过广播发送给S
- S收到密文msg后,使用sA进行解密,阅读到内容
- 因为在互相传送的过程中,只有公钥sB和用sB加密的密文msg被广播了,即使他们都被劫持,劫持者也无法对msg进行解密,关键的能解密的钥匙sA一直好好地呆在S手上,计划通
这个方法不仅看起来非常巧妙,而且看起来也完美无缺,但即使如此,非常遗憾,它也存在问题,而且是两个问题,虽然确切地说是一类问题
- 其实最开始的要求【F需要向S发送一段只有S才能看的信息msg】由于网络的不安全性,它具体包括两个方面
- 不能被偷看。除S之外的其他人无法阅读msg
- 不能被篡改。收到的msg确实是F发的原版msg,不是假的或者修改过的
- 你确实解决了第一个方面,但是第二个方面你完全不能防范,因为虽然劫持者得到的公钥sB不能对密文msg进行解密,但劫持者可以用公钥sB来伪造另一份jmsg,然后装作是F发送的msg送给S,S能对这个jmsg解密,而且解密之后并不能区分它是不是真的,假信息同样能对S造成危险(比如让S给某个账号打钱)
- 甚至由于同样的原因,你有没有恶寒地意识到另外一种危险的可能,那就是:最初F收到的公钥sB会不会是伪造的呢?
- 这样的话,其实你刚刚以为解决的第一个方面其实也没有解决,因为:假如最初F收到的公钥sB其实是劫持者发过来的假公钥jB,那么F就会用这个jB来对他要发送的msg进行加密,加密后广播发出去,被劫持者劫持后他就能使用他的jA来解密,窃取信息,任务失败。(不考虑 最初F会收到多份公钥、最后S收到的密文msg用sA无法解密 会引起怀疑,因为这个时候msg已经泄露了,而且引起怀疑之后问题还是在,还是需要解决)
这两个问题中其中一个问题比较好解决:确定【S收到的信息msg确实是F发送的】,没有被篡改,也就是信息要能确定地标识自己的身份
- 好像能利用神奇钥匙的另一个特点来解决问题:使用AB钥匙配对的唯一性来标识身份。大概是这样的:
- 当发送者用私钥对信息进行加密后,接收者发现公钥可以把接收的信息解密,这就说明收到的信息跟公钥的主人是同一个人(假如收到的公钥确实是他希望的发送者发来的话)
- 所以这里就可以具体这样做:
- 给F一套它的神奇钥匙,F把fA作为私钥,fB作为公钥
- F发送msg时,用它的私钥fA和S的公钥sB对msg进行双重加密
- S收到信息msg后,先用fB对msg进行解密,确定这条信息就是F发送来的,再用自己的私钥再次解密以读取信息
上面这个方法公钥身份的问题同样悬而未决,所以回到前面,最大的问题还是:如何确定【F收到的公钥sB确实是S发送的】,每一个公钥sB要能确定地标识自己的身份
- 简单用上面同样的方法想一下:
- S发送自己的公钥sB前,要先用自己的私钥sA对这个公钥sB加密;之后F收到经过sA加密的公钥sB后,如果使用sB能把它解密,那就说明这个被加密的信息确实是S发来的
- 哈哈等等,你看的时候就发现了一个很大的不对劲吧,是的,这里又出现了循环,而且非常明显:F在收到sB之前并不能对经过sA加密的信息解密,即使这个被加密的信息中就是sB,所以这个传送sB的方法行不通
那怎么办?明着传公钥会不知道是谁的,把身份加密进去传公钥对方又解不开密。身份肯定是要标识的,那不用加密的方式标识身份,换种方式标识行不行啊?这样对方确认身份的时候就不用解密,就不用担心对方没密钥解不了密了
如果不行的话那就只剩一个方法了,事先传公钥的时候要不就用一下安全通道嘞?是的,前面说的【建立安全通道的难度和成本都很高,甚至安全性都不一定靠谱】这几个问题其实是可以通过拆分然后逐个攻破的
- 可拆分成这两个维度:(这两个维度其实也是安全领域内两个永恒的主题)安全性和付出成本
- 安全性方面
- 对于个人用户来说,你确实你难以在网络上构建一条安全通道(因为你不是专业的搞安全的),但是如果你有一个靠谱的第三方机构的协助,你还是可能实现的
- 比如你把你的公钥发布到第三方机构,然后想发送给你信息的人先去第三方机构上下载你的公钥,这样你的公钥就通过一条安全通道传给了别人
- 付出成本方面
- 如果只是像上一条这样用这种方法构建安全通道的话,情况是这样的:(假如F要发送信息给S)
- 那么S要事先把自己的公钥发布到第三方机构,F也要事先把自己的公钥发布到第三方机构
- 然后F在发送之前先上第三方机构获取S的公钥,之后F把信息用S的公钥加密,再用自己的私钥加密
- 然后F把双重加密后的信息发送给S
- S收到信息后要先上第三方机构获取F的公钥,之后把收到的信息用F的公钥解密确认是F发的信息,再用自己的私钥解密读取数据
- 它会面临这些问题:
- 第三方机构需要实时维护一个巨大的公钥库,而且越来越大,存储和流量都是问题
- F给不同的对象发送信息,都要事先上第三方机构获取各种证书,而不能一次布置永久生效
- 正处于A和B连接过程中的时候,还需要另外去另一个地方C获取某个东西,非常麻烦
- 所以这种利用第三方机构构建安全通道的方法需要一些改进
- 如果只是像上一条这样用这种方法构建安全通道的话,情况是这样的:(假如F要发送信息给S)
聪明的密码学家想到了这个办法:(假如F要发送信息给S)
- 事先F和S都上第三方机构获取第三方机构的公钥
- 事先F和S都把自己的公钥发给第三方机构,然后第三方机构对他们的公钥用第三方机构的私钥进行加密,得到被加密的公钥叫做F和S的数字证书,返回给F和S
- F先向S请求要S的数字证书
- 于是S把自己的数字证书发送给F
- F使用第三方的公钥对数字证书进行解密,得到没有错的S的公钥【为什么没有错?下面要讲】
- 然后F就使用S的这个公钥对要发送的信息进行加密,再用F自己的私钥对这个信息二次加密,同时附上自己的数字证书。F把这些信息一块发给S
- S在收到信息后首先解密数字证书获得了F的公钥,然后用这个公钥对信息一次解密,能解开就说明发送信息的人是证书里写的这个人,假如证书里写的是F,那么就确定了F的身份,然后再用自己的私钥对信息进行二次解密,读取信息
- (这里其实有点像前面说的,在公钥上套一个数字证书,标识了其身份,然后不用怀疑来怀疑去了,但为什么数字证书就信了呢?)
为什么用第三方的公钥对数字证书进行解密这一过程能保证公钥的身份呢?
- 这个问题严格说来,情境是这样的:在你登录网站A时,收到一份使用数字证书私钥加密的公钥,如何能证明证书里边的公钥是网站A的公钥?
- 信任链条是这样的:
- 你最开始要知道数字证书里边是什么东西,主要有这两个匹配的东西:网站地址和网站的公钥
- 首先你电脑里记录了所有能信任的颁发数字证书的公司以及他们的公钥,这是你信任的基石,就像肯·汤普逊在他的《对深信不疑的信任》1983年获得图灵奖时的演说中说的一样:你最终还是要绝对信任某一人,在这个问题上没有第二条路可走
- 然后第一步,你检查这份证书是不是你信任的公司颁发的,如果是,使用公钥对这份证书进行解密,然后下一步
- 第二步,解密的结果是一个网站地址和网站公钥,现在,你只要核对网站地址和你现在登录的网站A是不是一个,如果是一个的话,那么证书里的这份公钥就是A网站的
但实际情况还在此基础上做了两次改进
- 对于客户来说,去第三方机构申请证书未免太繁琐了,而且这个成本什么的。。。而其实客户端可以不用证书的,因为可以用用户名和密码来校验身份
- A是服务器,B是客户
- B要登录A网站,B先获取A的证书(不管证书从哪里来的,它都能用你有的第三方公钥解密来分辨)
- 然后B对A的证书用第三方公钥进行解密(你事先会有一个列表,是确信的一些第三方公钥),得到A的公钥(而且经过验证这确实是A的)
- 然后B用A的公钥对自己要发送的【用户名和密码和自己的公钥】进行一次加密,把这密文发送给A
- A获得信息之后直接用自己的私钥解密,解密的内容中有 用户名、密码、用户的公钥
- 然后A只要验证用户名和密码就能知道用户的身份,然后确认这个公钥是这个用户的
- 接下来A发送数据就可以放心使用这个公钥进行加密了
- 又因为非对称加密非常消耗计算资源,所以客户端干脆不用非对称加密,然后只要建立好了SSL连接,双方安全地拥有了一把对称加密的钥匙之后,就都使用对称加密相互传递数据
- A是服务器,B是客户
- A有A证书,有A公钥和A私钥,B开始什么都没有,只持有第三方公钥(后来生成了一个对称密钥)
- B要登录A网站,B先获取A的证书
- 然后B对A的证书用第三方公钥进行解密,得到A的公钥(而且经过验证这确实是A的)
- 然后B用A的公钥对自己要发送的【用户名和密码和自己临时生成的一个对称密钥】进行加密,再把加密后的信息发送给A(外人没有A的私钥,所以这里传递对称密钥非常安全)
- A获得信息之后直接用自己的私钥解密,解密的内容中有 用户名、密码、对称密钥
- 然后A只要验证用户名和密码就能知道用户的身份,然后确认这个对称密钥是这个用户的
- 之后只要这个SSL连接没有关闭,后续的所有数据,无论是客户端发出的还是服务器发出的,均会使用这个对称密钥加密
- (这里使用对称密钥的安全性也是有保障的,对称加密算法中,依赖的是密钥的保密性,只要密钥没有被泄露,对称加密的结果被截获也没有什么意义。而密钥是用公钥加密的,只能由服务器解开)
虽然看起来上面这种方式已经让https非常安全了,但其实还是有些问题的:
- 假如你要访问网站A,那么一共有4种情况:
- 你要访问网站A,然后访问了网站A,网站A发送了一个网站A的证书给你
- 你要访问网站A,然后访问了网站A,网站A发送了一个网站B的证书给你
- 你要访问网站A,但是访问了类似钓鱼网站B,网站B发送了一个网站B的证书给你(网站B神通广大搞到一个证书)
- 你要访问网站A,但是访问了类似钓鱼网站B,网站B自己没有申请证书,只好发送一个网站A的证书给你
- 来分析一下:
- 第一种情况完全没有问题
- 第二种情况,发生的概率很小,而且马上就会报错,不会有上面问题
- (从这里开始你要注意一下吊诡的地方,这两种情况有钓鱼网站B加入,危险慢慢降临)
- 第四种情况,网页会报错,而且你确实是上了钓鱼网站,看起来这个https起到作用了,它阻止了你浏览钓鱼网站,阻止了你给他们发送自己的信息。但其实这种情况下,你不一定有危险,为什么呢,因为钓鱼网站发给你的证书是网站A的证书,当你向这个网站的服务器发送信息的时候是你用了网站A的证书里的公钥加密了你的用户信息,然后发送给钓鱼网站B,钓鱼网站B虽然劫持了你发送来的信息,但是它并不是A网站,它没有私钥来对你的信息解密,这样的话你的信息钓鱼网站并不能获取到(但其实这个时候我也不清楚钓鱼网站会不会有其他手段,所以这种情况也可能因为其他原因而比较危险)
- 反倒是第三种情况,这时候你上了钓鱼网站,但是网页并不会报错,因为网址和证书中的一致,https并不会阻止你上这个钓鱼网站,而且由于你用了钓鱼网站的公钥对你的信息进行加密,所以钓鱼网站可以对你的信息进行解密并获取,这时候才是真正危险的时候
- 总结就是,使用https并不能完全保证你的上网安全,其中主要是你的原因,其次https也有部分原因,具体在使用https的时候如何避免泄露信息呢:
- 所有https告诉你这个证书被冒用时,你一定要好好检查你的浏览器地址框,不要上错了网站
- 即使https没有告诉你证书被冒用,你也更加要好好检查你的浏览器地址框,不要上错了网站,这时候https并不能保护你
- 当https告诉你这个证书的颁发商不靠谱,你就也要小心,这可能有问题,也可能没问题,但是你最好还是不要上
- 希望https的颁发机构们工作细致,不要给钓鱼网站颁发证书