简体   繁体   English

与其他方法相比,兰特在红宝石中的安全性

[英]Security of rand in ruby compared to other methods

What's the security difference between: 之间的安全性区别是什么:

rand(10**100).to_s(16)
# => "a8ef61cbac3b770580cdebb55c1d2cf65cf32b5df57ef44a3bea4658ff66ac37f93b540bfb4c2ddc33e"

And RandomSecure and all the others? 还有RandomSecure和其他所有人? is rand(...).to_s(...) secure enough? rand(...).to_s(...)足够安全?

The question is never "is this secure?" 问题永远不会是“这样安全吗?” The question is "is this secure enough for what I'm doing?" 问题是“这对于我正在做的事情是否足够安全?” I don't know what you're doing. 我不知道你在做什么

OpenSSL::Random is cryptographically secure, but it's a bit of a pain in the ass to use. OpenSSL :: Random具有加密安全性,但使用起来有点麻烦。 That's good because you should not be trying to write your own crypto code! 很好,因为您不应该尝试编写自己的加密代码! Use a library. 使用图书馆。

I can say that neither Random nor Kernel#rand are cryptographically secure PRNGs . 我可以说RandomKernel#rand都不是加密安全的PRNG SecureRandom might be, and "might be secure" doesn't cut it. SecureRandom可能是这样,并且“可能是安全的”并不能解决问题。 However, they are pretty good. 但是,它们非常好。 Much better than, say, most of the rand functions that come with C's standard library. 比说C标准库附带的大多数rand函数要好得多。

Long story short, security is only as good as the weakest link in the chain. 长话短说,安全性仅是链中最薄弱的环节。 If you don't know enough to qualify a security question with how it's being used, the Ruby PRNGs aren't going to be that weakest link. 如果您不了解如何使用安全问题来限定安全性问题,那么Ruby PRNG并不是最薄弱的环节。 You are. 你是。 No offense meant, but security flaws are far more often programmer error than weak algorithms. 没有冒犯的意思,但是安全漏洞比弱算法更容易引起程序员错误。


From the Random docs ... 从随机文档 ...

PRNGs are currently implemented as a modified Mersenne Twister with a period of 2**19937-1. PRNG当前作为经过修改的Mersenne Twister实施,期限为2 ** 19937-1。

Mersenne Twister is a solid PRNG used by many, many, many languages and libraries. Mersenne Twister是许多语言和库都使用的可靠PRNG。 It's much, much, much better than most system PRNGs. 它比大多数系统PRNG都好很多。

However, MT is not cryptographically secure ! 但是,MT 不是加密安全的 If you observe about 1000 random numbers you can predict the output. 如果观察到大约1000个随机数,则可以预测输出。 It can be made more secure, but there's no indication Ruby has done that. 可以使其更安全,但是没有迹象表明Ruby已经做到了。

But Random is better than rand ... 但是Random rand ...

