在大多数编程语言中,stdlib中有一个模块或函数可用于创建随机输出,如Python中的random.random()

因为这些函数多年来一直使用不加密的普通PRNG,所以这些生成器但是,由于名称“ random”而被用于加密。为什么编程语言在stdlib中为什么不只使用加密安全的PRNG?即使不需要加密,它也能够产生随机输出,而且如果使用加密,它也是安全的。

与CSPRNG相比,普通PRNG是否有优势?如果您能以一种像我这样没有加密货币背景的人能理解的方式来解释它,我将非常高兴,非常感谢! :)

评论

对于编程语言标准库的作者来说,这比对crypto.se更好。我的观点是,如果某个东西靠近“随机数生成器”一词,那么默认情况下它应该是低温摄影,并且任何以梅森·扭曲者为目标的用垃圾代替它的人都应有非常强的经验基础和深思熟虑的理由无法提供加密安全性。

‘为什么业余爱好者的枪支没有安全功能?为什么这些仅出现在专业人士的枪支上?用脚射击有好处吗?’

@SqueamishOssifrage请问您的枪支评论是什么意思?业余者的枪是什么?

@SqueamishOssifrage目标手枪,像在奥运会上使用的手枪一样,通常没有手动安全装置,也没有防止掉落时开火的功能,这不同于日常携带的枪支(警察)。这是因为它们在仔细控制的条件下使用,并且这些安全功能会影响射击精度。适合正确工作的正确工具。

如果SDCC为一个简单的8051微处理器生成的字节码需要经过努力甚至在LCG过度使用时都需要生成密码安全的随机数,我会感到讨厌。

#1 楼

首先,不安全的PRNG通常比CSPRNG更快。例如,基于/ dev / urandom的CSPRNG(如果您熟悉Linux)必须每次都调用加密内核模块驱动程序。供参考:
ChaCha20的BearSSL实现(可以用作CSPRNG)在3.10 GHz的Intel Xeon CPU上达到270.72 MB / s;

一个实现在3 GHz的Intel Xeon 5160上,典型的PRNG Mersenne Twister的最大速率达到113.4 * 32/8 = 453.6 MB / s;

甚至有更快的算法/实现。例如,根据同一篇论文,GNU科学库中的rand()函数达到227.8 * 32/8 = 911.2 MB / s。 Xorwow属于Xorshift PRNG家族,达到1388.4 MB / s。

其次,编写包括CSPRNG在内的密码软件比编写通用软件要复杂得多。

还有历史原因。至少直到1990年代,开发人员,包括从事标准化新编程语言工作的一些开发人员,都害怕处理密码算法,因为对密码的出口限制很严格,而且并未被他们完全理解。引用这样一个开发人员:


我什至没有考虑过在没有得到MSLegal团队大量法律建议的情况下,将加密强度随机性放入浏览器附带的任何内容中。我不想在世界上认为运输代码向该国敌人出口弹药的世界中,用十英尺高的杆触碰加密货币。从今天的角度来看,这听起来很疯狂,但这就是那个世界。


最近的编程语言(例如Python)呢?

有人认为,默认情况下将CSPRNG烘焙到编程语言中会导致错误的安全感,尤其是当出现新的漏洞以及处理较旧的软件时。说现在,在2018年,random是加密安全的。开发人员是否记得在处理较旧版本时检查过旧的random实际上是不安全的吗?

这件事有趣的说法是:


任何写加密货币的人不阅读文档并了解他们在做什么的代码肯定会导致更多的错误,而不仅仅是使用错误的PRNG。向stdlib添加arc4random支持可能有一个很好的论据,但是将其设置为默认设置(具有所讨论的缺点,打破向后兼容性,令人惊讶的非加密用户等)将无法修复损坏的加密代码。这样做只会给人们一种错误的安全感,并鼓励他们忽略文档并编写损坏的加密代码。


请参阅此内容,以进一步了解Python社区如何推理实现默认为CSPRNG。

TL; DR。它们更快,更容易实现。过去,由于严格的限制,人们担心加密。现在,人们担心会给人以错误的安全感。

评论


$ \ begingroup $
大多数人甚至都不需要Mersenne Twister级随机性。 C89 RNG的修改版本每次呼叫生成63位的随机性,而不是15位,可以生成大约4GB /秒的随机数。
$ \ endgroup $
–马克
18年6月29日在20:29

$ \ begingroup $
@Mark Mersenne Twister是糟糕的RNG。它是听起来最酷的名称之一,但是在统计质量,状态大小和吞吐量方面都很差。一些更现代的(非CS)PRNG在这三个方面都击败了它。我认为某些CS-PRNG甚至在单个内核上在所有方面都胜过了它,但是我没有基准。
$ \ endgroup $
–未来的安全性
18年6月29日在21:38

$ \ begingroup $
另一个原因是,在某些情况下,人们想要可重现的伪随机数序列,例如在测试中-简单生成器通常会在给定相同起始种子的情况下生成相同序列。
$ \ endgroup $
–欧文·博尔维特(Erwin Bolwidt)
18年6月30日在5:36

