书籍信息
书名:《深入浅出密码学》
作者:[ 美 ] 戴维 • 王(David Wong)
译者:韩露露 ,谢文丽 ,杨雅希
(1)通过之前几章的学习,我们注意到,在密码学的算法(除哈希函数外)中,密钥、Nonce、初始向量(IV)、大素数生成等都会涉及随机性这个概念。在密码学的白皮书中,通常用一个顶部带美元符号的箭头 $ 来表示随机性。
←
(2)在安全类密码学应用中,随机数表现出的随机性必须不可预测。通常,我们会从不可预测的物理现象中提取密码学应用中所需的随机数。通常应用程序会利用操作系统来获取其所需的随机性,而操作系统会利用其所运行的软硬件设备来手机随机性。
(3)随机性的常见来源(也称为熵源)可能是硬件中断时间(如鼠标移动时间间隔)、软件中断时间、硬盘寻道时间等。【注:熵源,在信息论中,熵用来度量一系列数字或数据包含的随机性大小。这个术语是克劳德.香农创造的,他提出了熵的计算公私。数列越表现出不可预测性,熵值公公式计算结果就会越大(熵值为0表示完全可预测)】
(4)随机数算法的分类:
(4.1)TRNG: True Random Number Generator真随机数发生器,又叫硬件随机数发生器(Hardware Random Number Generator)。今天,越来越多的设备使用额外的传感器和硬件辅助设备来提供更好的熵源。这些硬件随机数发生器通常被称为真随机数发生器TRNG, 它们利用外部不可预测的物理现象(如热噪声)来获取随机性。但是从噪声中提取随机性是一个相当缓慢的过程,对于一些需要快速产生大量随机数的应用程序而言,提出随机性操作可能会成为应用程序的性能瓶颈。接下来介绍其他随机数算法:
(4.2)PRNG: Pseudorandom Number Generator, 伪随机数发生器。为了区分密码学和非密码学用途的PRNG,密码学用途的PRNG有时也称为CSPRNG(Cryptographically Secure PRNG),在随机数命名这方面,NIST采用与众不同的做法,它将PRNG命名为确定性随机比特发生器(Deterministic Random Bit Generator, DRGB)。非密码学的称为普通PRNG。
通常,伪随机数发生器需要一个初始的秘密信息,常称之为种子(Seed),可以从多个不同的熵源中提取出这样的种子,种子对PRNG的安全性至关重要,一旦种子确定了,整个随机数序列就确定了,且这个序列会周期性重复(尽管这个周期会非常大)。
密码学伪随机数发生器常有如下特性:
(a)高效 : PRNG可以在比TRNG短的多的时间内生成大量随机数。对很多业务场景来说,这很重要。
(b)确定性。如果两次输入的种子相同,那么伪随机数发生器会产生两个完全一样的随机数列(这个随机数列的周期可能会非常大)【 只要知道种子,就可以重放整个随机数序列,这显然不满足密码学安全性要求,不过在某些特殊场景下可能会有用。】
(c)周期性 : 从种子开始获取的随机数序列终将重复其自身。周期性也是个不满足密码学安全性要求的特征,但目前常用的PRNG的周期都非常大,在大部分场景下都可以忽略不计。PRNG的周期越大,密码学安全性就越好。
(5)伪随机数发生器不是需要一个不可预测的秘密种子(Seed)初始化吗(更准确地说,我们可以认为伪随机数发生器有一个从随机均匀分布中选取的n字节长密钥,这意味着伪随机发生器的密钥应该从所有可能的n字节长的字节串中选择,其中每个字节串选中的概率都一样)?之前学的很多秘密算法的输出都与均匀随机不可区分,那么我们是否可以使用这些算法来生成随机数呢?比如哈希函数,可扩展输出函数(XOF),分组密码,流密码和消息验证码算法可用于生成随机数。但是在实际使用上述算法生成随机数时,需要用哈希函数处理上述算法的输出,最后把得到的哈希值当作实际输出。
事实上,由于大多数机器支持AES算法,因此,我们通常把AES-CTR算法当作随机数发生器。此时,对称密码的密钥是该随机数发生器的种子,算法输出的密文就是随机数。在实践中,为了提供向前和向后保密性,实际构造会更加复杂。
(6)密钥派生:从一个秘密生成更多秘密信息(也称密钥拉伸)的密码原语有许多,伪随机数发生器只是这些算法中的一种。从一个秘密信息派生更多的秘密信息在密码学中很常见,通常称这个过程为"密钥派生"。密钥派生函数(Key Derivation Function, KDF)
密码学所需要的密钥,其本质是一个伪随机数。密钥的生成可以直接用随机数算法如PRNG或PRF(Pseudo-Random Function
,伪随机函数)生成,也可以用密钥派生算法获取。
密码学上,密钥派生函数KDF是将一个密码(可变长度)或密钥转换为一个或多个密钥的函数。注意:这里的密码
不是伪随机数,它只是便于人类记忆的一个口令,即我们平时所说的password
密钥派生的派生源有两种:
- 从一个
密钥
派生出一个或多个新的密钥
。比如在tls通信中,在双方协商出一个预主密钥之后,会从这个预主密钥派生出本次会话需要使用的一组密钥作为真正通信时使用的密钥。这个预主密钥本身已经是一个伪随机数。 - 从一个
密码
派生出一个或多个密钥
。即由用户使用的一个密码/口令/短语等派生出一个或多个密钥。
密钥派生可以认为是一种特殊的hash散列,因为它具有与散列一样的特点,甚至某些密钥派生算法本身就使用了散列或HMAC算法。某些密码学安全的KDF,比如Scrypt
和Argon2
又被称为慢哈希函数,它们在设计上就非常耗时(可能达到亚秒级别)和耗资源,这样暴力破解就需要花费实际上不可能的时间,比如上百年。
(7)常见的密钥派生算法
针对两种派生源,分别学习对应的常见密钥派生算法:
(a)从一个密钥
派生出一个或多个新的密钥
: HKDF, 基于HMAC的密钥派生算法。
(b)从一个密码
派生出一个或多个密钥
: PBKDF2、Bcrypt、Scrypt、Argon2
注:第(6),(7)两点的内容从这篇文章摘取:密码学学习笔记_03_随机数与密钥派生 - 知乎 (zhihu.com)