strongbox 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.html ADDED
@@ -0,0 +1,88 @@
1
+ <h1>Strongbox</h1>
2
+ <p>Strongbox provides Public Key Encryption for ActiveRecord. By using a public key sensitive information can be encrypted and stored automatically. Once stored a password is required to access the information.</p>
3
+ <p>Because the largest amount of data that can practically be encrypted with a public key is 245 byte, by default Strongbox uses a two layer approach. First it encrypts the attribute using symmetric encryption with a randomly generated key and initialization vector (IV) (which can just be through to as a second key), then it encrypts those with the public key.</p>
4
+ <p>Strongbox stores the encrypted attribute in a database column by the same name, i.e. if you tell Strongbox to encrypt &#8220;secret&#8221; then it will be store in &#8220;secret&#8221; in the database, just as the unencrypted attribute would be. If symmetric encryption is used (the default) two additional columns &#8220;secret_key&#8221; and &#8220;secret_iv&#8221; are needed as well.</p>
5
+ <p>The attribute is automatically encrypted simply by setting it:</p>
6
+ user.secret = &#8220;Shhhhhhh&#8230;&#8221;
7
+ <p>and decrypted by calling the &#8220;decrypt&#8221; method with the private key password.</p>
8
+ plain_text = user.secret.decrypt &#8216;letmein&#8217;
9
+ <h2>Quick Start</h2>
10
+ <p>In your model:</p>
11
+ <pre><code>class User &lt; ActiveRecord::Base
12
+ encrypt_with_public_key :secret,
13
+ :key_pair =&gt; File.join(RAILS_ROOT,'config','keypair.pem')
14
+ end</code></pre>
15
+ <p>In your migrations:</p>
16
+ <pre><code>class AddSecretColumnsToUser &lt; ActiveRecord::Migration
17
+ def self.up
18
+ add_column :users, :secret, :binary
19
+ add_column :users, :secret_key, :binary
20
+ add_column :users, :secret_iv, :binary
21
+ end
22
+ def self.down
23
+ remove_column :users, :secret
24
+ remove_column :users, :secret_key
25
+ remove_column :users, :secret_iv
26
+ end
27
+ end</code></pre>
28
+ <p>Generate a key pair:</p>
29
+ <p>(Choose a strong password.)</p>
30
+ <pre><code>openssl genrsa -des3 -out config/private.pem 2048
31
+ openssl rsa -in config/private.pem -out config/public.pem -outform PEM -pubout
32
+ cat config/private.pem config/public.pem &gt;&gt; config/keypair.pem</code></pre>
33
+ <p>In your views and forms you don&#8217;t need to do anything special to encrypt data. To decrypt call:</p>
34
+ <pre><code>user.secret.decrypt 'password'</code></pre>
35
+ <h2>Gem installation (Rails 2.1+)</h2>
36
+ <p>In config/environment.rb:</p>
37
+ <pre><code>config.gem "strongbox"</code></pre>
38
+ <h2>Usage</h2>
39
+ <p><em>encrypt_with_public_key</em> sets up the attribute it&#8217;s called on for automatic encryption. It&#8217;s simplest form is:</p>
40
+ <pre><code>class User &lt; ActiveRecord::Base
41
+ encrypt_with_public_key :secret,
42
+ :key_pair =&gt; File.join(RAILS_ROOT,'config','keypair.pem')
43
+ end</code></pre>
44
+ <p>Which will encrypt the attribute &#8220;secret&#8221;. The attribute will be encrypted using symmetric encryption with an automatically generated key and IV encrypted using the public key. This requires three columns in the database &#8220;secret&#8221;, &#8220;secret_key&#8221;, and &#8220;secret_iv&#8221; (see below).</p>
45
+ <p>Options to encrypt_with_public_key are:</p>
46
+ <p>:public_key &#8211; Path to the public key file. Overrides :keypair.</p>
47
+ <p>:private_key &#8211; Path to the private key file. Overrides :keypair.</p>
48
+ <p>:keypair &#8211; Path to a file containing both the public and private keys.</p>
49
+ <p>:symmetric :always/:never &#8211; Encrypt the date using symmetric encryption. The public key is used to encrypt an automatically generated key and IV. This allows for large amounts of data to be encrypted. The size of data that can be encrypted directly with the public is limit to key size (in bytes) &#8211; 11. So a 2048 key can encrypt <strong>245 bytes</strong>. Defaults to <strong>:always</strong>.</p>
50
+ <p>:symmetric_cipher &#8211; Cipher to use for symmetric encryption. Defaults to <strong>&#8216;aes-256-cbc&#8217;</strong>. Other ciphers support by OpenSSL may be used.</p>
51
+ <p>:base64 true/false &#8211; Use Base64 encoding to convert encrypted data to text. Use when binary save data storage is not available. Defaults to <strong>false</strong>.</p>
52
+ <p>:padding &#8211; Method used to pad data encrypted with the public key. Defaults to <strong>RSA_PKCS1_PADDING</strong>. The default should be fine unless you are dealing with legacy data.</p>
53
+ <p>:ensure_required_columns &#8211; Make sure the required database columns exist. Defaults to <strong>true</strong>, set to false if you want to encrypt/decrypt data stored outside of the database.</p>
54
+ <p>For example, encrypting a small attribute, providing only the public key for extra security, and Base64 encoding the encrypted data:</p>
55
+ <pre><code>class User &lt; ActiveRecord::Base
56
+ validates_length_of :pin_code, :is =&gt; 4
57
+ encrypt_with_public_key :pin_code,
58
+ :symmetric =&gt; :never,
59
+ :base64 =&gt; true,
60
+ :public_key =&gt; File.join(RAILS_ROOT,'config','public.pem')
61
+ end</code></pre>
62
+ <h2>Key Generation</h2>
63
+ <p>Generate a key pair:</p>
64
+ <pre><code>openssl genrsa -des3 -out config/private.pem 2048
65
+ Generating RSA private key, 2048 bit long modulus
66
+ ......+++
67
+ .+++
68
+ e is 65537 (0x10001)
69
+ Enter pass phrase for config/private.pem:
70
+ Verifying - Enter pass phrase for config/private.pem:</code></pre>
71
+ <p>and extract the the public key:</p>
72
+ <pre><code>openssl rsa -in config/private.pem -out config/public.pem -outform PEM -pubout
73
+ Enter pass phrase for config/private.pem:
74
+ writing RSA key</code></pre>
75
+ <p>If you are going to leave the private key installed it&#8217;s easiest to create a single key pair file:</p>
76
+ <pre><code>cat config/private.pem config/public.pem &gt;&gt; config/keypair.pem</code></pre>
77
+ <p>Or, for added security, store the private key file else where, leaving only the public key.</p>
78
+ <h2>Table Creation</h2>
79
+ <p>In it&#8217;s default configuration Strongbox requires three columns, one the encrypted data, one for the encrypted symmetric key, and one for the encrypted symmetric IV. If symmetric encryption is disabled then only the columns for the data being encrypted is needed.</p>
80
+ <p>If your underlying database allows, use the <strong>binary</strong> column type. If you must store your data in text format be sure to enable Base64 encoding and to use the <strong>text</strong> column type. If you use a <em>string</em> column and encrypt anything greater than 186 bytes (245 bytes if you don&#8217;t enable Base64 encoding) <strong>your data will be lost</strong>.</p>
81
+ <h2>Security Caveats</h2>
82
+ <p>If you don&#8217;t encrypt your data, then an attacker only needs to steal that data to get your secrets.</p>
83
+ <p>If encrypt your data using symmetric encrypts and a stored key, then the attacker needs the data and the key stored on the server.</p>
84
+ <p>If you use public key encryption, the attacker needs the data, the private key, and the password. This means the attacker has to sniff the password somehow, so that&#8217;s what you need to protect against.</p>
85
+ <h2>Authors</h2>
86
+ <p>Spike Ilacqua</p>
87
+ <h2>Thanks</h2>
88
+ <p>Strongbox&#8217;s implementation drew inspiration from Thoughtbot&#8217;s Paperclip gem http://www.thoughtbot.com/projects/paperclip</p>
data/README.textile CHANGED
@@ -1,19 +1,10 @@
1
1
  h1. Strongbox
2
2
 
3
- Strongbox provides Public Key Encryption for ActiveRecord. By using a public key
4
- sensitive information can be encrypted and stored automatically. Once stored a
5
- password is required to access the information.
3
+ Strongbox provides Public Key Encryption for ActiveRecord. By using a public key sensitive information can be encrypted and stored automatically. Once stored a password is required to access the information.
6
4
 
7
- Because the largest amount of data that can practically be encrypted with a public
8
- key is 245 byte, by default Strongbox uses a two layer approach. First it encrypts
9
- the attribute using symmetric encryption with a randomly generated key and
10
- initialization vector (IV) (which can just be through to as a second key), then it
11
- encrypts those with the public key.
5
+ Because the largest amount of data that can practically be encrypted with a public key is 245 byte, by default Strongbox uses a two layer approach. First it encrypts the attribute using symmetric encryption with a randomly generated key and initialization vector (IV) (which can just be through to as a second key), then it encrypts those with the public key.
12
6
 
13
- Strongbox stores the encrypted attribute in a database column by the same name, i.e.
14
- if you tell Strongbox to encrypt "secret" then it will be store in "secret" in the
15
- database, just as the unencrypted attribute would be. If symmetric encryption is used
16
- (the default) two additional columns "secret_key" and "secret_iv" are needed as well.
7
+ Strongbox stores the encrypted attribute in a database column by the same name, i.e. if you tell Strongbox to encrypt "secret" then it will be store in "secret" in the database, just as the unencrypted attribute would be. If symmetric encryption is used (the default) two additional columns "secret_key" and "secret_iv" are needed as well.
17
8
 
18
9
  The attribute is automatically encrypted simply by setting it:
19
10
 
@@ -55,8 +46,7 @@ bc. openssl genrsa -des3 -out config/private.pem 2048
55
46
  openssl rsa -in config/private.pem -out config/public.pem -outform PEM -pubout
56
47
  cat config/private.pem config/public.pem >> config/keypair.pem
57
48
 
58
- In your views and forms you don't need to do anything special to encrypt data. To
59
- decrypt call:
49
+ In your views and forms you don't need to do anything special to encrypt data. To decrypt call:
60
50
 
61
51
  bc. user.secret.decrypt 'password'
62
52
 
@@ -68,18 +58,14 @@ bc. config.gem "strongbox"
68
58
 
69
59
  h2. Usage
70
60
 
71
- _encrypt_with_public_key_ sets up the attribute it's called on for automatic
72
- encryption. It's simplest form is:
61
+ _encrypt_with_public_key_ sets up the attribute it's called on for automatic encryption. It's simplest form is:
73
62
 
74
63
  bc. class User < ActiveRecord::Base
75
64
  encrypt_with_public_key :secret,
76
65
  :key_pair => File.join(RAILS_ROOT,'config','keypair.pem')
77
66
  end
78
67
 
79
- Which will encrypt the attribute "secret". The attribute will be encrypted using
80
- symmetric encryption with an automatically generated key and IV encrypted using the
81
- public key. This requires three columns in the database "secret", "secret_key", and
82
- "secret_iv" (see below).
68
+ Which will encrypt the attribute "secret". The attribute will be encrypted using symmetric encryption with an automatically generated key and IV encrypted using the public key. This requires three columns in the database "secret", "secret_key", and "secret_iv" (see below).
83
69
 
84
70
  Options to encrypt_with_public_key are:
85
71
 
@@ -89,22 +75,17 @@ Options to encrypt_with_public_key are:
89
75
 
90
76
  :keypair - Path to a file containing both the public and private keys.
91
77
 
92
- :symmetric :always/:never - Encrypt the date using symmetric encryption. The public
93
- key is used to encrypt an automatically generated key and IV. This allows for large
94
- amounts of data to be encrypted. The size of data that can be encrypted directly with
95
- the public is limit to key size (in bytes) - 11. So a 2048 key can encrypt *245 bytes*. Defaults to :always
78
+ :symmetric :always/:never - Encrypt the date using symmetric encryption. The public key is used to encrypt an automatically generated key and IV. This allows for large amounts of data to be encrypted. The size of data that can be encrypted directly with the public is limit to key size (in bytes) - 11. So a 2048 key can encrypt *245 bytes*. Defaults to *:always*.
96
79
 
97
80
  :symmetric_cipher - Cipher to use for symmetric encryption. Defaults to *'aes-256-cbc'*. Other ciphers support by OpenSSL may be used.
98
81
 
99
- :base64 true/false - Use Base64 encoding to convert encrypted data to text. Use when
100
- binary save data storage is not available. Defaults to *false*
82
+ :base64 true/false - Use Base64 encoding to convert encrypted data to text. Use when binary save data storage is not available. Defaults to *false*.
101
83
 
102
- :padding - Method used to pad data encrypted with the public key. Defaults to
103
- RSA_PKCS1_PADDING. The default should be fine unless you are dealing with legacy
104
- data.
84
+ :padding - Method used to pad data encrypted with the public key. Defaults to *RSA_PKCS1_PADDING*. The default should be fine unless you are dealing with legacy data.
105
85
 
106
- For example, encrypting a small attribute, providing only the public key for extra
107
- security, and Base64 encoding the encrypted data:
86
+ :ensure_required_columns - Make sure the required database column(s) exist. Defaults to *true*, set to false if you want to encrypt/decrypt data stored outside of the database.
87
+
88
+ For example, encrypting a small attribute, providing only the public key for extra security, and Base64 encoding the encrypted data:
108
89
 
109
90
  bc. class User < ActiveRecord::Base
110
91
  validates_length_of :pin_code, :is => 4
@@ -132,8 +113,7 @@ bc. openssl rsa -in config/private.pem -out config/public.pem -outform PEM -pubo
132
113
  Enter pass phrase for config/private.pem:
133
114
  writing RSA key
134
115
 
135
- If you are going to leave the private key installed it's easiest to create a single
136
- key pair file:
116
+ If you are going to leave the private key installed it's easiest to create a single key pair file:
137
117
 
138
118
  bc. cat config/private.pem config/public.pem >> config/keypair.pem
139
119
 
@@ -141,27 +121,18 @@ Or, for added security, store the private key file else where, leaving only the
141
121
 
142
122
  h2. Table Creation
143
123
 
144
- In it's default configuration Strongbox requires three columns, one the encrypted
145
- data, one for the encrypted symmetric key, and one for the encrypted symmetric IV. If
146
- symmetric encryption is disabled then only the columns for the data being encrypted
147
- is needed.
124
+ In it's default configuration Strongbox requires three columns, one the encrypted data, one for the encrypted symmetric key, and one for the encrypted symmetric IV. If symmetric encryption is disabled then only the columns for the data being encrypted is needed.
148
125
 
149
- If your underlying database allows, use the *binary* column type. If you must store
150
- your data in text format be sure to enable Base64 encoding and to use the *text*
151
- column type. If you use a _string_ column and encrypt anything greater than 186 bytes (245 bytes if you don't enable Base64 encoding) *your data will be lost*.
126
+ If your underlying database allows, use the *binary* column type. If you must store your data in text format be sure to enable Base64 encoding and to use the *text* column type. If you use a _string_ column and encrypt anything greater than 186 bytes (245 bytes if you don't enable Base64 encoding) *your data will be lost*.
152
127
 
153
128
 
154
129
  h2. Security Caveats
155
130
 
156
- If you don't encrypt your data, then an attacker only needs to steal that data to get
157
- your secrets.
131
+ If you don't encrypt your data, then an attacker only needs to steal that data to get your secrets.
158
132
 
159
- If encrypt your data using symmetric encrypts and a stored key, then the attacker
160
- needs the data and the key stored on the server.
133
+ If encrypt your data using symmetric encrypts and a stored key, then the attacker needs the data and the key stored on the server.
161
134
 
162
- If you use public key encryption, the attacker needs the data, the private key, and
163
- the password. This means the attacker has to sniff the password somehow, so that's
164
- what you need to protect against.
135
+ If you use public key encryption, the attacker needs the data, the private key, and the password. This means the attacker has to sniff the password somehow, so that's what you need to protect against.
165
136
 
166
137
  h2. Authors
167
138
 
@@ -169,6 +140,5 @@ Spike Ilacqua
169
140
 
170
141
  h2. Thanks
171
142
 
172
- Strongbox's implementation drew inspiration from Thoughtbot's Paperclip gem
173
- http://www.thoughtbot.com/projects/paperclip
143
+ Strongbox's implementation drew inspiration from Thoughtbot's Paperclip gem http://www.thoughtbot.com/projects/paperclip
174
144
 
data/lib/strongbox.rb CHANGED
@@ -5,13 +5,13 @@ require 'strongbox/lock'
5
5
 
6
6
  module Strongbox
7
7
 
8
- VERSION = "0.4.1"
8
+ VERSION = "0.4.2"
9
9
 
10
10
  RSA_PKCS1_PADDING = OpenSSL::PKey::RSA::PKCS1_PADDING
11
11
  RSA_SSLV23_PADDING = OpenSSL::PKey::RSA::SSLV23_PADDING
12
12
  RSA_NO_PADDING = OpenSSL::PKey::RSA::NO_PADDING
13
13
  RSA_PKCS1_OAEP_PADDING = OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING
14
-
14
+
15
15
  class << self
16
16
  # Provides for setting the default options for Strongbox
17
17
  def options
@@ -19,10 +19,11 @@ module Strongbox
19
19
  :base64 => false,
20
20
  :symmetric => :always,
21
21
  :padding => RSA_PKCS1_PADDING,
22
- :symmetric_cipher => 'aes-256-cbc'
22
+ :symmetric_cipher => 'aes-256-cbc',
23
+ :ensure_required_columns => true
23
24
  }
24
25
  end
25
-
26
+
26
27
  def included base #:nodoc:
27
28
  base.extend ClassMethods
28
29
  end
@@ -30,7 +31,7 @@ module Strongbox
30
31
 
31
32
  class StrongboxError < StandardError #:nodoc:
32
33
  end
33
-
34
+
34
35
  module ClassMethods
35
36
  # +encrypt_with_public_key+ gives the class it is called on an attribute that
36
37
  # when assigned is automatically encrypted using a public key. This allows the
@@ -49,18 +50,18 @@ module Strongbox
49
50
 
50
51
 
51
52
  lock_options[name] = options.symbolize_keys.reverse_merge Strongbox.options
52
-
53
+
53
54
  define_method name do
54
55
  lock_for(name)
55
56
  end
56
-
57
+
57
58
  define_method "#{name}=" do | plaintext |
58
59
  lock_for(name).encrypt plaintext
59
60
  end
60
-
61
+
61
62
  end
62
63
  end
63
-
64
+
64
65
  module InstanceMethods
65
66
  def lock_for name
66
67
  @_locks ||= {}
@@ -1,17 +1,17 @@
1
1
  module Strongbox
2
- # The Lock class encrypts and decrypts the protected attribute. It
2
+ # The Lock class encrypts and decrypts the protected attribute. It
3
3
  # automatically encrypts the data when set and decrypts it when the private
4
4
  # key password is provided.
5
5
  class Lock
6
-
6
+
7
7
  def initialize name, instance, options = {}
8
8
  @name = name
9
9
  @instance = instance
10
-
10
+
11
11
  @size = nil
12
-
12
+
13
13
  options = Strongbox.options.merge(options)
14
-
14
+
15
15
  @base64 = options[:base64]
16
16
  @public_key = options[:public_key] || options[:key_pair]
17
17
  @private_key = options[:private_key] || options[:key_pair]
@@ -20,10 +20,11 @@ module Strongbox
20
20
  @symmetric_cipher = options[:symmetric_cipher]
21
21
  @symmetric_key = options[:symmetric_key] || "#{name}_key"
22
22
  @symmetric_iv = options[:symmetric_iv] || "#{name}_iv"
23
+ @ensure_required_columns = options[:ensure_required_columns]
23
24
  end
24
-
25
+
25
26
  def encrypt plaintext
26
- ensure_required_columns
27
+ ensure_required_columns if @ensure_required_columns
27
28
  unless @public_key
28
29
  raise StrongboxError.new("#{@instance.class} model does not have public key_file")
29
30
  end
@@ -55,22 +56,22 @@ module Strongbox
55
56
  @instance[@name] = ciphertext
56
57
  end
57
58
  end
58
-
59
+
59
60
  # Given the private key password decrypts the attribute. Will raise
60
61
  # OpenSSL::PKey::RSAError if the password is wrong.
61
-
62
- def decrypt password = nil
62
+
63
+ def decrypt password = nil, ciphertext = nil
63
64
  # Given a private key and a nil password OpenSSL::PKey::RSA.new() will
64
65
  # *prompt* for a password, we default to an empty string to avoid that.
65
- ciphertext = @instance[@name]
66
+ ciphertext ||= @instance[@name]
66
67
  return nil if ciphertext.nil?
67
68
  return "" if ciphertext.empty?
68
-
69
+
69
70
  return "*encrypted*" if password.nil?
70
71
  unless @private_key
71
72
  raise StrongboxError.new("#{@instance.class} model does not have private key_file")
72
73
  end
73
-
74
+
74
75
  if ciphertext
75
76
  ciphertext = Base64.decode64(ciphertext) if @base64
76
77
  private_key = get_rsa_key(@private_key,password)
@@ -94,20 +95,20 @@ module Strongbox
94
95
  nil
95
96
  end
96
97
  end
97
-
98
+
98
99
  def to_s
99
100
  decrypt
100
101
  end
101
-
102
+
102
103
  # Needed for validations
103
104
  def blank?
104
105
  @instance[@name].blank?
105
106
  end
106
-
107
+
107
108
  def nil?
108
109
  @instance[@name].nil?
109
110
  end
110
-
111
+
111
112
  def size
112
113
  @size
113
114
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: strongbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Spike Ilacqua
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-10-09 00:00:00 -06:00
12
+ date: 2011-01-17 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -53,6 +53,7 @@ extra_rdoc_files: []
53
53
  files:
54
54
  - LICENSE
55
55
  - Rakefile
56
+ - README.html
56
57
  - README.textile
57
58
  - init.rb
58
59
  - lib/strongbox/lock.rb