0
@@ -5,160 +5,17 @@ module Rails
0
# generator = Rails::SecretKeyGenerator("some unique identifier, such as the application name")
0
# generator.generate_secret # => "f3f1be90053fa851... (some long string)"
0
+ # This class is *deprecated* in Rails 2.2 in favor of ActiveSupport::SecureRandom.
0
+ # It is currently a wrapper around ActiveSupport::SecureRandom.
0
class SecretKeyGenerator
0
- GENERATORS = [ :secure_random, :win32_api, :urandom, :openssl, :prng ].freeze
0
def initialize(identifier)
0
- @identifier = identifier
0
# Generate a random secret key with the best possible method available on
0
# the current platform.
0
- generator = GENERATORS.find do |g|
0
- self.class.send("supports_#{g}?")
0
- send("generate_secret_with_#{generator}")
0
- # Generate a random secret key by using the Win32 API. Raises LoadError
0
- # if the current platform cannot make use of the Win32 API. Raises
0
- # SystemCallError if some other error occurred.
0
- def generate_secret_with_win32_api
0
- # Following code is based on David Garamond's GUID library for Ruby.
0
- crypt_acquire_context = Win32API.new("advapi32", "CryptAcquireContext",
0
- crypt_gen_random = Win32API.new("advapi32", "CryptGenRandom",
0
- crypt_release_context = Win32API.new("advapi32", "CryptReleaseContext",
0
- crypt_verifycontext = 0xF0000000
0
- if crypt_acquire_context.call(hProvStr, nil, nil, prov_rsa_full,
0
- crypt_verifycontext) == 0
0
- raise SystemCallError, "CryptAcquireContext failed: #{lastWin32ErrorMessage}"
0
- hProv, = hProvStr.unpack('L')
0
- if crypt_gen_random.call(hProv, bytes.size, bytes) == 0
0
- raise SystemCallError, "CryptGenRandom failed: #{lastWin32ErrorMessage}"
0
- if crypt_release_context.call(hProv, 0) == 0
0
- raise SystemCallError, "CryptReleaseContext failed: #{lastWin32ErrorMessage}"
0
- # Generate a random secret key with Ruby 1.9's SecureRandom module.
0
- # Raises LoadError if the current Ruby version does not support
0
- def generate_secret_with_secure_random
0
- require 'securerandom'
0
- return SecureRandom.hex(64)
0
- # Generate a random secret key with OpenSSL. If OpenSSL is not
0
- # already loaded, then this method will attempt to load it.
0
- # LoadError will be raised if that fails.
0
- def generate_secret_with_openssl
0
- if !File.exist?("/dev/urandom")
0
- # OpenSSL transparently seeds the random number generator with
0
- # data from /dev/urandom. On platforms where that is not
0
- # available, such as Windows, we have to provide OpenSSL with
0
- # our own seed. Unfortunately there's no way to provide a
0
- # secure seed without OS support, so we'll have to do with
0
- # rand() and Time.now.usec().
0
- OpenSSL::Random.seed(rand(0).to_s + Time.now.usec.to_s)
0
- data = OpenSSL::BN.rand(2048, -1, false).to_s
0
- if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00908000
0
- OpenSSL::Digest::SHA512.new(data).hexdigest
0
- generate_secret_with_prng
0
+ ActiveSupport::SecureRandom.hex(64)
0
- # Generate a random secret key with /dev/urandom.
0
- # Raises SystemCallError on failure.
0
- def generate_secret_with_urandom
0
- return File.read("/dev/urandom", 64).unpack("H*")[0]
0
- # Generate a random secret key with Ruby's pseudo random number generator,
0
- # as well as some environment information.
0
- # This is the least cryptographically secure way to generate a secret key,
0
- # and should be avoided whenever possible.
0
- def generate_secret_with_prng
0
- sha = Digest::SHA2.new(512)
0
- sha << String(now.usec)
0
- sha << String(rand(0))
0
- def lastWin32ErrorMessage
0
- # Following code is based on David Garamond's GUID library for Ruby.
0
- get_last_error = Win32API.new("kernel32", "GetLastError", '', 'L')
0
- format_message = Win32API.new("kernel32", "FormatMessageA",
0
- 'LPLLPLPPPPPPPP', 'L')
0
- format_message_ignore_inserts = 0x00000200
0
- format_message_from_system = 0x00001000
0
- code = get_last_error.call
0
- len = format_message.call(format_message_ignore_inserts +
0
- format_message_from_system, 0,
0
- code, 0, msg, 1024, nil, nil,
0
- nil, nil, nil, nil, nil, nil)
0
- msg[0, len].tr("\r", '').chomp
0
- def self.supports_secure_random?
0
- require 'securerandom'
0
- def self.supports_win32_api?
0
- return false unless RUBY_PLATFORM =~ /(:?mswin|mingw)/
0
- def self.supports_urandom?
0
- File.exist?('/dev/urandom')
0
- def self.supports_openssl?
0
- def self.supports_prng?