Bug #4579 » securerandom.rb.diff
| lib/securerandom.rb (working copy) | ||
|---|---|---|
| 
       # NotImplementedError is raised. 
   | 
||
| 
       def self.random_bytes(n=nil) 
   | 
||
| 
         n ||= 16 
   | 
||
| 
         if defined? OpenSSL::Random 
   | 
||
| 
           @pid = $$ if !defined?(@pid) 
   | 
||
| 
           pid = $$ 
   | 
||
| 
           if @pid != pid 
   | 
||
| 
             now = Time.now 
   | 
||
| 
             ary = [now.to_i, now.usec, @pid, pid] 
   | 
||
| 
             OpenSSL::Random.seed(ary.to_s) 
   | 
||
| 
             @pid = pid 
   | 
||
| 
           end 
   | 
||
| 
           return OpenSSL::Random.random_bytes(n) 
   | 
||
| 
         end 
   | 
||
| 
         if !defined?(@has_urandom) || @has_urandom 
   | 
||
| 
           @has_urandom = false 
   | 
||
| 
           flags = File::RDONLY 
   | 
||
| test/test_securerandom.rb (revision 0) | ||
|---|---|---|
| 
     require 'test/unit' 
   | 
||
| 
     require 'securerandom' 
   | 
||
| 
     require 'tempfile' 
   | 
||
| 
     # This testcase does NOT aim to test cryptographically strongness and randomness. 
   | 
||
| 
     class TestSecureRandom < Test::Unit::TestCase 
   | 
||
| 
       def setup 
   | 
||
| 
         @it = SecureRandom 
   | 
||
| 
       end 
   | 
||
| 
       def test_s_random_bytes 
   | 
||
| 
         assert_equal(16, @it.random_bytes.size) 
   | 
||
| 
         65.times do |idx| 
   | 
||
| 
           assert_equal(idx, @it.random_bytes(idx).size) 
   | 
||
| 
         end 
   | 
||
| 
       end 
   | 
||
| 
     # This test took 2 minutes on my machine. 
   | 
||
| 
     # And 65536 times loop could not be enough for forcing PID recycle. 
   | 
||
| 
     if false 
   | 
||
| 
       def test_s_random_bytes_is_fork_safe 
   | 
||
| 
         begin 
   | 
||
| 
           require 'openssl' 
   | 
||
| 
         rescue LoadError 
   | 
||
| 
           return 
   | 
||
| 
         end 
   | 
||
| 
         SecureRandom.random_bytes(8) 
   | 
||
| 
         pid, v1 = forking_random_bytes 
   | 
||
| 
         assert(check_forking_random_bytes(pid, v1), 'Process ID not recycled?') 
   | 
||
| 
       end 
   | 
||
| 
       def forking_random_bytes 
   | 
||
| 
         r, w = IO.pipe 
   | 
||
| 
         pid = fork { 
   | 
||
| 
           r.close 
   | 
||
| 
           w.write SecureRandom.random_bytes(8) 
   | 
||
| 
           w.close 
   | 
||
| 
         } 
   | 
||
| 
         w.close 
   | 
||
| 
         v = r.read(8) 
   | 
||
| 
         r.close 
   | 
||
| 
         Process.waitpid2(pid) 
   | 
||
| 
         [pid, v] 
   | 
||
| 
       end 
   | 
||
| 
       def check_forking_random_bytes(target_pid, target) 
   | 
||
| 
         65536.times do 
   | 
||
| 
           pid = fork { 
   | 
||
| 
             if $$ == target_pid 
   | 
||
| 
               v2 = SecureRandom.random_bytes(8) 
   | 
||
| 
               if v2 == target 
   | 
||
| 
                 exit(1) 
   | 
||
| 
               else 
   | 
||
| 
                 exit(2) 
   | 
||
| 
               end 
   | 
||
| 
             end 
   | 
||
| 
             exit(3) 
   | 
||
| 
           } 
   | 
||
| 
           pid, status = Process.waitpid2(pid) 
   | 
||
| 
           case status.exitstatus 
   | 
||
| 
           when 1 
   | 
||
| 
             raise 'returned same sequence for same PID' 
   | 
||
| 
           when 2 
   | 
||
| 
             return true 
   | 
||
| 
           end 
   | 
||
| 
         end 
   | 
||
| 
         false # not recycled? 
   | 
||
| 
       end 
   | 
||
| 
     end 
   | 
||
| 
       def test_s_random_bytes_without_openssl 
   | 
||
| 
         begin 
   | 
||
| 
           require 'openssl' 
   | 
||
| 
         rescue LoadError 
   | 
||
| 
           return 
   | 
||
| 
         end 
   | 
||
| 
         begin 
   | 
||
| 
           load_path = $LOAD_PATH.dup 
   | 
||
| 
           loaded_features = $LOADED_FEATURES.dup 
   | 
