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