以下是一些想法。如果你不耐烦,请跳到结论部分。
1. 什么是安全种子?
安全性只相对于攻击模型而言。我们需要一个由n位组成的序列,该序列对于攻击者有n位熵:简而言之,攻击者从可能的2n个值中选择任意一个值的概率都是相等的。
这是一个与攻击者可获得的信息相关的模型。生成和使用种子的应用程序(通常在PRNG中)知道确切的种子;种子是否“安全”并不是种子本身甚至是种子生成过程的绝对属性。重要的是攻击者对生成过程所拥有的信息量。这个信息量因情况而异;例如,在多用户系统上(比如类Unix系统,具有硬件强制应用程序隔离功能),内存访问的精确时间可以揭示关于名义上受保护的进程如何读取内存的信息。即使是远程攻击者也可以获得这样的信息。这已经在AES加密中得到证明(典型的AES实现使用内部表,其访问模式取决于密钥;攻击者通过精确计时服务器响应来强制缓存未命中并检测它们)。
种子的生命周期必须考虑在内。只要攻击者不知道种子,种子就是安全的;这个属性在之后必须仍然成立。特别地,不应该能够从随后PRNG输出的摘录中恢复种子。理想情况下,即使在某个时刻获得完整的PRNG状态,也不应该提供任何关于PRNG之前产生的比特的线索。随机数据源不会产生漂亮的均匀位(每个位的值恰好为1的概率为0.5,且位值彼此独立)。相反,随机源会产生特定于源的值集。这些值可以编码为位序列,但你得不到你的钱的价值:要拥有n比特的熵,必须具有使用远多于n比特的值进行编码的值。
在这里使用的密码工具是一个PRF,它接受任意长度的输入,并生成一个n比特的输出。这种类型的密码学安全PRF被建模为random oracle:简而言之,在给定输入的情况下,预测有关oracle输出的任何内容都是不可行的。
现在,我们有哈希函数。哈希函数必须满足一些安全属性,即抗预像、第二预像和碰撞。我们通常通过尝试看它们与随机神谕模型的偏差来分析哈希函数。这里有一个重要的点:遵循随机神谕模型的PRF将是一个好的哈希函数,但是可能存在良好的哈希函数(在抵抗预像和碰撞方面),而这些函数仍然容易与随机神谕区分开来。特别地,SHA-2函数(SHA-256、SHA-512等)被认为是安全的,但由于“长度扩展攻击”(给定h(m),可以计算出部分约束消息m'的h(m || m')而不知道m),它们与随机神谕模型不同。长度扩展攻击似乎并没有提供任何快捷方式来创建预像或碰撞,但它表明这些哈希函数不是随机神谕。对于SHA-3竞赛,NIST表示候选者不应允许这种“长度扩展”。
因此,混合步骤并不容易。现在最好的选择仍然是使用SHA-256或SHA-512,并在选择SHA-3时切换(这应该会在2012年中期左右发生)。
3. 来源
一台计算机是一个确定性的机器。为了获得一些随机性,您必须混合一些物理世界的测量结果。/dev/random
或/dev/urandom
[两者都有优点和问题,选择你的毒药];在Windows上,调用CryptGenRandom()
)。java.security.SecureRandom
之前。由于Java非常有效地将应用程序代码与硬件隔离开来,因此获得随机种子是一个艰巨的挑战。通常的解决方案是同时运行两个或三个线程,并进行疯狂的线程切换,以便每秒线程切换次数有些随机(实际上,这尝试通过操作系统调度程序操作的时间来提取随机性,这取决于在计算机上发生的事件,包括与硬件相关的事件)。这是相当不令人满意的。有人提出使用音频卡作为“白噪声”的来源,通过将放大器调到最大(即使服务器现在也有音频)。其他人则主张启动网络摄像头(我们知道网络摄像头的视频是“嘈杂”的,这对于随机性来说很好,即使网络摄像头面对的是一堵墙);但带有网络摄像头的服务器并不常见。您还可以ping一个外部网络服务器(例如www.google.com
),看看它返回所需的时间(但这可能会被攻击者窃听网络观察到)。
混合步骤的美妙之处,在于哈希函数只能累积熵;即使数据不太随机,添加数据也没有任何害处。尽可能多地通过哈希函数塞入数据。哈希函数非常快速(一个良好的SHA-512实现将在典型PC上使用单个核心处理超过150 MB/s),并且种子不经常发生。
4. 结论
使用HSM。它们价值几百或几千美元,但你的机密比这更有价值吧?HSM包括RNG硬件,运行PRNG算法,并具有防篡改功能的种子存储。此外,大多数HSM已经获得了各种国家法规的认证(例如美国的FIPS 140和欧洲的EAL级别)。
如果您太过吝啬,不愿购买HSM,或者想要保护实际上并不是很有价值的数据,那么可以使用通过哈希大量物理度量获得的种子来构建一个具有密码学安全性的PRNG。任何来自某些硬件的东西都应该被哈希,以及获取该数据的即时时间(读作“周期计数器”)。在此处应将数据哈希为兆字节。或者,更好的选择是不这样做:只需使用操作系统提供的工具,其中已经包含了这样的代码。一些PRNG具有内置策略,允许混合来自低质量来源的熵以产生高质量结果。一个非常好的生成器是Fortuna生成器。它专门使用限制风险的策略,即使任何熵源被攻击也不会有太大的风险。
enonH
给我的同伙。她知道要获取http://is.gd/enonH-(这是一个“安全”的扩展URL,它会带您到is.gd扩展页面,该页面指向完全安全的青蛙图像)。这给了我们409k位的一次性密码,或者如果我在低语“enonH”时眨眼,她知道要获取图像的哈希值,并将其用作我的下一次传输的解码密钥。
由于JPEG图像中的压缩,它们往往是相对较好的熵源,如ent所述:
$ ent frog.jpg
熵 = 7.955028 bits 每字节。最佳压缩将减少此51092字节文件的大小0%。
51092个样本的卡方分布为4409.15,随机情况下会超过这个值0.01%的时间。
数据字节的算术平均值为129.0884(127.5 =随机)。
Pi的蒙特卡罗值为3.053435115(误差 2.81%)。
串行相关系数为0.052738(完全不相关= 0.0)。
将其与我指导她使用的几乎不可能猜测的图像相结合,我的秘密烤面包机计划就安全地避开了官方的监视。
/dev/random
。这非常接近于“真正”的随机数生成器,而/dev/urandom
则可以通过PRNG生成,如果熵池耗尽的话。以下引用来自Linux内核的random.c文件。整个文件都有很多注释,非常易懂。代码本身是从PGP采用的,它的美丽不受C语言的限制,由全局结构体包装访问器标记。它是一个简单令人敬畏的设计。编写一个互联网广播客户端,从广播中随机抽取一个样本。有多个电台可以选择和/或回退。
詹姆斯是正确的。此外,您可以购买硬件来提供随机数据。我不确定在哪里看到它,但我认为我读到一些声卡带有这样的硬件。
您还可以使用像 http://www.random.org/ 这样的网站。
http://en.wikipedia.org/wiki/Hardware_random_number_generator
所以,这假设每个客户端都有一个公钥/私钥对,服务器知道每个客户端的公钥。 要生成密钥,可以使用类似于PGP的方法,在键入时计算按键之间的时间差异,因为这是不可猜测的。