$ \ begingroup $
@daniel完成。的确,对于简单的应用程序,2倍的速度差异可能并不重要,但是其他应用程序(例如蒙特卡洛模拟)则大量使用了随机数。假设您有一个要在90天内完成的项目。如果您可以在90天内(使用PRNG)或180天内(使用CSPRNG)完成仿真,这会有所不同吗?我会说是的。另外,如果您的压模应用程序与实际资金挂钩(例如在赌场中),请使用CSPRNG。不良PRNG在赌场中并不好。
$ \ endgroup $
– A.达尔文
18年6月30日在6:53



$ \ begingroup $
@ErwinBolwidt CSPRNG还将在给定相同起始种子的情况下生成相同序列。在实践中,为了使它们真正安全,通常需要不断向生成器提供一些随时间变化的物理熵。但是,完全有可能在“确定性模式”下使用CSPRNG,实际上我认为某些加密应用程序中也需要这样做。
$ \ endgroup $
–leftaround关于
18-6-30上午9:17



#2 楼

对于编程语言创建者和开发者来说是个好问题。

如果您查看PEP 506背后的故事,即向标准库添加秘密模块(Python增强建议506),则OpenBSD Theo de Raadt的创建者对使用Python“随机”的开发人员感到厌倦“用于秘密内容的模块(并非用于此目的),已与Python编程语言的创建者Guido van Rossum联系。

我的想法是,当程序员需要一个模块来生成伪代码时,软件的随机性,主要用例是建模和仿真,而不是立即用于安全目的(生成随机字符串,整数,会话令牌和会话IDS等)。

因此,大多数编程语言提供了标准的PRNG和用于安全性的CSPRNG(加密安全)。

一个很好的例子是Google的Go编程语言。相对较新且绝对现代的编程语言仍提供
名为math / rand的常规PRNG包(当然,这是确定性的)

以及用于安全性的真正CSPRNG包crypto.rand(是的,您应该使用它来为会话密钥(CSRF令牌)生成随机填充。)

CSPRNG总是比PRNG慢,以交换几乎真正的随机性,这在有限的计算机系统中是无法实现的。

评论


$ \ begingroup $
iya。不太清楚最后一句话的意思。什么被换成什么?
$ \ endgroup $
–Paul Uszak
19年8月16日在21:45

$ \ begingroup $
@PaulUszak,您好!与我们的宇宙不同,计算机系统是有限的。无论CSPRNG背后的数学功能多么强大,它们仍然会从运行代码的系统中吸收熵。只要有足够的动力,机会和手段,威胁行动者就可以从物理上或远程获得对这些系统的访问权并对其进行操纵。 CSPRNG模块使用常见的计算机操作系统密码库作为源-即Windows操作系统中的CryptGenRandom或CNG-API或Linux中的getrandom(2)以及其他* Nix系统的/ dev / urandom。如果我太悲观,请让我知道:-)
$ \ endgroup $
–游击队7
19年8月16日在22:08



$ \ begingroup $
“即使偏执狂也可以有敌人”-亨利·基辛格(也许)。
$ \ endgroup $
–Paul Uszak
19年8月16日在22:21

#3 楼

许多伪随机数生成器被设计为能够生成通过指定种子值选择的可重现数字序列。对于大多数常见目的,种子值不必很大。除非程序需要超过32767个不同的数字序列,否则即使16位的值也足够了。

要使伪随机数发生器具有密码安全性,那么,可能的种子范围必须大得多。 -太大而无法容纳一个数字。此外,除非应用程序具有生成种子的密码安全方法(当然,大多数应用程序不会),否则使用CSPRNG的价值将受到限制。

评论


$ \ begingroup $
加密伪随机数生成器也可以与固定种子一起使用。实际上,由于它们是为在不同类型的计算机之间通过Internet进行协议互操作而设计的,因此可以保证它们具有可重现性,这与在C语言中调用标准库rand不同。
$ \ endgroup $
–吱吱作响的s骨
18年6月29日在21:01

$ \ begingroup $
即使每个$ 2 ^ {16} $种子产生统计上独立的输出流,对于典型的应用程序来说,这还是不够的。哪些应用程序的运行次数少于32,000(或65K)次?而且您还必须担心种子碰撞,实际上在以$ 2 ^ {n / 2} $(对于n位种子)的大小而不是$ 2 ^ {n-1} $的大小生成的多个种子周围实际上变得可能$ 2 ^ n $种子。
$ \ endgroup $
–未来的安全性
18年6月29日在21:50



$ \ begingroup $
@FutureSecurity:在许多情况下,如果手动提供种子,即使有十几个不同的流也足够了。显然,有很多情况需要的数量超过32767,大多数实现可以处理40亿,但这还远远不能满足大多数与安全性相关的应用程序的需求。
$ \ endgroup $
–超级猫
18年6月29日在22:08

#4 楼

除了由于CSPRNG实施较慢而导致的性能问题(这只会影响在随机数上花费大量CPU时间的应用程序)之外,还有一个维护问题会影响更多的应用程序。

