Class | Rails::SecretKeyGenerator |
In: |
vendor/rails/railties/lib/rails_generator/secret_key_generator.rb
|
Parent: | Object |
A class for creating random secret keys. This class will do its best to create a random secret key that‘s as secure as possible, using whatever methods are available on the current platform. For example:
generator = Rails::SecretKeyGenerator("some unique identifier, such as the application name") generator.generate_secret # => "f3f1be90053fa851... (some long string)"
GENERATORS | = | [ :secure_random, :win32_api, :urandom, :openssl, :prng ].freeze |
# File vendor/rails/railties/lib/rails_generator/secret_key_generator.rb, line 11 11: def initialize(identifier) 12: @identifier = identifier 13: end
Generate a random secret key with the best possible method available on the current platform.
# File vendor/rails/railties/lib/rails_generator/secret_key_generator.rb, line 17 17: def generate_secret 18: generator = GENERATORS.find do |g| 19: self.class.send("supports_#{g}?") 20: end 21: send("generate_secret_with_#{generator}") 22: end
Generate a random secret key with OpenSSL. If OpenSSL is not already loaded, then this method will attempt to load it. LoadError will be raised if that fails.
# File vendor/rails/railties/lib/rails_generator/secret_key_generator.rb, line 67 67: def generate_secret_with_openssl 68: require 'openssl' 69: if !File.exist?("/dev/urandom") 70: # OpenSSL transparently seeds the random number generator with 71: # data from /dev/urandom. On platforms where that is not 72: # available, such as Windows, we have to provide OpenSSL with 73: # our own seed. Unfortunately there's no way to provide a 74: # secure seed without OS support, so we'll have to do with 75: # rand() and Time.now.usec(). 76: OpenSSL::Random.seed(rand(0).to_s + Time.now.usec.to_s) 77: end 78: data = OpenSSL::BN.rand(2048, -1, false).to_s 79: 80: if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00908000 81: OpenSSL::Digest::SHA512.new(data).hexdigest 82: else 83: generate_secret_with_prng 84: end 85: end
Generate a random secret key with Ruby‘s pseudo random number generator, as well as some environment information.
This is the least cryptographically secure way to generate a secret key, and should be avoided whenever possible.
# File vendor/rails/railties/lib/rails_generator/secret_key_generator.rb, line 98 98: def generate_secret_with_prng 99: require 'digest/sha2' 100: sha = Digest::SHA2.new(512) 101: now = Time.now 102: sha << now.to_s 103: sha << String(now.usec) 104: sha << String(rand(0)) 105: sha << String($$) 106: sha << @identifier 107: return sha.hexdigest 108: end
Generate a random secret key with Ruby 1.9‘s SecureRandom module. Raises LoadError if the current Ruby version does not support SecureRandom.
# File vendor/rails/railties/lib/rails_generator/secret_key_generator.rb, line 59 59: def generate_secret_with_secure_random 60: require 'securerandom' 61: return SecureRandom.hex(64) 62: end
Generate a random secret key with /dev/urandom. Raises SystemCallError on failure.
# File vendor/rails/railties/lib/rails_generator/secret_key_generator.rb, line 89 89: def generate_secret_with_urandom 90: return File.read("/dev/urandom", 64).unpack("H*")[0] 91: end
Generate a random secret key by using the Win32 API. Raises LoadError if the current platform cannot make use of the Win32 API. Raises SystemCallError if some other error occured.
# File vendor/rails/railties/lib/rails_generator/secret_key_generator.rb, line 27 27: def generate_secret_with_win32_api 28: # Following code is based on David Garamond's GUID library for Ruby. 29: require 'Win32API' 30: 31: crypt_acquire_context = Win32API.new("advapi32", "CryptAcquireContext", 32: 'PPPII', 'L') 33: crypt_gen_random = Win32API.new("advapi32", "CryptGenRandom", 34: 'LIP', 'L') 35: crypt_release_context = Win32API.new("advapi32", "CryptReleaseContext", 36: 'LI', 'L') 37: prov_rsa_full = 1 38: crypt_verifycontext = 0xF0000000 39: 40: hProvStr = " " * 4 41: if crypt_acquire_context.call(hProvStr, nil, nil, prov_rsa_full, 42: crypt_verifycontext) == 0 43: raise SystemCallError, "CryptAcquireContext failed: #{lastWin32ErrorMessage}" 44: end 45: hProv, = hProvStr.unpack('L') 46: bytes = " " * 64 47: if crypt_gen_random.call(hProv, bytes.size, bytes) == 0 48: raise SystemCallError, "CryptGenRandom failed: #{lastWin32ErrorMessage}" 49: end 50: if crypt_release_context.call(hProv, 0) == 0 51: raise SystemCallError, "CryptReleaseContext failed: #{lastWin32ErrorMessage}" 52: end 53: bytes.unpack("H*")[0] 54: end