Skip to content
This repository
Browse code

Merge pull request #6952 from NZKoz/key_generator

Add ActiveSupport::KeyGenerator as a simple wrapper around PBKDF2
  • Loading branch information...
commit 0a507925cfc54246dc7d329936f60f8f410c38b6 2 parents df08271 + 0479bff
Michael Koziarski authored October 02, 2012
1  activesupport/lib/active_support.rb
@@ -48,6 +48,7 @@ module ActiveSupport
48 48
     autoload :Gzip
49 49
     autoload :Inflector
50 50
     autoload :JSON
  51
+    autoload :KeyGenerator
51 52
     autoload :MessageEncryptor
52 53
     autoload :MessageVerifier
53 54
     autoload :Multibyte
23  activesupport/lib/active_support/key_generator.rb
... ...
@@ -0,0 +1,23 @@
  1
+require 'openssl'
  2
+
  3
+module ActiveSupport
  4
+  # KeyGenerator is a simple wrapper around OpenSSL's implementation of PBKDF2
  5
+  # It can be used to derive a number of keys for various purposes from a given secret.
  6
+  # This lets rails applications have a single secure secret, but avoid reusing that
  7
+  # key in multiple incompatible contexts.
  8
+  class KeyGenerator
  9
+    def initialize(secret, options = {})
  10
+      @secret = secret
  11
+      # The default iterations are higher than required for our key derivation uses
  12
+      # on the off chance someone uses this for password storage
  13
+      @iterations = options[:iterations] || 2**16
  14
+    end
  15
+
  16
+    # Returns a derived key suitable for use.  The default key_size is chosen
  17
+    # to be compatible with the default settings of ActiveSupport::MessageVerifier.
  18
+    # i.e. OpenSSL::Digest::SHA1#block_length
  19
+    def generate_key(salt, key_size=64)
  20
+      OpenSSL::PKCS5.pbkdf2_hmac_sha1(@secret, salt, @iterations, key_size)
  21
+    end
  22
+  end
  23
+end
32  activesupport/test/key_generator_test.rb
... ...
@@ -0,0 +1,32 @@
  1
+require 'abstract_unit'
  2
+
  3
+begin
  4
+  require 'openssl'
  5
+  OpenSSL::PKCS5
  6
+rescue LoadError, NameError
  7
+  $stderr.puts "Skipping KeyGenerator test: broken OpenSSL install"
  8
+else
  9
+
  10
+require 'active_support/time'
  11
+require 'active_support/json'
  12
+
  13
+class KeyGeneratorTest < ActiveSupport::TestCase
  14
+  def setup
  15
+    @secret    = SecureRandom.hex(64)
  16
+    @generator = ActiveSupport::KeyGenerator.new(@secret, :iterations=>2)
  17
+  end
  18
+
  19
+  test "Generating a key of the default length" do
  20
+    derived_key = @generator.generate_key("some_salt")
  21
+    assert_kind_of String, derived_key
  22
+    assert_equal OpenSSL::Digest::SHA1.new.block_length, derived_key.length, "Should have generated a key of the default size"
  23
+  end
  24
+
  25
+  test "Generating a key of an alternative length" do
  26
+    derived_key = @generator.generate_key("some_salt", 32)
  27
+    assert_kind_of String, derived_key
  28
+    assert_equal 32, derived_key.length, "Should have generated a key of the right size"
  29
+  end
  30
+end
  31
+
  32
+end
11  railties/lib/rails/application.rb
@@ -101,6 +101,14 @@ def reload_routes!
101 101
       routes_reloader.reload!
102 102
     end
103 103
 
  104
+
  105
+    # Return the application's KeyGenerator
  106
+    def key_generator
  107
+      # number of iterations selected based on consultation with the google security
  108
+      # team. Details at https://github.com/rails/rails/pull/6952#issuecomment-7661220
  109
+      @key_generator ||= ActiveSupport::KeyGenerator.new(config.secret_token, :iterations=>1000)
  110
+    end
  111
+
104 112
     # Stores some of the Rails initial environment parameters which
105 113
     # will be used by middlewares and engines to configure themselves.
106 114
     # Currently stores:
@@ -121,7 +129,8 @@ def env_config
121 129
         "action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions,
122 130
         "action_dispatch.show_detailed_exceptions" => config.consider_all_requests_local,
123 131
         "action_dispatch.logger" => Rails.logger,
124  
-        "action_dispatch.backtrace_cleaner" => Rails.backtrace_cleaner
  132
+        "action_dispatch.backtrace_cleaner" => Rails.backtrace_cleaner,
  133
+        "action_dispatch.key_generator" => key_generator
125 134
       })
126 135
     end
127 136
 
1  railties/test/application/configuration_test.rb
@@ -634,6 +634,7 @@ def index
634 634
       assert_equal      app.env_config['action_dispatch.show_exceptions'],   app.config.action_dispatch.show_exceptions
635 635
       assert_equal      app.env_config['action_dispatch.logger'],            Rails.logger
636 636
       assert_equal      app.env_config['action_dispatch.backtrace_cleaner'], Rails.backtrace_cleaner
  637
+      assert_equal      app.env_config['action_dispatch.key_generator'],     Rails.application.key_generator
637 638
     end
638 639
 
639 640
     test "config.colorize_logging default is true" do

0 notes on commit 0a50792

Please sign in to comment.
Something went wrong with that request. Please try again.