||
| 
           openssl = Object.instance_eval { remove_const(:OpenSSL) } 
   | 
||
| 
           remove_feature('securerandom.rb') 
   | 
||
| 
           remove_feature('openssl.rb') 
   | 
||
| 
           Dir.mktmpdir do |dir| 
   | 
||
| 
             open(File.join(dir, 'openssl.rb'), 'w') { |f| 
   | 
||
| 
               f << 'raise LoadError' 
   | 
||
| 
             } 
   | 
||
| 
             $LOAD_PATH.unshift(dir) 
   | 
||
| 
             require 'securerandom' 
   | 
||
| 
             test_s_random_bytes 
   | 
||
| 
           end 
   | 
||
| 
         ensure 
   | 
||
| 
           $LOADED_FEATURES.replace(loaded_features) 
   | 
||
| 
           $LOAD_PATH.replace(load_path) 
   | 
||
| 
           Object.const_set(:OpenSSL, openssl) 
   | 
||
| 
         end 
   | 
||
| 
       end 
   | 
||
| 
       def test_s_hex 
   | 
||
| 
         assert_equal(16 * 2, @it.hex.size) 
   | 
||
| 
         33.times do |idx| 
   | 
||
| 
           assert_equal(idx * 2, @it.hex(idx).size) 
   | 
||
| 
           assert_equal(idx, @it.hex(idx).gsub(/(..)/) { [$1].pack('H*') }.size) 
   | 
||
| 
         end 
   | 
||
| 
       end 
   | 
||
| 
       def test_s_base64 
   | 
||
| 
         assert_equal(16, @it.base64.unpack('m*')[0].size) 
   | 
||
| 
         17.times do |idx| 
   | 
||
| 
           assert_equal(idx, @it.base64(idx).unpack('m*')[0].size) 
   | 
||
| 
         end 
   | 
||
| 
       end 
   | 
||
| 
     if false # not in 1.8.7 
   | 
||
| 
       def test_s_urlsafe_base64 
   | 
||
| 
         safe = /[\n+\/]/ 
   | 
||
| 
         65.times do |idx| 
   | 
||
| 
           assert_not_match(safe, @it.urlsafe_base64(idx)) 
   | 
||
| 
         end 
   | 
||
| 
         # base64 can include unsafe byte 
   | 
||
| 
         10001.times do |idx| 
   | 
||
| 
           return if safe =~ @it.base64(idx) 
   | 
||
| 
         end 
   | 
||
| 
         flunk 
   | 
||
| 
       end 
   | 
||
| 
     end 
   | 
||
| 
       def test_s_random_number_float 
   | 
||
| 
         101.times do 
   | 
||
| 
           v = @it.random_number 
   | 
||
| 
           assert(0.0 <= v && v < 1.0) 
   | 
||
| 
         end 
   | 
||
| 
       end 
   | 
||
| 
       def test_s_random_number_float_by_zero 
   | 
||
| 
         101.times do 
   | 
||
| 
           v = @it.random_number(0) 
   | 
||
| 
           assert(0.0 <= v && v < 1.0) 
   | 
||
| 
         end 
   | 
||
| 
       end 
   | 
||
| 
       def test_s_random_number_int 
   | 
||
| 
         101.times do |idx| 
   | 
||
| 
           next if idx.zero? 
   | 
||
| 
           v = @it.random_number(idx) 
   | 
||
| 
           assert(0 <= v && v < idx) 
   | 
||
| 
         end 
   | 
||
| 
       end 
   | 
||
| 
     if false # not in 1.8.7 
   | 
||
| 
       def test_uuid 
   | 
||
| 
         uuid = @it.uuid 
   | 
||
| 
         assert_equal(36, uuid.size) 
   | 
||
| 
         uuid.unpack('a8xa4xa4xa4xa12').each do |e| 
   | 
||
| 
           assert_match(/^[0-9a-f]+$/, e) 
   | 
||
| 
         end 
   | 
||
| 
       end 
   | 
||
| 
     end 
   | 
||
| 
       def protect 
   | 
||
| 
         begin 
   | 
||
| 
           yield 
   | 
||
| 
         rescue NotImplementedError 
   | 
||
| 
           # ignore 
   | 
||
| 
         end 
   | 
||
| 
       end 
   | 
||
| 
       def remove_feature(basename) 
   | 
||
| 
         $LOADED_FEATURES.delete_if { |path| 
   | 
||
| 
           if File.basename(path) == basename 
   | 
||
| 
             $LOAD_PATH.any? { |dir| 
   | 
||
| 
               File.exists?(File.join(dir, basename)) 
   | 
||
| 
             } 
   | 
||
| 
           end 
   | 
||
| 
         } 
   | 
||
| 
       end 
   | 
||
| 
     end 
   | 
||
- « Previous
 - 1
 - …
 - 4
 - 5
 - 6
 - Next »