You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

147 lines
12 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 17 | 加密密钥是怎么来的?
你好,我是范学雷。
到目前为止,你已经跟我一起走了很长的路了。不知道这一路上,你有了哪些心得和体会?对密码学是不是多了很多新的认知和想法?这一讲,我们继续上路,踏足密码学的世界。
前几讲,我们花了很长时间讨论了对称密钥的算法,以及使用对称密钥算法要注意哪些陷阱。但是,不知道你有没有注意到,一直有一个悬而未决的问题。
我们要使用对称密钥算法,总得有对称密钥吧。那么,对称密钥是从哪儿来的?这是我们这一次要讨论的问题。
# 合格的对称密钥什么样?
对称密钥从哪里来的?在讨论这个问题之前,我们先要弄清楚另外一个问题。一个合格的对称密钥,应该满足什么样的条件呢?只有知道了需求,我们才能有解决的方案。
## 对称密钥的长度
还记得我们之前提到过的AES-128和AES-256算法吗
其中的128和256指的是密钥的长度。也就是说AES-128需要128位的密钥AES-256需要256位的密钥。一般来说一个对称密钥算法的密钥长度是固定的。这就是对称密钥的第一个要求**对称密钥的长度是由对称密钥算法确定的。**
当然这并不意味着一个对称密钥只能用于一个加密算法。一个对称密钥一般可以用于任意一个对称密钥算法只要这个对称密钥满足算法要求的密钥长度。比如一个256位的对称密钥既可以用于AES-256也可以用于ChaCha20。
可是,一个对称密钥用于两个不同算法,这不是我们推荐的用法。因为,我们要考虑算法破解的风险。如果一个算法被破解了,那么它使用的对称密钥可能也就被破解了。我们不希望一个算法的失败连累另一个算法要保护的数据。
所以大部分的应用程序接口都不会限制一个对称密钥只能用于一个算法。但是我们要有意识地避免这种情况。比如说如果一个对称密钥已经用于AES-256的加密计算了就不要再把它用于ChaCha20或者其他的加密算法了。
## 对称密钥的强度
说完了对称密钥的长度,我们来看对称密钥的强度。
有印象的话你应该记得AES-128算法的安全强度是128位AES-256算法的安全强度是256位。可是如果没有高质量的对称密钥这样的安全强度就没有意义。
举个例子如果密钥只能是阿拉伯数字那么128位的密钥就只有10^16种可能性。也就是如果使用蛮力攻击的话最多需要10^16次尝试加密密钥就能够找到加密数据就能够被破解。
如果我们把10^16转换成按位表示的安全强度也不过就是53位的安全强度这离128位的安全强度可相差太远了。所以**对称密钥的强度一定要和加密算法的强度匹配。**比如说吧AES-128算法需要128位的密钥这个密钥就要有128位的强度。
对于任意给定的密钥我们并不一定能够判断它的强度是不是足够。比如说我们并不能判断“123456”是不是比“135246”强度更大。所以当我们说密钥强度的时候其实我们关注的还有产生密钥的机制。
**首先,产生密钥的机制要有匹配的强度。**如果产生密钥的机制只有128位的安全强度它就不能提供256位安全强度的密钥。简单地说攻击产生密钥的机制就可以了。
**其次密钥在它的长度上要均匀分布。也就是说这个密钥的每一位是0还是1的概率都是50%。如果不能做到均匀分布,就会降低密钥的安全性。**比如说,我们前面提到的阿拉伯数字的密钥,就是密钥没有做到均匀分布,导致安全强度降低的例子。
还有,**密钥生成机制产生的密钥要随机**。也就是说下一个密钥要均匀分布而且不可预测。如果下一个密钥不是随机的那么下一个密钥的安全性就没有保障。如果上一个密钥是“123456”下一个密钥是“123457”只是简单地递增那么这两个密钥都是不合格的密钥。
总结起来就是,**一个合格的对称密钥,它的长度和强度要与对称密钥算法相匹配。**
## 对称密钥的秘密
在[第6讲](https://time.geekbang.org/column/article/316802),我们提到,密钥的保密性和算法的安全性是对称密钥算法安全的两个关键因素。
既然密钥需要保密,那当然也就意味着密钥有秘可保。没有秘密的密钥当然谈不上保密,不能保密的密钥也没法保护数据的机密性。总之,对称密钥要有秘密。
不过,需要注意的是,秘密也是有安全强度的。比如说,很多地方的民俗,有“猜有无”的酒令。猜的人猜测对方握紧的手里有没有东西。
对于出酒令的人来说手里有没有东西当然是一个秘密。但是这个秘密被猜中的几率是50%。如果换算成密码学的指标也就是只有1位的安全强度。1位的安全强度当然简单好玩适合于饮酒助兴。可是只有1位的安全性并不适合在计算机系统中保护我们的机密数据。
**一个合格的对称密钥,要有足够的秘密,并且它的长度和强度要与对称密钥算法相匹配。**
这三个需求看起来简单、直观,但是用起来很容易就掉进强度错配、无秘可保的坑里。好了,有了这三个需求,对称密钥从哪里来这个问题,我们就可以来一起讨论它了。
# 对称密钥从哪里来?
那么,对称密钥是从哪里来的呢?你可能觉得这个问题有点怪怪的,其实这个问题,换个说法,就是我们去哪里才能够找到长度和强度都符合要求的秘密?
先看秘密的来源,来源主要有两类:
* 一类是计算机用户持有的秘密;
* 另一类是计算机持有的秘密。
对应地,也就是对称密钥的两种来源。
## 用户持有的秘密
计算机用户持有的秘密,主要表现为只有该用户知道的秘密和只有该用户拥有的秘密两种。比如,我们能够记住的用户口令,是只有我们知道的秘密;我们的指纹,是只有我们拥有的信息。
遗憾的是,我们能够记住的密码很短,一般来说,满足不了对称密钥强度的需求;我们拥有的指纹、面容、虹膜信息,都可以复制,保守这样的秘密是一个极具挑战的任务。陌生的场合,我们摸一摸杯子,睁一睁眼睛,露一下面颊,这些所谓的秘密就都不再是秘密了。
我们拥有的生物特征不可靠,我们能够记住的又太少,那为什么指纹识别和用户密码还这么流行呢?主要原因是还是没有更好的、更简单的办法。
从我接触密码学开始,就已经有人喊口令要消亡了。二十多年了,口令依然活得有模有样,指纹/面部识别也越来越流行,尤其是需要身份认证的时候。
## 使用口令生成对称密钥
既然口令的强度不够,那如果一段加密数据,只有用户参与才能解密,那该怎么办呢?**解决的办法就是分级:使用弱的口令来保护强的密钥,然后使用强的密钥来保护私密数据。**
如果加密数据泄漏了,由于保护它的对称密钥有足够的强度,我们不用担心破解的问题。
而口令,主要用于身份认证和衍生密钥。身份认证和密钥衍生,都不是高频次的运算。 从口令推导出来的对称密钥也不保存、不长留。这些措施,都降低了口令破解带来的数据泄漏风险。
![](https://static001.geekbang.org/resource/image/2d/b3/2d9ff1f0dc3c3cedb0186c129ccb6fb3.jpeg)
使用口令生成对称密钥的办法通常成为“基于口令的密钥推导”。现在常用的基于口令的密钥推导算法是PBKDF2。我不在这里讲这个算法的细节了你可以自己去找一找相关的规范。
不过,我们需要注意的是,由于口令的安全强度不够,很容易被破解,我们需要经常地变换口令,有些公司是强制性要求。如果口令变换了,从它衍生出来的对称密钥当然也就随着变换了。
如果我们直接使用衍生出来的对称密钥加密数据,每次的口令变化,都需要把已经加密的数据重新加密一遍。这可不是好事情!
![](https://static001.geekbang.org/resource/image/8e/99/8e2yyc1d93e05379e3b83b4yy43a8699.jpeg)
所以,通常地,我们也不推荐使用口令推导出来的密钥直接加密需要留存的数据。有什么办法克服这个障碍呢?解决这个问题,我们还要再添加一个环节。也就是使用推导出的密钥保护一个使用时间更长的密钥;而使用时间更长的密钥用来保护私密数据。
![](https://static001.geekbang.org/resource/image/f6/19/f6dee390ea9e5971e31857b18768ef19.jpeg)
多了一个环节以后,如果口令发生变更,我们只需要重新加密留存的对称密钥就行了,而不需要改动已经加密了的数据。那么,这个使用时间更长的密钥是怎么来的呢?
这就需要我们讨论下一个秘密的来源了:计算机持有的秘密。
## 使用随机数生成对称密钥
计算机持有的秘密,主要用的是我们上一节所讨论的随机数。
由于随机数是不可预测的,我们只要把随机数当做秘密信息来保护,就没有其他的人或者其他的计算机能够知道这个秘密。这样看起来,随机数能够完美地契合对称密钥的需求,无论是长度强度,还是保密要求。
需要一个对称密钥的时候,如果我们知道需要的长度、强度,找对强度匹配的随机数发生器,生成一个对应长度的随机数,就可以获得一个对称密钥了。这是一个看起来很简单、直观的办法。
但是,计算机持有的秘密也有一个缺陷,就是没法转换成我们人脑能够记住的东西。我们没有办法记住随机数,更没有办法记住从随机数衍生出来的对称密钥。既然我们没有办法,解密还需要对称密钥,那就需要计算机替我们记住它。
计算机该怎么管理对称密钥,怎么保守密钥秘密?这些问题也就一下子都冒出来了。
正像我们讨论过的一样,使用口令推导出的密钥可以保护使用时间更长的密钥,当然也包括使用随机数生成的密钥。不过这种保护方式,也有很大的局限性。这种局限性又在哪里呢?还有没有其他的方式?这些问题,我们下一次再讨论。
# Take Away今日收获
今天,我们讨论了一个合格的对称密钥应该满足什么条件,以及对称密钥的两个主要来源。
通过今天的讨论,我们要:
* 了解对称密钥要满足的三个条件:长度、强度和秘密。
* 了解产生对称密钥的两个主要办法:使用随机数,或者是基于口令的密钥推导。
* 知道使用基于口令的密钥推导来保护数据的常用办法。
# 思考题
好的,又到了留思考题的时候了。
今天的思考题,我们稍微加大一点难度。不过也不用紧张,我相信只要你去反复撕扯这个问题,不管结论是什么,你都会有收获的。
我们反复强调过,我们能够记住的东西很少,我们能够记住的口令的安全强度也远远不够。那为什么从口令推导出来的密钥就能够更安全呢? 如果口令只有6位数字猜中口令的可能性是10^6。
转换成按位表示的安全强度也不过就是20位的强度。这样的安全强度我们应该担心吗如果这样的担忧是合理的我们应该怎么提高口令的安全性如果使用从口令推导出来的密钥需要注意哪些问题
欢迎在留言区留言,分享你的经验。参与讨论的人越多,我们互相学习、互相启发,能够得到的就越多。
好的,今天就这样,我们下次再聊。
元旦快乐!