想象一下random.random()实现为CSPRNG,并按原样使用。现在,当发现一个错误时,它是整个Python的主要安全缺陷。因此,必须将一个更大的Python库作为“安全修复程序”来分发,而不是使用一个较小的CSPRNG库,这意味着必须立即安装该库,并且必须重新启动使用该库的服务器。通常,当获得使用的库的安全修复程序时,没有简单的方法来判断您的应用程序是否受到影响,因此不使用random.random()的服务器将不得不重新启动。

更糟,如果将Python库作为一个软件包分发到给定平台上,则其中的每个错误修复都可能成为“安全修复程序”。

此外,修复与加密相关的错误random.random()可能会破坏未通过验证的应用不要将其用于加密,并且首先不需要修复。例如。对于某些软件来说,对于给定的种子依赖于特定的伪随机序列是很常见的,几乎任何修复都会改变。

评论


$ \ begingroup $
“某些软件依赖于给定种子的特定伪随机序列是很常见的”您是否有一个示例,其中程序依赖于通用随机接口(而不是显式命名的PRNG接口)返回给定种子的相同值?那将是依赖未定义行为的主要示例。
$ \ endgroup $
–纳特
18年6月30日11:24



$ \ begingroup $
@Nat The Seed实现
$ \ endgroup $
– NieDzejkob
18年6月30日在20:24

$ \ begingroup $
@Nat具有固定种子的可重复测试套件非常常见。而依靠随机返回特定值的不是UB。最糟糕的是,它是“特定于实现的行为”,实际上在某些语言和库中都有很好的定义,例如Java。
$ \ endgroup $
–德米特里·格里戈里耶夫(Dmitry Grigoryev)
18年7月2日在7:29



#5 楼

它们是两个完全不同的事物,没有重叠的目的。

在执行诸如随机模拟之类的操作时,您需要一个从0.0到1.0的均匀分布的浮点数。随机数分布比随机数中的位数更重要。这里没有熵的概念。熵是不确定性的明确定义的位数。满足的接口通常将是:

func(prngState) float // from 0.0 to 1.0, ideally uniformly and randomly distributed

密码随机数生成器为您提供一串具有已知熵的比特。在这种情况下,熵就是一切。

func(cprngState) []byte // n bytes means 8*n bits of entropy in the ideal case

对于熵的每一点,不确定性的空间都会加倍。如果sha256哈希从0到7的数字,那么熵只有3位-而不是256。256只是结果的位数。但是,如果存在3位熵,则只需要生成2 ^ 3种可能性即可计算出哈希输入。

评论


$ \ begingroup $
您可以轻松地使用CSPRNG生成浮点数...
$ \ endgroup $
–森林
18年6月30日在6:02

$ \ begingroup $
@foret,但这是用于非安全目的的为什么随机数生成器并不安全。他们并不需要安全,因此他们不必为安全而付出巨大的代价。您可以使用安全的随机数生成器满足统一分发的接口要求,这听起来似乎没有理由使用默认的不安全随机数生成器;这并不能回答为什么默认情况下它是不安全的。两者的接口和要求是不同的,并且没有重叠的目的。
$ \ endgroup $
–Rob
18年6月30日在15:13

$ \ begingroup $
两者的接口相同,并且CSPRNG的要求是PRNG要求的超集。
$ \ endgroup $
–user253751
18年7月1日在10:21

$ \ begingroup $
接口实际上是完全不同的。如果从CSPRNG中获得32个随机位,则首先获得一个位数组-所需的熵位数-作为输出返回。如果仅将这些位转换为float32,则在对数字进行浮点运算时会得到不均匀的分布。如果您将8个随机位转换为一个数字并对其进行调制,则为73,则环绕的较低数字的显示频率是原来的两倍。从(0.0 .. 1.0)开始的浮点数的PRNG需要均匀分布,并且不一定说明熵的多少位。
$ \ endgroup $
–Rob
18年7月3日在1:16

$ \ begingroup $
尝试用CSPRNG满足PRNG的最接近的方法是采用一些(熵)位,例如24位(不使用指数)。从(0 .. 2 ^ 24-1)中获取该数字,并将其缩小以均匀地适合float32(0.0 .. 1.0)。这些数字应均匀分布并随机选择。
$ \ endgroup $
–Rob
18年7月3日在1:21



#6 楼

公认的答案很好,但是我想给出一个简短的答案:伪随机数的更常见的工作量是您需要它们的快速过程,并且您需要能够在测试中获得可重复的序列。具有加密功能的伪随机数生成器没有这两个属性。

评论


$ \ begingroup $
,并且您需要能够在测试CSPRNG时获得可重复的序列,以从种子值提供确定的输出。
$ \ endgroup $
–艾拉·罗斯(Ella Rose)
18年6月30日在20:08

$ \ begingroup $
@EllaRose虽然/ dev / * random和任何Microsoft使用的都没有...
$ \ endgroup $
–Paul Uszak
18年6月30日在21:46



$ \ begingroup $
CSPRNG具有这两个属性(取决于您选择的一个)。
$ \ endgroup $
–user253751
18年7月1日在10:20