Module: SecureRandom

### Home Classes Methods

### In Files

- lib/compat/securerandom.rb

### Methods

- ::base64
- ::hex
- ::random_bytes
- ::random_number

### Class/Module Index

Quicksearch

- UUIDTools
- UUIDTools::UUID
- SecureRandom

No matching classes.

# SecureRandom

### Public Class Methods

base64(n=nil) click to toggle source

SecureRandom.base64 generates a random base64 string.

The argument n specifies the length of the random length. The length of the result string is about 4/3 of n.

If n is not specified, 16 is assumed. It may be larger in future.

If secure random number generator is not available, NotImplementedError is raised.

    # File lib/compat/securerandom.rb, line 145
    def self.base64(n=nil)
      [random_bytes(n)].pack("m*").delete("\n")
    end

hex(n=nil) click to toggle source

SecureRandom.hex generates a random hex string.

The argument n specifies the length of the random length. The length of the result string is twice of n.

If n is not specified, 16 is assumed. It may be larger in future.

If secure random number generator is not available, NotImplementedError is raised.

    # File lib/compat/securerandom.rb, line 131
    def self.hex(n=nil)
      random_bytes(n).unpack("H*")[0]
    end

random_bytes(n=nil) click to toggle source

SecureRandom.random_bytes generates a random binary string.

The argument n specifies the length of the result string.

If n is not specified, 16 is assumed. It may be larger in future.

If secure random number generator is not available, NotImplementedError is raised.

    # File lib/compat/securerandom.rb, line 52
    def self.random_bytes(n=nil)
      n ||= 16

      if defined? OpenSSL::Random
        return OpenSSL::Random.random_bytes(n)
      end

      if !defined?(@has_urandom) || @has_urandom
        flags = File::RDONLY
        flags |= File::NONBLOCK if defined? File::NONBLOCK
        flags |= File::NOCTTY if defined? File::NOCTTY
        flags |= File::NOFOLLOW if defined? File::NOFOLLOW
        begin
          File.open("/dev/urandom", flags) {|f|
            unless f.stat.chardev?
              raise Errno::ENOENT
            end
            @has_urandom = true
            ret = f.readpartial(n)
            if ret.length != n
              raise NotImplementedError,
                "Unexpected partial read from random device"
            end
            return ret
          }
        rescue Errno::ENOENT
          @has_urandom = false
        end
      end

      if !defined?(@has_win32)
        begin
          require 'Win32API'

          crypt_acquire_context = Win32API.new(
            "advapi32", "CryptAcquireContext", 'PPPII', 'L'
          )
          @crypt_gen_random = Win32API.new(
            "advapi32", "CryptGenRandom", 'LIP', 'L'
          )

          hProvStr = " " * 4
          prov_rsa_full = 1
          crypt_verifycontext = 0xF0000000

          if crypt_acquire_context.call(
              hProvStr, nil, nil, prov_rsa_full, crypt_verifycontext) == 0
            raise SystemCallError,
              "CryptAcquireContext failed: #{lastWin32ErrorMessage}"
          end
          @hProv, = hProvStr.unpack('L')

          @has_win32 = true
        rescue LoadError
          @has_win32 = false
        end
      end
      if @has_win32
        bytes = " " * n
        if @crypt_gen_random.call(@hProv, bytes.size, bytes) == 0
          raise SystemCallError,
            "CryptGenRandom failed: #{lastWin32ErrorMessage}"
        end
        return bytes
      end

      raise NotImplementedError, "No random device"
    end

random_number(n=0) click to toggle source

SecureRandom.random_number generates a random number.

If an positive integer is given as n, SecureRandom.random_number returns an integer: 0 <= SecureRandom.random_number(n) < n.

If 0 is given or an argument is not given, SecureRandom.random_number returns an float: 0.0 <= SecureRandom.random_number() < 1.0.

    # File lib/compat/securerandom.rb, line 158
    def self.random_number(n=0)
      if 0 < n
        hex = n.to_s(16)
        hex = '0' + hex if (hex.length & 1) == 1
        bin = [hex].pack("H*")
        first = bin[0..0]
        mask = first.respond_to?(:ord) ? first.ord : first.sum(8)
        mask |= mask >> 1
        mask |= mask >> 2
        mask |= mask >> 4
        begin
          rnd = SecureRandom.random_bytes(bin.length)
          first = rnd[0..0]
          ordinal = first.respond_to?(:ord) ? first.ord : first.sum(8)
          rnd[0..0] = (ordinal & mask).chr
        end until rnd < bin
        rnd.unpack("H*")[0].hex
      else
        # assumption: Float::MANT_DIG <= 64
        i64 = SecureRandom.random_bytes(8).unpack("Q")[0]
        Math.ldexp(i64 >> (64-Float::MANT_DIG), -Float::MANT_DIG)
      end
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.