简体   繁体   中英

PRNG not seeded error

i'm getting an intermittent error saying that the pseudo random number generator is not seeded when trying to generate the form auth token. i've copied the relevant part of the stack trace below.

here's what i know/see: - restarting passenger seems to temporarily fix the issue - running the same code from the console works as expected - /dev/urandom exists so it should be able to use that to seed - this is happening on ubuntu 10.04, with openssl 0.9.8k, ree 1.8.7 p253, and passenger 3.0.3. - i've read about an issue on unicorn that sounds sorta like it that happens when restarting workers but haven't seen anything like that described on passenger.

SessionsController#new (ActionView::TemplateError) "PRNG not seeded"
/usr/local/lib/ruby/1.8/securerandom.rb:53:in `random_bytes'
/usr/local/lib/ruby/1.8/securerandom.rb:53:in `random_bytes'
/usr/local/lib/ruby/1.8/securerandom.rb:105:in `base64'
vendor/bundle/ruby/1.8/gems/actionpack-2.3.14/lib/action_controller/request_forgery_protection.rb:109:in `form_authenticity_token'
(eval):2:in `send'
(eval):2:in `form_authenticity_token'

pretty stumped. any help greatly appreciated.

Assuming both /dev/random and /dev/urandom are read/writeable and you are still getting this error, maybe you need to run/install an entropy generator like prngd ?

Try:

 $ sudo /etc/init.d/prngd start

And if that fails, install prngd first:

 $ sudo apt-get install prngd

A farfetched hypothesis. The relevant bit of code should be something like (possibly this is not the same version):

def self.random_bytes(n=nil)
  n ||= 16
  if defined? OpenSSL::Random
    @pid = 0 if !defined?(@pid)
    pid = $$
    if @pid != pid
      now = Time.now
      ary = [now.to_i, now.usec, @pid, pid]
      OpenSSL::Random.seed(ary.join('.'))
      @pid = pid
    end
    return OpenSSL::Random.random_bytes(n)
end

and we know that OpenSSL gives the error you reported if fed with less than 128 bits of entropy. Which is 16 bytes in all (or 18..22, if OpenSSL is clever enough to spot a string of ASCII printable characters and ignore the high bit).

The sequence initializing OpenSSL is something like, 1342652367.A.0.B; could it be possible that, sometimes, pid is small enough, and microseconds is near enough to zero, that the resulting entropy falls below the critical threshold?

This should be quite easy to test: replace

ary.join('.')

with

Digest::MD5.hexdigest(ary.join('.'))

in order to have a surely-128 bit, possibly-even-256 bit string length of reasonable unpredictability.

A more definite check would be to add an exception and print out what ary was when the error was triggered.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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