symmetric-encryption 0.7.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -138,97 +138,34 @@ specified environment
138
138
  Note: Passwords must be encrypted in the environment in which they will be used.
139
139
  Since each environment should have its own symmetric encryption keys
140
140
 
141
- ## Install
141
+ ## Installation
142
142
 
143
- gem install symmetric-encryption
144
-
145
- ## Configuration
146
-
147
- ### Generating the RSA Private key
143
+ ### Add to an existing Rails project
144
+ Add the following line to Gemfile
148
145
 
149
- To protect the files holding the Symmetric Encryption keys, symmetric-encryption uses 2048 bit RSA
150
- encryption.
146
+ gem 'symmetric-encryption'
151
147
 
152
- Generate the RSA Private key as follows
148
+ Install the Gem with bundler
153
149
 
154
- openssl genrsa 2048
150
+ bundle install
155
151
 
156
- Paste the output into the configuration created below
152
+ ## Rails Configuration
157
153
 
158
154
  ### Creating the configuration file
159
155
 
160
- Create a configuration file in config/symmetric-encryption.yml per the following example:
156
+ The configuration file contains the path to the production encryption key files.
157
+ Generally in development and test the files are not created, so supply the full path
158
+ to these files in production. Once the config file has been generated it can be
159
+ modified as needed.
161
160
 
162
- #
163
- # Symmetric Encryption for Ruby
164
- #
165
- ---
166
- # For the development and test environments the test symmetric encryption keys
167
- # can be placed directly in the source code.
168
- # And therefore no RSA private key is required
169
- development: &development_defaults
170
- key: 1234567890ABCDEF1234567890ABCDEF
171
- iv: 1234567890ABCDEF
172
- cipher: aes-128-cbc
161
+ Generate the configuration file:
173
162
 
174
- test:
175
- <<: *development_defaults
163
+ rails generate symmetric_encryption:config /etc/rails/keys
176
164
 
177
- production:
178
- # Since the key to encrypt and decrypt with must NOT be stored along with the
179
- # source code, we only hold a RSA key that is used to unlock the file
180
- # containing the actual symmetric encryption key
181
- #
182
- # Sample RSA Key, DO NOT use this RSA key, generate a new one using
183
- # openssl genrsa 2048
184
- private_rsa_key: |
185
- -----BEGIN RSA PRIVATE KEY-----
186
- MIIEpAIBAAKCAQEAxIL9H/jYUGpA38v6PowRSRJEo3aNVXULNM/QNRpx2DTf++KH
187
- 6DcuFTFcNSSSxG9n4y7tKi755be8N0uwCCuOzvXqfWmXYjbLwK3Ib2vm0btpHyvA
188
- qxgqeJOOCxKdW/cUFLWn0tACUcEjVCNfWEGaFyvkOUuR7Ub9KfhbW9cZO3BxZMUf
189
- IPGlHl/gWyf484sXygd+S7cpDTRRzo9RjG74DwfE0MFGf9a1fTkxnSgeOJ6asTOy
190
- fp9tEToUlbglKaYGpOGHYQ9TV5ZsyJ9jRUyb4SP5wK2eK6dHTxTcHvT03kD90Hv4
191
- WeKIXv3WOjkwNEyMdpnJJfSDb5oquQvCNi7ZSQIDAQABAoIBAQCbzR7TUoBugU+e
192
- ICLvpC2wOYOh9kRoFLwlyv3QnH7WZFWRZzFJszYeJ1xr5etXQtyjCnmOkGAg+WOI
193
- k8GlOKOpAuA/PpB/leJFiYL4lBwU/PmDdTT0cdx6bMKZlNCeMW8CXGQKiFDOcMqJ
194
- 0uGtH5YD+RChPIEeFsJxnC8SyZ9/t2ra7XnMGiCZvRXIUDSEIIsRx/mOymJ7bL+h
195
- Lbp46IfXf6ZuIzwzoIk0JReV/r+wdmkAVDkrrMkCmVS4/X1wN/Tiik9/yvbsh/CL
196
- ztC55eSIEjATkWxnXfPASZN6oUfQPEveGH3HzNjdncjH/Ho8FaNMIAfFpBhhLPi9
197
- nG5sbH+BAoGBAOdoUyVoAA/QUa3/FkQaa7Ajjehe5MR5k6VtaGtcxrLiBjrNR7x+
198
- nqlZlGvWDMiCz49dgj+G1Qk1bbYrZLRX/Hjeqy5dZOGLMfgf9eKUmS1rDwAzBMcj
199
- M9jnnJEBx8HIlNzaR6wzp3GMd0rrccs660A8URvzkgo9qNbvMLq9vyUtAoGBANll
200
- SY1Iv9uaIz8klTXU9YzYtsfUmgXzw7K8StPdbEbo8F1J3JPJB4D7QHF0ObIaSWuf
201
- suZqLsvWlYGuJeyX2ntlBN82ORfvUdOrdrbDlmPyj4PfFVl0AK3U3Ai374DNrjKR
202
- hF6YFm4TLDaJhUjeV5C43kbE1N2FAMS9LYtPJ44NAoGAFDGHZ/E+aCLerddfwwun
203
- MBS6MnftcLPHTZ1RimTrNfsBXipBw1ItWEvn5s0kCm9X24PmdNK4TnhqHYaF4DL5
204
- ZjbQK1idEA2Mi8GGPIKJJ2x7P6I0HYiV4qy7fe/w1ZlCXE90B7PuPbtrQY9wO7Ll
205
- ipJ45X6I1PnyfOcckn8yafUCgYACtPAlgjJhWZn2v03cTbqA9nHQKyV/zXkyUIXd
206
- /XPLrjrP7ouAi5A8WuSChR/yx8ECRgrEM65Be3qBEtoGCB4AS1G0NcigM6qhKBFi
207
- VS0aMXr3+V8argcUIwJaWW/x+p2go48yXlJpLHPweeXe8mXEt4iM+QZte6p2yKQ4
208
- h9PGQQKBgQCqSydmXBnXGIVTp2sH/2GnpxLYnDBpcJE0tM8bJ42HEQQgRThIChsn
209
- PnGA91G9MVikYapgI0VYBHQOTsz8rTIUzsKwXG+TIaK+W84nxH5y6jUkjqwxZmAz
210
- r1URaMAun2PfAB4g2N/kEZTExgeOGqXjFhvvjdzl97ux2cTyZhaTXg==
211
- -----END RSA PRIVATE KEY-----
165
+ Note: Ignore the warning about "Symmetric Encryption config not found" since it is
166
+ being generated
212
167
 