[Random#rand] provides the base functionality of Kernel#rand along with better handling of floating point values. [Random#rand]提供了Kernel#rand的基本功能以及对浮点值的更好处理。 These are both interfaces to Random::DEFAULT, the Ruby system PRNG. 它们都是Ruby系统PRNG Random :: DEFAULT的接口。

::new will create a new PRNG with a state independent of Random::DEFAULT, allowing multiple generators with different seed values or sequence positions to exist simultaneously. :: new将创建一个新的PRNG,其状态独立于Random :: DEFAULT,从而允许多个具有不同种子值或序列位置的生成器同时存在。 Random objects can be marshaled, allowing sequences to be saved and resumed. 可以对随机对象进行编组,从而可以保存和恢复序列。

prng = Random.new; puts prng.rand prng = Random.new; puts prng.rand is better than puts rand because each separate instance of Random will be using a different seed (and thus a different psuedo-random pattern), whereas every call to rand is using the same seed. prng = Random.new; puts prng.rand优于puts rand因为Random每个单独实例将使用不同的种子(因此使用不同的伪随机模式),而对rand每次调用都使用相同的种子。

If your code is using rand to generate random numbers, the attacker can assume that any random number is using the same seed and the same sequence. 如果您的代码使用rand生成随机数,则攻击者可以假定任何随机数都使用相同的种子和相同的序列。 Then they can more quickly gather observations to guess at the seed. 然后他们可以更快地收集观察结果以猜测种子。

If each part of your code is using its own Random.new , now the attacker has to figure out which random number goes with which seed. 如果您的代码的每个部分都使用自己的Random.new ,那么攻击者必须找出哪个随机数与哪个种子一起出现。 This makes it harder to build a sequence of random numbers, and gives the attacker less numbers to work with. 这使得构建随机数序列变得更加困难,并且使攻击者可以使用的数字更少。


Your random number generator is only as good as its seed. 您的随机数生成器仅与其种子一样好。 Random and Kernel#rand both use... Random和Kernel#rand都使用...

If number is omitted, seeds the generator using a source of entropy provided by the operating system, if available (/dev/urandom on Unix systems or the RSA cryptographic provider on Windows), which is then combined with the time, the process id, and a sequence number. 如果省略number,则使用操作系统提供的熵源(如果适用)(在Unix系统上是/ dev / urandom,在Windows上是RSA密码提供程序),将生成器作为种子,然后与时间,进程ID,和序列号。

/dev/urandom is pretty good these days, I don't know about Windows, but ultimately it depends on the operating system and its version. 这些天, /dev/urandom相当不错,我不了解Windows,但最终它取决于操作系统及其版本。


What about SecureRandom ? 那么SecureRandom呢?

This library is an interface to secure random number generators which are suitable for generating session keys in HTTP cookies, etc. 该库是确保随机数生成器安全的接口,该生成器适用于在HTTP cookie等中生成会话密钥。

It supports the following secure random number generators: 它支持以下安全随机数生成器:

openssl OpenSSL的

/dev/urandom 的/ dev / urandom的

Win32 Win32的

That doesn't tell us much. 那没有告诉我们太多。 Peeking at the implementation, it's just a seed generator for OpenSSL::Random. 窥视实现,它只是OpenSSL :: Random的种子生成器。

               # File securerandom.rb, line 51
def self.gen_random(n)
  @pid = 0 unless defined?(@pid)
  pid = $$
  unless @pid == pid
    now = Process.clock_gettime(Process::CLOCK_REALTIME, :nanosecond)
    OpenSSL::Random.random_add([now, @pid, pid].join(""), 0.0)
    seed = Random.raw_seed(16)
    if (seed)
      OpenSSL::Random.random_add(seed, 16)
    end
    @pid = pid
  end
  return OpenSSL::Random.random_bytes(n)
end

It's making up its own seed for OpenSSL::Random out of the process id, the system clock, and whatever comes from Random.raw_seed (ie. /dev/urandom ). 它在进程ID,系统时钟以及任何来自Random.raw_seed (即/dev/urandom )的内容中组成OpenSSL::Random的种子。 I really can't say if that's cryptographically secure or not, nor if it's better than just letting OpenSSL::Random.random_bytes pick its own seed. 我真的不能说这在密码学上是否安全,还是比让OpenSSL::Random.random_bytes选择自己的种子更好。

When it comes to crypto, more can be less. 说到加密,更多可能更少。

But it has some nice methods to format the random bytes . 但是它有一些不错的格式化随机字节的方法


If you want cryptographically secure PRNG, use OpenSSL::Random . 如果要使用加密安全的PRNG,请使用OpenSSL :: Random

require 'openssl'
rand = OpenSSL::Random.random_bytes

This doesn't produce a number, it produces a stream of bytes which is what you really want for cryptography. 这不会产生数字,而是会产生字节流,而这正是您真正希望进行加密的条件。 If this doesn't make any sense to you, don't write crypto code (but do look into it!). 如果这对您没有任何意义, 请不要编写加密代码 (但请仔细研究!)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM