1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/lib/securerandom.rb

94 lines
2.1 KiB
Ruby
Raw Normal View History

# -*- coding: us-ascii -*-
# frozen_string_literal: true
require 'random/formatter'
# == Secure random number generator interface.
#
# This library is an interface to secure random number generators which are
# suitable for generating session keys in HTTP cookies, etc.
#
# You can use this library in your application by requiring it:
#
# require 'securerandom'
#
# It supports the following secure random number generators:
#
# * openssl
# * /dev/urandom
# * Win32
#
# SecureRandom is extended by the Random::Formatter module which
# defines the following methods:
#
# * alphanumeric
# * base64
# * choose
# * gen_random
# * hex
# * rand
# * random_bytes
# * random_number
# * urlsafe_base64
# * uuid
#
# These methods are usable as class methods of SecureRandom such as
# +SecureRandom.hex+.
#
# If a secure random number generator is not available,
# +NotImplementedError+ is raised.
module SecureRandom
class << self
def bytes(n)
return gen_random(n)
end
private
def gen_random_openssl(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.urandom(16)
if (seed)
OpenSSL::Random.random_add(seed, 16)
end
@pid = pid
end
return OpenSSL::Random.random_bytes(n)
end
def gen_random_urandom(n)
ret = Random.urandom(n)
unless ret
raise NotImplementedError, "No random device"
end
unless ret.length == n
raise NotImplementedError, "Unexpected partial read from random device: only #{ret.length} for #{n} bytes"
end
ret
end
Make SecureRandom support Ractor SecureRandom lazily defines `get_random`. Accessing the mutex to define the `get_random` method is not supported inside a Ractor. This commit defines `gen_random` when `securerandom` is required and makes it suppore Ractor (as well as thread safe). Here is a test program: ```ruby require "securerandom" r = Ractor.new do loop do Ractor.yield SecureRandom.hex end end p r.take ``` Before this commit: ``` $ make runruby ./miniruby -I./lib -I. -I.ext/common ./tool/runruby.rb --extout=.ext -- --disable-gems ./test.rb <internal:ractor>:38: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues. /Users/aaron/git/ruby/lib/securerandom.rb:94:in `gen_random': can not access instance variables of classes/modules from non-main Ractors (RuntimeError) <internal:ractor>:124:in `take': thrown by remote Ractor. (Ractor::RemoteError) from ./test.rb:9:in `<main>' /Users/aaron/git/ruby/lib/securerandom.rb:94:in `gen_random': can not access instance variables of classes/modules from non-main Ractors (RuntimeError) from /Users/aaron/git/ruby/lib/securerandom.rb:155:in `random_bytes' from /Users/aaron/git/ruby/lib/securerandom.rb:176:in `hex' from ./test.rb:5:in `block (2 levels) in <main>' from ./test.rb:4:in `loop' from ./test.rb:4:in `block in <main>' make: *** [runruby] Error ``` After this commit: ``` $ make runruby ./miniruby -I./lib -I. -I.ext/common ./tool/runruby.rb --extout=.ext -- --disable-gems ./test.rb <internal:ractor>:38: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues. "3fc8885157e3911bab4b5d7619bb0308" ```
2020-09-04 20:32:31 -04:00
begin
# Check if Random.urandom is available
Random.urandom(1)
alias gen_random gen_random_urandom
rescue RuntimeError
Make SecureRandom support Ractor SecureRandom lazily defines `get_random`. Accessing the mutex to define the `get_random` method is not supported inside a Ractor. This commit defines `gen_random` when `securerandom` is required and makes it suppore Ractor (as well as thread safe). Here is a test program: ```ruby require "securerandom" r = Ractor.new do loop do Ractor.yield SecureRandom.hex end end p r.take ``` Before this commit: ``` $ make runruby ./miniruby -I./lib -I. -I.ext/common ./tool/runruby.rb --extout=.ext -- --disable-gems ./test.rb <internal:ractor>:38: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues. /Users/aaron/git/ruby/lib/securerandom.rb:94:in `gen_random': can not access instance variables of classes/modules from non-main Ractors (RuntimeError) <internal:ractor>:124:in `take': thrown by remote Ractor. (Ractor::RemoteError) from ./test.rb:9:in `<main>' /Users/aaron/git/ruby/lib/securerandom.rb:94:in `gen_random': can not access instance variables of classes/modules from non-main Ractors (RuntimeError) from /Users/aaron/git/ruby/lib/securerandom.rb:155:in `random_bytes' from /Users/aaron/git/ruby/lib/securerandom.rb:176:in `hex' from ./test.rb:5:in `block (2 levels) in <main>' from ./test.rb:4:in `loop' from ./test.rb:4:in `block in <main>' make: *** [runruby] Error ``` After this commit: ``` $ make runruby ./miniruby -I./lib -I. -I.ext/common ./tool/runruby.rb --extout=.ext -- --disable-gems ./test.rb <internal:ractor>:38: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues. "3fc8885157e3911bab4b5d7619bb0308" ```
2020-09-04 20:32:31 -04:00
begin
require 'openssl'
rescue NoMethodError
raise NotImplementedError, "No random device"
else
alias gen_random gen_random_openssl
end
end
public :gen_random
end
end
SecureRandom.extend(Random::Formatter)