213
- # List Symmetric Key files in the order of current / latest first
214
- ciphers:
215
- -
216
- # Filename containing Symmetric Encryption Key encrypted using the
217
- # RSA public key derived from the private key above
218
- key_filename: /etc/rails/.rails.key
219
- iv_filename: /etc/rails/.rails.iv
220
-
221
- # Encryption cipher
222
- # Recommended values:
223
- # aes-256-cbc
224
- # 256 AES CBC Algorithm. Very strong
225
- # Ruby 1.8.7 MRI Approximately 100,000 encryptions or decryptions per second
226
- # JRuby 1.6.7 with Ruby 1.8.7 Approximately 22,000 encryptions or decryptions per second
227
- # aes-128-cbc
228
- # 128 AES CBC Algorithm. Less strong.
229
- # Ruby 1.8.7 MRI Approximately 100,000 encryptions or decryptions per second
230
- # JRuby 1.6.7 with Ruby 1.8.7 Approximately 22,000 encryptions or decryptions per second
231
- cipher: aes-256-cbc
168
+ #### Save to version control
232
169
 
233
170
  This configuration file should be checked into the source code control system.
234
171
  It does Not include the Symmetric Encryption keys. They will be generated in the
@@ -236,22 +173,44 @@ next step.
236
173
 
237
174
  ### Generating and securing the Symmetric Encryption keys
238
175
 
176
+ Once development and testing is complete we need to generate secure encryption
177
+ key files for production. It is recommended that the step below be run on only
178
+ one of the production servers. The generated key files must then be copied to
179
+ all the production web servers.
180
+
181
+ Note: Do not run this step more than once, otherwise new keys will be generated
182
+ and any encrypted data will no longer be accessible.
183
+
184
+ Note: Do not run this step on more than one server in each environment otherwise
185
+ each server will be encrypting with it's own key and the servers will not be able
186
+ to decrypt data encrypted on another server. Just copy the generated files to each
187
+ server
188
+
239
189
  The symmetric encryption key consists of the key itself and an optional
240
190
  initialization vector.
241
191
 
242
- To generate the keys run the following Rake task in each environment:
192
+ To generate the keys run the following Rake task once only in each environment:
243
193
 
244
- RAILS_ENV=production rake symmetric_encryption:generate_symmetric_keys
194
+ rails generate symmetric_encryption:new_keys production
245
195
 
246
196
  Replace 'production' as necessary for each environment.
247
197
 
248
198
  Make sure that the current user has read and write access to the folder listed
249
- in the configuration option symmetric_key_filename above.
199
+ in the config file option key_filename.
200
+
201
+ Note: Ignore the warning about the key files "not found or readable" since they
202
+ are being generated
250
203
 
251
204
  Once the Symmetric Encryption keys have been generated, secure them further by
252
- making the files read-only to the Rails user and not readable by any other user
205
+ making the files read-only to the Rails user and not readable by any other user.
206
+ Change ownership of the keys to the rails user and only give it access to read the key files:
207
+
208
+ chown rails /etc/rails/keys/*
209
+ chmod 0400 /etc/rails/keys/*
253
210
 
254
- chmod ...
211
+ Change 'rails' above to the userid under which your Rails processes are run
212
+ and update the path to the one supplied when generating the config file or
213
+ look in the config file itself
255
214
 
256
215
  When running multiple Rails servers in a particular environment copy the same
257
216
  key files to every server in that environment. I.e. All Rails servers in each
@@ -261,8 +220,16 @@ Note: The generate step above must only be run once in each environment
261
220
 
262
221
  ## Using in non-Rails environments
263
222
 
264
- symmetric-encryption can also be used in non-Rails environment. At application
265
- startup, run the code below to initialize symmetric-encryption prior to
223
+ SymmetricEncryption can also be used in non-Rails environment.
224
+
225
+ Install SymmetricEncryption
226
+
227
+ gem install symmetric-encryption
228
+
229
+ Manually create a symmetric-encryption.yml configuration file based on the
230
+ one supplied in examples/symmetric-encryption.yml.
231
+
232
+ At application startup, run the code below to initialize symmetric-encryption prior to
266
233
  attempting to encrypt or decrypt any data
267
234
 
268
235
  require 'symmetric-encryption'
@@ -309,8 +276,8 @@ Create a configuration file in config/symmetric-encryption.yml per the following
309
276
  # can be placed directly in the source code.
310
277
  # And therefore no RSA private key is required
311
278
  development: &development_defaults
312
- key: 1234567890ABCDEF1234567890ABCDEF
313
- iv: 1234567890ABCDEF
279
+ key: 1234567890ABCDEF1234567890ABCDEF
280
+ iv: 1234567890ABCDEF
314
281
  cipher: aes-128-cbc
315
282
 
316
283
  test:
@@ -358,7 +325,7 @@ Create a configuration file in config/symmetric-encryption.yml per the following
358
325
  # Filename containing Symmetric Encryption Key encrypted using the
359
326
  # RSA public key derived from the private key above
360
327
  key_filename: /etc/rails/.rails.key
361
- iv_filename: /etc/rails/.rails.iv
328
+ iv_filename: /etc/rails/.rails.iv
362
329
 
363
330
  # Encryption cipher
364
331
  # Recommended values:
@@ -380,10 +347,17 @@ Create a configuration file in config/symmetric-encryption.yml per the following
380
347
  # Only used when old data still exists that requires old decryption keys
381
348
  # to be used
382
349
  key_filename: /etc/rails/.rails_old.key
383
- iv_filename: /etc/rails/.rails_old.iv
384
- cipher: aes-256-cbc
350
+ iv_filename: /etc/rails/.rails_old.iv
351
+ cipher: aes-256-cbc
385
352
 
386
- ## Possible Future Enhancements
353
+ ## Future Enhancements
354
+
355
+ * Ability to randomly generate a new initialization vector (iv) with every
356
+ encryption and put the iv in the encrypted data as its header
357
+
358
+ * With file encryption randomly generate a new key and initialization vector (iv) with every
359
+ file encryption and put the key and iv in the encrypted data as its header which
360
+ is encrypted using the global key and iv
387
361
 
388
362
  Submit an issue ticket to request any of the following features:
389
363
 
@@ -395,16 +369,6 @@ Submit an issue ticket to request any of the following features:
395
369
  data exceeds some predefined size. And automatically decompressing the data
396
370
  during decryption
397
371
 
398
- * Make attr_encrypted auto-detect the encrypted column type and Base64 encode
399
- when type is CHAR and store as binary when type is BINARY or BLOB
400
-
401
- * Create rake task / generator to generate a sample configuration file
402
- with a new RSA Private key already in it
403
-
404
- * Ability to change SymmetricEncryption configuration options from custom
405
- Rails initializers, rather than having everything in the config file.
406
- For example config.symmetric_encryption.cipher = 'aes-128-cbc'
407
-
408
372
  Meta
409
373
  ----
410
374
 
@@ -68,6 +68,21 @@ production:
68
68
  # JRuby 1.6.7 with Ruby 1.8.7 Approximately 22,000 encryptions or decryptions per second
69
69
  cipher: aes-256-cbc
70
70
 
71
+ # Set the way the encrypted data is encoded:
72
+ # base64
73
+ # Encrypted data is returned in base64 encoding format
74
+ # Symmetric::Encryption.decrypt will also base64 decode any data prior
75
+ # to decrypting it
76
+ # base64strict
77
+ # As base64 except that does not contain any newlines
78
+ # This is the recommended setting
79
+ # none
80
+ # Encrypted data is returned as raw binary
81
+ # Although smaller than base64 it cannot be stored in MySQL text columns
82
+ # It can only be held in binary columns such as BINARY or BLOB
83
+ # Default: base64
84
+ encoding: base64strict
85
+
71
86
  # FUTURE ENHANCEMENT:
72
87
  #
73
88
  # By adding a version indicator all encrypted data will include
@@ -86,23 +101,6 @@ production:
86
101
  # Default: 0
87
102
  #version: 0
88
103
 
89
- # FUTURE ENHANCEMENT:
90
- #
91
- # Set the way the encrypted data is encoded:
92
- # base64
93
- # Encrypted data is returned in base64 encoding format
94
- # Symmetric::Encryption.decrypt will also base64 decode any data prior
95
- # to decrypting it
96
- # base64withoutsuffix
97
- # As base64 except that the trailing newline is removed after base64
98
- # encoding
99
- # binary
100
- # Encrypted data is returned as raw binary
101
- # Although smaller than base64 it cannot be stored in MySQL text columns
102
- # It can only be held in binary columns such as BINARY or BLOB
103
- # Default: base64withoutsuffix
104
- #encoding: base64withoutsuffix
105
-
106
104
  # OPTIONAL:
107
105
  #
108
106
  # Any previous Symmetric Encryption Keys
@@ -112,3 +110,4 @@ production:
112
110
  - key_filename: /etc/rails/.rails_old.key
113
111
  iv_filename: /etc/rails/.rails_old.iv
114
112
  cipher: aes-256-cbc
113
+ encoding: base64strict
@@ -0,0 +1,22 @@
1
+ module SymmetricEncryption
2
+ module Generators
3
+ class ConfigGenerator < Rails::Generators::Base
4
+ desc "Creates a SymmetricEncryption configuration file at config/symmetric-encryption.yml"
5
+
6
+ argument :key_path, :type => :string, :optional => false
7
+
8
+ def self.source_root
9
+ @_symmetric_encryption_source_root ||= File.expand_path("../templates", __FILE__)
10
+ end
11
+
12
+ def app_name
13
+ Rails::Application.subclasses.first.parent.to_s.underscore
14
+ end
15
+
16
+ def create_config_file
17
+ template 'symmetric-encryption.yml', File.join('config', "symmetric-encryption.yml")
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,50 @@
1
+ #
2
+ # Symmetric Encryption for Ruby
3
+ #
4
+ ---
5
+ # For the development and test environments the test symmetric encryption keys
6
+ # can be placed directly in the source code.
7
+ # And therefore no RSA private key is required
8
+ development: &development_defaults
9
+ key: 1234567890ABCDEF1234567890ABCDEF
10
+ iv: 1234567890ABCDEF
11
+ cipher: aes-128-cbc
12
+
13
+ test:
14
+ <<: *development_defaults
15
+
16
+ release:
17
+ # Since the key to encrypt and decrypt with must NOT be stored along with the
18
+ # source code, we only hold a RSA key that is used to unlock the file
19
+ # containing the actual symmetric encryption key
20
+ private_rsa_key: |
21
+ <%= OpenSSL::PKey::RSA.generate(2048).to_s.collect { |line| " #{line}" }.join('') %>
22
+
23
+ # List Symmetric Key files in the order of current / latest first
24
+ ciphers:
25
+ -
26
+ # Filename containing Symmetric Encryption Key encrypted using the
27
+ # RSA public key derived from the private key above
28
+ key_filename: <%= File.join(key_path, "#{app_name}_release.key") %>
29
+ iv_filename: <%= File.join(key_path, "#{app_name}_release.iv") %>
30
+ cipher: aes-256-cbc
31
+ # Base64 encode encrypted data without newlines
32
+ encoding: base64strict
33
+
34
+ production:
35
+ # Since the key to encrypt and decrypt with must NOT be stored along with the
36
+ # source code, we only hold a RSA key that is used to unlock the file
37
+ # containing the actual symmetric encryption key
38
+ private_rsa_key: |
39
+ <%= OpenSSL::PKey::RSA.generate(2048).to_s.collect { |line| " #{line}" }.join('') %>
40
+
41
+ # List Symmetric Key files in the order of current / latest first
42
+ ciphers:
43
+ -
44
+ # Filename containing Symmetric Encryption Key encrypted using the
45
+ # RSA public key derived from the private key above
46
+ key_filename: <%= File.join(key_path, "#{app_name}_production.key") %>
47
+ iv_filename: <%= File.join(key_path, "#{app_name}_production.iv") %>
48
+ cipher: aes-256-cbc
49
+ # Base64 encode encrypted data without newlines
50
+ encoding: base64strict
@@ -0,0 +1,14 @@
1
+ module SymmetricEncryption
2
+ module Generators
3
+ class NewKeysGenerator < Rails::Generators::Base
4
+ desc "Generate new Symmetric key and initialization vector based on values in config/symmetric-encryption.yml"
5
+
6
+ argument :environment, :type => :string, :optional => false
7
+
8
+ def create_config_file
9
+ SymmetricEncryption.generate_symmetric_key_files(File.join('config', "symmetric-encryption.yml"), environment)
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -7,10 +7,11 @@ module SymmetricEncryption
7
7
  # threads at the same time without needing an instance of Cipher per thread
8
8
  class Cipher
9
9
  # Cipher to use for encryption and decryption
10
- attr_reader :cipher, :version
10
+ attr_reader :cipher, :version, :version
11
+ attr_accessor :encoding
11
12
 
12
- # Future Use:
13
- # attr_accessor :encoding, :version
13
+ # Available encodings
14
+ ENCODINGS = [:none, :base64, :base64strict]
14
15
 
15
16
  # Generate a new Symmetric Key pair
16
17
  #
@@ -43,6 +44,9 @@ module SymmetricEncryption
43
44
  @iv = parms[:iv]
44
45
  @cipher = parms[:cipher] || 'aes-256-cbc'
45
46
  @version = parms[:version]
47
+ @encoding = (parms[:encoding] || :base64).to_sym
48
+
49
+ raise("Invalid Encoding: #{@encoding}") unless ENCODINGS.include?(@encoding)
46
50
  end
47
51
 
48
52
  # AES Symmetric Encryption of supplied string
@@ -7,10 +7,14 @@ module SymmetricEncryption #:nodoc:
7
7
  # @example Set up configuration in the Rails app.
8
8
  # module MyApplication
9
9
  # class Application < Rails::Application
10
- # config.symmetric_encryption.cipher = 'aes-256-cbc'
10
+ # config.symmetric_encryption.cipher = SymmetricEncryption::Cipher.new(
11
+ # :key => '1234567890ABCDEF1234567890ABCDEF',
12
+ # :iv => '1234567890ABCDEF',
13
+ # :cipher => 'aes-128-cbc'
14
+ # )
11
15
  # end
12
16
  # end
13
- #config.symmetric_encryption = ::SymmetricEncryption::Config
17
+ config.symmetric_encryption = ::SymmetricEncryption
14
18
 
15
19
  rake_tasks do
16
20
  load "symmetric_encryption/railties/symmetric_encryption.rake"
@@ -33,8 +37,8 @@ module SymmetricEncryption #:nodoc:
33
37
  if config_file.file?
34
38
  ::SymmetricEncryption.load!(config_file, Rails.env)
35
39
  else
36
- puts "\nSymmetric Encryption config not found. Create a config file at: config/symmetric-encryption.yml"
37
- # puts "to generate one run: rails generate symmetric-encryption:config\n\n"
40
+ puts "\nSymmetric Encryption config not found."
41
+ puts "To generate one for the first time: rails generate symmetric_encryption:config\n\n"
38
42
  end
39
43
  end
40
44
 
@@ -23,11 +23,6 @@ namespace :symmetric_encryption do
23
23
  puts "\nEncrypted: #{SymmetricEncryption.encrypt(password1)}\n\n"
24
24
  end
25
25
 
26
- desc 'Generate new Symmetric key and initialization vector. Example: RAILS_ENV=production rake symmetric_encryption:generate_symmetric_keys'
27
- task :generate_symmetric_keys do
28
- SymmetricEncryption.generate_symmetric_key_files
29
- end
30
-
31
26
  desc 'Generate a random password and display its encrypted form. Example: rake symmetric_encryption:random_password'
32
27
  task :random_password => :environment do
33
28
  p = SymmetricEncryption.random_password
@@ -65,13 +65,19 @@ module SymmetricEncryption
65
65
  #
66
66
  def self.decrypt(str)
67
67
  raise "Call SymmetricEncryption.load! or SymmetricEncryption.cipher= prior to encrypting or decrypting data" unless @@cipher
68
- binary = ::Base64.decode64(str) if str
68
+
69
+ # Decode data first based on encoding setting
70
+ case @@cipher.encoding
71
+ when :base64, :base64strict
72
+ str = ::Base64.decode64(str) if str
73
+ end
74
+
69
75
  begin
70
- @@cipher.decrypt(binary)
76
+ @@cipher.decrypt(str)
71
77
  rescue OpenSSL::Cipher::CipherError => exc
72
78
  @@secondary_ciphers.each do |cipher|
73
79
  begin
74
- return cipher.decrypt(binary)
80
+ return cipher.decrypt(str)
75
81
  rescue OpenSSL::Cipher::CipherError
76
82
  end
77
83
  end
@@ -87,11 +93,18 @@ module SymmetricEncryption
87
93
  raise "Call SymmetricEncryption.load! or SymmetricEncryption.cipher= prior to encrypting or decrypting data" unless @@cipher
88
94
 
89
95
  # Encrypt data as a binary string
90
- result = @@cipher.encrypt(str)
91
-
92
- # Base 64 Encoding of binary data
93
- result = ::Base64.encode64(result) if result
94
- result
96
+ if result = @@cipher.encrypt(str)
97
+ # Now encode data based on encoding setting
98
+ case @@cipher.encoding
99
+ when :base64
100
+ # Base 64 Encoding of binary data
101
+ ::Base64.encode64(result)
102
+ when :base64strict
103
+ ::Base64.encode64(result).gsub(/\n/, '')
104
+ else
105
+ result
106
+ end
107
+ end
95
108
  end
96
109
 
97
110
  # Invokes decrypt
@@ -117,11 +130,9 @@ module SymmetricEncryption
117
130
  def self.encrypted?(encrypted_data)
118
131
  raise "Call SymmetricEncryption.load! or SymmetricEncryption.cipher= prior to encrypting or decrypting data" unless @@cipher
119
132
 
120
- # First make sure Base64 encoded data still ends with "\n" since it could be used in a key field somewhere
121
- return false unless encrypted_data.end_with?("\n")
122
-
123
133
  # For now have to decrypt it fully
124
- !try_decrypt(encrypted_data).nil?
134
+ result = try_decrypt(encrypted_data)
135
+ !(result.nil? || result == '')
125
136
  end
126
137
 
127
138
  # Load the Encryption Configuration from a YAML file
@@ -142,11 +153,7 @@ module SymmetricEncryption
142
153
  else
143
154
  private_rsa_key = config[:private_rsa_key]
144
155
  @@cipher, *@@secondary_ciphers = config[:ciphers].collect do |cipher_conf|
145
- cipher_from_encrypted_files(
146
- private_rsa_key,
147
- cipher_conf[:cipher],
148
- cipher_conf[:key_filename],
149
- cipher_conf[:iv_filename])
156
+ cipher_from_encrypted_files(private_rsa_key, cipher_conf)
150
157
  end
151
158
  end
152
159
 
@@ -164,7 +171,7 @@ module SymmetricEncryption
164
171
  # and initilization vector .iv
165
172
  # which is encrypted with the above Public key
166
173
  #
167
- # Warning: Existing files will be overwritten
174
+ # Existing key files will be renamed if present
168
175
  def self.generate_symmetric_key_files(filename=nil, environment=nil)
169
176
  config = read_config(filename, environment)
170
177
  cipher_cfg = config[:ciphers].first
@@ -239,6 +246,7 @@ module SymmetricEncryption
239
246
  :cipher => cipher_cfg['cipher'] || default_cipher,
240
247
  :key_filename => key_filename,
241
248
  :iv_filename => iv_filename,
249
+ :encoding => cipher_cfg['encoding']
242
250
  }
243
251
  end
244
252
 
@@ -271,18 +279,34 @@ module SymmetricEncryption
271
279
  # iv_filename
272
280
  # Optional. Name of file containing symmetric key initialization vector
273
281
  # encrypted using the public key matching the supplied private_key
274
- def self.cipher_from_encrypted_files(private_rsa_key, cipher, key_filename, iv_filename = nil)
282
+ def self.cipher_from_encrypted_files(private_rsa_key, cipher_conf)
275
283
  # Load Encrypted Symmetric keys
276
- encrypted_key = File.read(key_filename)
277
- encrypted_iv = File.read(iv_filename) if iv_filename
284
+ key_filename = cipher_conf[:key_filename]
285
+ encrypted_key = begin
286
+ File.read(key_filename)
287
+ rescue Errno::ENOENT
288
+ puts "\nSymmetric Encryption key file: '#{key_filename}' not found or readable."
289
+ puts "To generate the keys for the first time run: rails generate symmetric_encryption:new_keys\n\n"
290
+ return
291
+ end
292
+
293
+ iv_filename = cipher_conf[:iv_filename]
294
+ encrypted_iv = begin
295
+ File.read(iv_filename) if iv_filename
296
+ rescue Errno::ENOENT
297
+ puts "\nSymmetric Encryption initialization vector file: '#{iv_filename}' not found or readable."
298
+ puts "To generate the keys for the first time run: rails generate symmetric_encryption:new_keys\n\n"
299
+ return
300
+ end
278
301
 
279
302
  # Decrypt Symmetric Keys
280
303
  rsa = OpenSSL::PKey::RSA.new(private_rsa_key)
281
304
  iv = rsa.private_decrypt(encrypted_iv) if iv_filename
282
305
  Cipher.new(
283
- :key => rsa.private_decrypt(encrypted_key),
284
- :iv => iv,
285
- :cipher => cipher
306
+ :key => rsa.private_decrypt(encrypted_key),
307
+ :iv => iv,
308
+ :cipher => cipher_conf[:cipher],
309
+ :encoding => cipher_conf[:encoding]
286
310
  )
287
311
  end
288
312
 
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module SymmetricEncryption #:nodoc
3
- VERSION = "0.7.2"
3
+ VERSION = "0.8.0"
4
4
  end
@@ -51,10 +51,10 @@ class AttrEncryptedTest < Test::Unit::TestCase
51
51
 
52
52
  setup do
53
53
  @bank_account_number = "1234567890"
54
- @bank_account_number_encrypted = "L94ArJeFlJrZp6SYsvoOGA==\n"
54
+ @bank_account_number_encrypted = "L94ArJeFlJrZp6SYsvoOGA=="
55
55
 
56
56
  @social_security_number = "987654321"
57
- @social_security_number_encrypted = "S+8X1NRrqdfEIQyFHVPuVA==\n"
57
+ @social_security_number_encrypted = "S+8X1NRrqdfEIQyFHVPuVA=="
58
58
 
59
59
  @user = User.new(
60
60
  # Encrypted Attribute
@@ -39,9 +39,13 @@ test:
39
39
  - key_filename: /Users/rmorrison/Sandbox/symmetric-encryption/test/config/test_new.key
40
40
  iv_filename: /Users/rmorrison/Sandbox/symmetric-encryption/test/config/test_new.iv
41
41
  cipher: aes-128-cbc
42
+ # Base64 encode encrypted data without newlines
43
+ encoding: base64strict
42
44
 
43
45
  # Previous Symmetric Encryption Key
44
46
  - key_filename: /Users/rmorrison/Sandbox/symmetric-encryption/test/config/test_secondary_1.key
45
47
  iv_filename: /Users/rmorrison/Sandbox/symmetric-encryption/test/config/test_secondary_1.iv
46
48
  cipher: aes-128-cbc
49
+ # Base64 encode encrypted data without newlines
50
+ encoding: base64
47
51
 
@@ -39,19 +39,19 @@ class FieldEncryptedTest < Test::Unit::TestCase
39
39
  context 'the SymmetricEncryption Library' do
40
40
  setup do
41
41
  @bank_account_number = "1234567890"
42
- @bank_account_number_encrypted = "L94ArJeFlJrZp6SYsvoOGA==\n"
42
+ @bank_account_number_encrypted = "L94ArJeFlJrZp6SYsvoOGA=="
43
43
 
44
44
  @social_security_number = "987654321"
45
- @social_security_number_encrypted = "S+8X1NRrqdfEIQyFHVPuVA==\n"
45
+ @social_security_number_encrypted = "S+8X1NRrqdfEIQyFHVPuVA=="
46
46
 
47
47
  @integer = 32768
48
- @integer_encrypted = "FA3smFQEKqB/ITv+A0xACg==\n"
48
+ @integer_encrypted = "FA3smFQEKqB/ITv+A0xACg=="
49
49
 
50
50
  @float = 0.9867
51
- @float_encrypted = "z7Pwt2JDp74d+u0IXFAdrQ==\n"
51
+ @float_encrypted = "z7Pwt2JDp74d+u0IXFAdrQ=="
52
52
 
53
53
  @date = Date.parse('20120320')
54
- @date_encrypted = "WTkSPHo5ApSSHBJMxxWt2A==\n"
54
+ @date_encrypted = "WTkSPHo5ApSSHBJMxxWt2A=="
55
55
 
56
56
  # #TODO Intercept passing in attributes to create etc.
57
57
  @user = MongoidUser.new(
@@ -24,11 +24,42 @@ class SymmetricEncryptionTest < Test::Unit::TestCase
24
24
  end
25
25
  end
26
26
 
27
- context 'SymmetricEncryption tests' do
27
+ context 'Base64 encoding tests' do
28
28
  setup do
29
29
  @social_security_number = "987654321"
30
30
  @social_security_number_encrypted = "S+8X1NRrqdfEIQyFHVPuVA==\n"
31
31
  @social_security_number_encrypted_with_secondary_1 = "D1UCu38pqJ3jc0GvwJHiow==\n"
32
+ @encoding = SymmetricEncryption.cipher.encoding
33
+ SymmetricEncryption.cipher.encoding = :base64
34
+ end
35
+
36
+ teardown do
37
+ SymmetricEncryption.cipher.encoding = @encoding
38
+ end
39
+
40
+ should "encrypt simple string" do
41
+ assert_equal @social_security_number_encrypted, SymmetricEncryption.encrypt(@social_security_number)
42
+ end
43
+
44
+ should "decrypt string" do
45
+ assert_equal @social_security_number, SymmetricEncryption.decrypt(@social_security_number_encrypted)
46
+ end
47
+
48
+ should "determine if string is encrypted" do
49
+ assert_equal true, SymmetricEncryption.encrypted?(@social_security_number_encrypted)
50
+ assert_equal false, SymmetricEncryption.encrypted?(@social_security_number)
51
+ end
52
+
53
+ should "decrypt with secondary key when first one fails" do
54
+ assert_equal @social_security_number, SymmetricEncryption.decrypt(@social_security_number_encrypted)
55
+ end
56
+ end
57
+
58
+ context 'Base64Strict tests' do
59
+ setup do
60
+ @social_security_number = "987654321"
61
+ @social_security_number_encrypted = "S+8X1NRrqdfEIQyFHVPuVA=="
62
+ @social_security_number_encrypted_with_secondary_1 = "D1UCu38pqJ3jc0GvwJHiow=="
32
63
  end
33
64
 
34
65
  should "encrypt simple string" do
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 7
8
- - 2
9
- version: 0.7.2
7
+ - 8
8
+ - 0
9
+ version: 0.8.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Reid Morrison
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2012-08-22 00:00:00 -04:00
17
+ date: 2012-08-28 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
@@ -32,6 +32,9 @@ files:
32
32
  - csv_encrypted
33
33
  - csv_encrypted_zip
34
34
  - examples/symmetric-encryption.yml
35
+ - lib/rails/generators/symmetric_encryption/config/config_generator.rb
36
+ - lib/rails/generators/symmetric_encryption/config/templates/symmetric-encryption.yml
37
+ - lib/rails/generators/symmetric_encryption/new_keys/new_keys_generator.rb
35
38
  - lib/symmetric-encryption.rb
36
39
  - lib/symmetric_encryption/cipher.rb
37
40
  - lib/symmetric_encryption/extensions/active_record/base.rb