symmetric-encryption 3.6.0 → 3.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -649
- data/lib/_test_empty +0 -0
- data/lib/symmetric_encryption/cipher.rb +13 -13
- data/lib/symmetric_encryption/exception.rb +15 -0
- data/lib/symmetric_encryption/extensions/mongo_mapper/plugins/encrypted_key.rb +1 -1
- data/lib/symmetric_encryption/extensions/mongoid/encrypted.rb +1 -1
- data/lib/symmetric_encryption/generator.rb +23 -31
- data/lib/symmetric_encryption/railties/symmetric_encryption.rake +1 -1
- data/lib/symmetric_encryption/reader.rb +7 -5
- data/lib/symmetric_encryption/symmetric_encryption.rb +14 -14
- data/lib/symmetric_encryption/version.rb +1 -1
- data/lib/symmetric_encryption/writer.rb +4 -4
- data/lib/symmetric_encryption.rb +1 -0
- data/test/active_record_test.rb +12 -9
- data/test/cipher_test.rb +3 -3
- data/test/mongo_mapper_test.rb +445 -442
- data/test/mongoid_test.rb +11 -4
- data/test/reader_test.rb +16 -10
- data/test/symmetric_encryption_test.rb +15 -2
- data/test/test_db.sqlite3 +0 -0
- data/test/test_helper.rb +8 -6
- data/test/writer_test.rb +2 -2
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e915d588960df033c0b853044479791936cd44f3
|
4
|
+
data.tar.gz: b3f6ac284287271eb76e0e089cbeaab5977ffd3c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96d996cb3867547b6130c483e5b4eb6bcb51c6fe5b29a18d3cfafe2b2f9d8d0716d775fc67faba86afa8875970f84da324a8097babb05c4c65b780a7a2a7aa34
|
7
|
+
data.tar.gz: f653e563bf1175825859a1a8e4a3cf45adafee4f56f1089e85ac0b62ce4a309564a81181725b610d52ee1bf3849cb7859e37c396a79819c193acfc486835f031
|
data/README.md
CHANGED
@@ -15,658 +15,17 @@ and consistent way
|
|
15
15
|
Symmetric Encryption uses OpenSSL to encrypt and decrypt data, and can therefore
|
16
16
|
expose all the encryption algorithms supported by OpenSSL.
|
17
17
|
|
18
|
-
##
|
19
|
-
|
20
|
-
Many solutions that encrypt data require the encryption keys to be stored in the
|
21
|
-
applications source code or leave it up to the developer to secure the keys on
|
22
|
-
the application servers. symmetric-encryption takes care of securing the
|
23
|
-
symmetric encryption keys.
|
24
|
-
|
25
|
-
The following steps are used to secure the symmetric encryption keys using symmetric-encryption:
|
26
|
-
|
27
|
-
* Symmetric Encryption keys are stored in files that are not part of the application,
|
28
|
-
its source code, or even stored in its source control system. These files can be
|
29
|
-
created, managed and further secured by System Administrators. This prevents
|
30
|
-
developers having or needing to have access to the symmetric encryption keys
|
31
|
-
* The Operating System security features limit access to the Symmetric Encryption
|
32
|
-
key files to System Administrators and the userid under which the Rails application runs.
|
33
|
-
* The files in which the Symmetric Encryption keys are stored are further
|
34
|
-
encrypted using RSA 2048 bit encryption
|
35
|
-
|
36
|
-
In order for anyone to decrypt the data being encrypted in the database, they
|
37
|
-
would need access to ALL of the following:
|
38
|
-
* A copy of the files containing the Symmetric Encryption Keys which are secured
|
39
|
-
by the Operating System
|
40
|
-
* The application source code containing the RSA private key to decrypt the above files
|
41
|
-
* The userid and password for the database to copy the encrypted data itself,
|
42
|
-
or an unsecured copy or export of the database contents
|
43
|
-
|
44
|
-
A major feature of symmetric encryption is that it makes the encryption and decryption
|
45
|
-
automatically available when the Rails application is started. This includes all
|
46
|
-
rake tasks and the Rails console. In this way data can be encrypted or decrypted as
|
47
|
-
part of any rake task.
|
48
|
-
|
49
|
-
From a security perspective it is important then to properly secure the system so that
|
50
|
-
no hacker can switch to and run as the rails user and thereby gain access to the
|
51
|
-
encryption and decryption capabilities
|
52
|
-
|
53
|
-
It is not necessary to encrypt the IV (initialization vector), and it can be placed
|
54
|
-
directly in the configuration file. The encryption key must be kept secure and
|
55
|
-
must never be placed in the configuration file or other Rails source file in production.
|
56
|
-
The IV should be generated using the rails generator described below to ensure
|
57
|
-
it is a truly random key from the key space.
|
58
|
-
|
59
|
-
## Limitations
|
60
|
-
|
61
|
-
By default symmetric encryption uses the same initialization vector (IV) and
|
62
|
-
encryption key to encrypt data using the SymmetricEncryption.encrypt call.
|
63
|
-
This technique is required in cases where the encrypted data is used as a key
|
64
|
-
to lookup for example a Social Security Number, since for the same input data it
|
65
|
-
must always return the same encrypted result. The drawback is that this
|
66
|
-
technique is not considered secure when encypting large amounts of data.
|
67
|
-
|
68
|
-
For non-key fields, such as storing encrypted raw responses,
|
69
|
-
use the :random_iv => true option where possible so that a
|
70
|
-
randomly generated IV is used and included in every encrypted string.
|
71
|
-
|
72
|
-
The Symmetric Encryption streaming interface SymmetricEncryption::Writer avoids this
|
73
|
-
problem by using a random IV and key in every file/stream by default.
|
74
|
-
The random IV and key are stored in the header of the output stream so that it
|
75
|
-
is available when reading back the encrypted file/stream. The key is placed
|
76
|
-
in a header on the file in encrypted form using the current global key/cipher.
|
77
|
-
|
78
|
-
The ActiveRecord attr_encrypted method supports the :random_iv => true option.
|
79
|
-
Similarly for MongoMapper and Mongoid the :random_iv => true option can be added.
|
80
|
-
|
81
|
-
Note that encrypting the same input string with the same key and :random_iv => true
|
82
|
-
option will result in different encrypted output every time it is encrypted.
|
83
|
-
|
84
|
-
## Features
|
85
|
-
|
86
|
-
* Encryption of passwords in configuration files
|
87
|
-
* Encryption of ActiveRecord model attributes by prefixing attributes / column
|
88
|
-
names with encrypted_
|
89
|
-
* Encryption of MongoMapper keys by using :encrypted_key
|
90
|
-
* Encryption of Mongoid model fields by adding :encrypted option to field
|
91
|
-
definitions
|
92
|
-
* Externalization of symmetric encryption keys so that they are not in the
|
93
|
-
source code, or the source code control system
|
94
|
-
* Validator for ActiveRecord Models to ensure fields contain encrypted data
|
95
|
-
* Stream based encryption and decryption so that large files can be read or
|
96
|
-
written with encryption, along with a random key and IV for every file
|
97
|
-
* Stream based encryption and decryption also supports compression and decompression
|
98
|
-
on the fly
|
99
|
-
* When :compress => true option is specified Symmetric Encryption will transparently
|
100
|
-
compress the data prior to decryption. When decrypting compressed data Symmetric
|
101
|
-
Encryption will transparently decompress the data after decryption based on the
|
102
|
-
header stored in the encrypted data
|
103
|
-
* Uses built-in support in Ruby for OpenSSL and Zlib for high performance and
|
104
|
-
maximum portability without introducing any additional dependencies
|
105
|
-
* Drop in replacement for attr_encrypted. Just remove the attr_encrypted gem
|
106
|
-
* For maximum security supports fully random keys and initialization vectors
|
107
|
-
extracted from the entire encryption key space
|
108
|
-
|
109
|
-
## Recommendations
|
110
|
-
|
111
|
-
* Add the encryption header to all encrypted strings.
|
112
|
-
See the _always_add_header_ option in the configuration file.
|
113
|
-
|
114
|
-
* Add `random_iv: true` for all ActiveRecord attributes, MongoMapper keys, and
|
115
|
-
Mongoid fields which are not used in indexes and will not be used as part of a query.
|
116
|
-
|
117
|
-
## Binary Data
|
118
|
-
|
119
|
-
On decryption an attempt is made to encode the data as UTF-8, if it fails it
|
120
|
-
will be returned as BINARY encoded.
|
121
|
-
|
122
|
-
## Examples
|
123
|
-
|
124
|
-
### Encryption Example
|
125
|
-
|
126
|
-
```ruby
|
127
|
-
SymmetricEncryption.encrypt "Sensitive data"
|
128
|
-
```
|
129
|
-
|
130
|
-
### Decryption Example
|
131
|
-
|
132
|
-
```ruby
|
133
|
-
SymmetricEncryption.decrypt "JqLJOi6dNjWI9kX9lSL1XQ==\n"
|
134
|
-
```
|
135
|
-
|
136
|
-
### ActiveRecord Example
|
137
|
-
|
138
|
-
```ruby
|
139
|
-
class User < ActiveRecord::Base
|
140
|
-
# Requires table users to have a column called encrypted_bank_account_number
|
141
|
-
attr_encrypted :bank_account_number
|
142
|
-
|
143
|
-
# Requires users table to have a column called encrypted_social_security_number
|
144
|
-
#
|
145
|
-
# Note: Encrypting the same value twice will result in the _same_ encrypted value
|
146
|
-
# when :random_iv => false, or is not specified
|
147
|
-
attr_encrypted :social_security_number
|
148
|
-
|
149
|
-
# By specifying the type as :integer the value will be returned as an integer and
|
150
|
-
# can be set as an integer, even though it is stored in the database as an
|
151
|
-
# encrypted string
|
152
|
-
#
|
153
|
-
# Requires users table to have a column called encrypted_age of type string
|
154
|
-
attr_encrypted :age, type: integer
|
155
|
-
|
156
|
-
# Since string and long_string are not used in the where clause of any SQL
|
157
|
-
# queries it is better to ensure that the encrypted value is always different
|
158
|
-
# by encrypting every value with a random Initialization Vector.
|
159
|
-
#
|
160
|
-
# Note: Encrypting the same value twice will result in different encrypted
|
161
|
-
# values when :random_iv is true
|
162
|
-
attr_encrypted :string, random_iv: true
|
163
|
-
|
164
|
-
# Long encrypted strings can also be compressed prior to encryption to save
|
165
|
-
# disk space
|
166
|
-
attr_encrypted :long_string, random_iv: true, compress: true
|
167
|
-
|
168
|
-
# By specifying the type as :json the value will be serialized to JSON
|
169
|
-
# before encryption and deserialized from JSON after decryption.
|
170
|
-
#
|
171
|
-
# It is sometimes useful to use compression on large fields, so we can enable
|
172
|
-
# compression before the string is encrypted
|
173
|
-
#
|
174
|
-
# Requires users table to have a column called encrypted_values of type string
|
175
|
-
attr_encrypted :values, type: :json, compress: true
|
176
|
-
|
177
|
-
validates :encrypted_bank_account_number, symmetric_encryption: true
|
178
|
-
validates :encrypted_social_security_number, symmetric_encryption: true
|
179
|
-
end
|
180
|
-
|
181
|
-
# Create a new user instance assigning a bank account number
|
182
|
-
user = User.new
|
183
|
-
user.bank_account_number = '12345'
|
184
|
-
|
185
|
-
# Saves the bank_account_number in the column encrypted_bank_account_number in
|
186
|
-
# encrypted form
|
187
|
-
user.save!
|
188
|
-
|
189
|
-
# Short example using create
|
190
|
-
User.create(bank_account_number: '12345')
|
191
|
-
```
|
192
|
-
|
193
|
-
Several types are supported for ActiveRecord models when encrypting or decrypting data.
|
194
|
-
Each type maps to the built-in Ruby types as follows:
|
195
|
-
|
196
|
-
- :string => String
|
197
|
-
- :integer => Integer
|
198
|
-
- :float => Float
|
199
|
-
- :decimal => BigDecimal
|
200
|
-
- :datetime => DateTime
|
201
|
-
- :time => Time
|
202
|
-
- :date => Date
|
203
|
-
- :json => Uses JSON serialization, useful for hashes and arrays
|
204
|
-
- :yaml => Uses YAML serialization, useful for hashes and arrays
|
205
|
-
|
206
|
-
### MongoMapper Example
|
207
|
-
|
208
|
-
To encrypt a field in a MongoMapper document, use `encrypted_key` instead of `key`
|
209
|
-
when specifying a key.
|
210
|
-
|
211
|
-
```ruby
|
212
|
-
field :encrypted_age, type: String, encrypted: {type: :integer}
|
213
|
-
end
|
214
|
-
|
215
|
-
# User model MongoMapper
|
216
|
-
class User
|
217
|
-
include MongoMapper::Document
|
218
|
-
|
219
|
-
key :name, String
|
220
|
-
encrypted_key :bank_account_number, String
|
221
|
-
encrypted_key :social_security_number, String
|
222
|
-
encrypted_key :life_history, String, encrypted: { random_iv: true, compress: true }
|
223
|
-
|
224
|
-
# Encrypted fields are _always_ stored in Mongo as a String
|
225
|
-
# To get the result back as an Integer, Symmetric Encryption will automatically
|
226
|
-
# perform the necessary conversions
|
227
|
-
encrypted_key :integer_value, Integer
|
228
|
-
encrypted_key :float_value, Float
|
229
|
-
encrypted_key :decimal_value, BigDecimal
|
230
|
-
encrypted_key :datetime_value, DateTime
|
231
|
-
encrypted_key :time_value, Time
|
232
|
-
encrypted_key :date_value, Date
|
233
|
-
encrypted_key :true_value, Boolean
|
234
|
-
encrypted_key :data_json, Hash, encrypted: {random_iv: true, compress: true}
|
235
|
-
# By default Hash is saved as JSON, to save as YAML add the type specifier:
|
236
|
-
encrypted_key :data_yaml, Hash, encrypted: {random_iv: true, compress: true, type: :yaml}
|
237
|
-
|
238
|
-
# Optionally add validation to ensure that encrypted fields are in fact encrypted
|
239
|
-
# before the data is saved
|
240
|
-
validates :encrypted_bank_account_number, symmetric_encryption: true
|
241
|
-
validates :encrypted_social_security_number, symmetric_encryption: true
|
242
|
-
end
|
243
|
-
|
244
|
-
# Create a new user document
|
245
|
-
User.create(bank_account_number: '12345')
|
246
|
-
|
247
|
-
# When finding a document, always use the encrypted form of the field name
|
248
|
-
user = User.where(encrypted_bank_account_number: SymmetricEncryption.encrypt('12345')).first
|
249
|
-
|
250
|
-
# Fields can be accessed using their unencrypted names
|
251
|
-
puts user.bank_account_number
|
252
|
-
```
|
253
|
-
|
254
|
-
### Mongoid Example
|
255
|
-
|
256
|
-
To encrypt a field in a Mongoid document, just add "encrypted: true" at the end
|
257
|
-
of the field specifier. The field name must currently begin with "encrypted_"
|
258
|
-
|
259
|
-
```ruby
|
260
|
-
# User model in Mongoid
|
261
|
-
class User
|
262
|
-
include Mongoid::Document
|
263
|
-
|
264
|
-
field :name, type: String
|
265
|
-
field :encrypted_bank_account_number, type: String, encrypted: true
|
266
|
-
field :encrypted_social_security_number, type: String, encrypted: true
|
267
|
-
field :encrypted_life_history, type: String, encrypted: {compress: true, random_iv: true}
|
268
|
-
|
269
|
-
# Encrypted fields are _always_ stored in Mongo as a String
|
270
|
-
# To get the result back as an Integer, Symmetric Encryption can do the
|
271
|
-
# necessary conversions by specifying the internal type as an option
|
272
|
-
# to :encrypted
|
273
|
-
# #see SymmetricEncryption::COERCION_TYPES for full list of types
|
274
|
-
field :encrypted_age, type: String, encrypted: {type: :integer}
|
275
|
-
end
|
276
|
-
|
277
|
-
# Create a new user document
|
278
|
-
User.create(bank_account_number: '12345')
|
279
|
-
|
280
|
-
# When finding a document, always use the encrypted form of the field name
|
281
|
-
user = User.where(encrypted_bank_account_number: SymmetricEncryption.encrypt('12345')).first
|
282
|
-
|
283
|
-
# Fields can be accessed using their unencrypted names
|
284
|
-
puts user.bank_account_number
|
285
|
-
```
|
286
|
-
|
287
|
-
### Validation Example
|
288
|
-
|
289
|
-
```ruby
|
290
|
-
class MyModel < ActiveRecord::Base
|
291
|
-
validates :encrypted_ssn, symmetric_encryption: true
|
292
|
-
end
|
293
|
-
|
294
|
-
m = MyModel.new
|
295
|
-
m.valid?
|
296
|
-
# => false
|
297
|
-
m.encrypted_ssn = SymmetricEncryption.encrypt('123456789')
|
298
|
-
m.valid?
|
299
|
-
# => true
|
300
|
-
```
|
301
|
-
### Encrypting Passwords in configuration files
|
302
|
-
|
303
|
-
Passwords can be encrypted in any YAML configuration file.
|
304
|
-
|
305
|
-
For example config/database.yml
|
306
|
-
|
307
|
-
```yaml
|
308
|
-
---
|
309
|
-
production:
|
310
|
-
adapter: mysql
|
311
|
-
host: db1w
|
312
|
-
database: myapp_production
|
313
|
-
username: admin
|
314
|
-
password: <%= SymmetricEncryption.try_decrypt "JqLJOi6dNjWI9kX9lSL1XQ==\n" %>
|
315
|
-
```
|
316
|
-
|
317
|
-
Note: Use SymmetricEncryption.try_decrypt method which will return nil if it
|
318
|
-
fails to decrypt the value, which is essential when the encryption keys differ
|
319
|
-
between environments
|
320
|
-
|
321
|
-
Note: In order for the above technique to work in other YAML configuration files
|
322
|
-
the YAML file must be processed using ERB prior to passing to YAML. For example
|
323
|
-
|
324
|
-
```ruby
|
325
|
-
config_file = Rails.root.join('config', 'redis.yml')
|
326
|
-
raise "redis config not found. Create a config file at: config/redis.yml" unless config_file.file?
|
327
|
-
|
328
|
-
cfg = YAML.load(ERB.new(File.new(config_file).read).result)[Rails.env]
|
329
|
-
raise("Environment #{Rails.env} not defined in redis.yml") unless cfg
|
330
|
-
```
|
331
|
-
|
332
|
-
### Large File Encryption
|
333
|
-
|
334
|
-
Example: Read and decrypt a line at a time from a file
|
335
|
-
|
336
|
-
```ruby
|
337
|
-
SymmetricEncryption::Reader.open('encrypted_file') do |file|
|
338
|
-
file.each_line do |line|
|
339
|
-
puts line
|
340
|
-
end
|
341
|
-
end
|
342
|
-
```
|
343
|
-
|
344
|
-
Example: Encrypt and write data to a file
|
345
|
-
|
346
|
-
```ruby
|
347
|
-
SymmetricEncryption::Writer.open('encrypted_file') do |file|
|
348
|
-
file.write "Hello World\n"
|
349
|
-
file.write "Keep this secret"
|
350
|
-
end
|
351
|
-
```
|
352
|
-
|
353
|
-
Example: Compress, Encrypt and write data to a file
|
354
|
-
|
355
|
-
```ruby
|
356
|
-
SymmetricEncryption::Writer.open('encrypted_compressed.zip', compress: true) do |file|
|
357
|
-
file.write "Hello World\n"
|
358
|
-
file.write "Compress this\n"
|
359
|
-
file.write "Keep this safe and secure\n"
|
360
|
-
end
|
361
|
-
```
|
362
|
-
|
363
|
-
### Standalone test
|
364
|
-
|
365
|
-
Before generating keys we can use SymmetricEncryption in a standalone test environment:
|
366
|
-
|
367
|
-
```ruby
|
368
|
-
# Use test encryption keys
|
369
|
-
SymmetricEncryption.cipher = SymmetricEncryption::Cipher.new(
|
370
|
-
key: '1234567890ABCDEF1234567890ABCDEF',
|
371
|
-
iv: '1234567890ABCDEF',
|
372
|
-
cipher_name: 'aes-128-cbc'
|
373
|
-
)
|
374
|
-
encrypted = SymmetricEncryption.encrypt('hello world')
|
375
|
-
puts SymmetricEncryption.decrypt(encrypted)
|
376
|
-
```
|
377
|
-
|
378
|
-
### Rake Tasks
|
379
|
-
|
380
|
-
For PCI compliance developers should not be the ones creating or encrypting
|
381
|
-
passwords. The following rake tasks can be used by system administrators to
|
382
|
-
generate and encrypt passwords for databases, or external web calls.
|
383
|
-
It is safe to pass the encrypted password for say MySQL to the developers
|
384
|
-
who can then put it in the config files which are kept in source control.
|
385
|
-
|
386
|
-
Generate a random password and display its encrypted form:
|
387
|
-
|
388
|
-
rake symmetric_encryption:random_password
|
389
|
-
|
390
|
-
Encrypt a known value, such as a password:
|
391
|
-
|
392
|
-
rake symmetric_encryption:encrypt
|
393
|
-
|
394
|
-
Note: Passwords must be encrypted in the environment in which they will be used.
|
395
|
-
Since each environment should have its own symmetric encryption keys
|
396
|
-
|
397
|
-
Note: To use the rake task 'symmetric_encryption:encrypt' the gem 'highline'
|
398
|
-
must first be installed by adding to bundler or installing directly:
|
399
|
-
|
400
|
-
```ruby
|
401
|
-
gem install 'highline'
|
402
|
-
```
|
403
|
-
|
404
|
-
Encrypt a file
|
405
|
-
|
406
|
-
INFILE="Gemfile.lock" OUTFILE="Gemfile.lock.encrypted" rake symmetric_encryption:encrypt_file
|
407
|
-
|
408
|
-
Encrypt and compress a file
|
18
|
+
## Documentation
|
409
19
|
|
410
|
-
|
20
|
+
For complete documentation see: http://reidmorrison.github.io/symmetric-encryption/
|
411
21
|
|
412
|
-
|
22
|
+
## Changes with V4
|
413
23
|
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
The file header also contains a random key and iv used to encrypt the files contents.
|
420
|
-
The key and iv is encrypted with the global encryption key being used by the symmetric
|
421
|
-
encryption installation.
|
422
|
-
|
423
|
-
## Dependencies
|
424
|
-
|
425
|
-
- Ruby 1.9.3 (or above) Or, JRuby 1.7.3 (or above)
|
426
|
-
- Optional: To log to MongoDB, Mongo Ruby Driver 1.5.2 or above
|
427
|
-
|
428
|
-
## Installation
|
429
|
-
|
430
|
-
### Add to an existing Rails project
|
431
|
-
Add the following line to Gemfile
|
432
|
-
|
433
|
-
```ruby
|
434
|
-
gem 'symmetric-encryption'
|
435
|
-
```
|
436
|
-
|
437
|
-
Install the Gem with bundler
|
438
|
-
|
439
|
-
bundle install
|
440
|
-
|
441
|
-
## Rails Configuration
|
442
|
-
|
443
|
-
If deploying to Heroku skip to the section "Rails Configuration for a Heroku deployment" below
|
444
|
-
|
445
|
-
### Creating the configuration file
|
446
|
-
|
447
|
-
The configuration file contains the path to the production encryption key files.
|
448
|
-
Generally in development and test the files are not created, so supply the full path
|
449
|
-
to these files in production. Once the config file has been generated it can be
|
450
|
-
modified as needed.
|
451
|
-
|
452
|
-
Generate the configuration file:
|
453
|
-
|
454
|
-
rails generate symmetric_encryption:config /etc/rails/keys
|
455
|
-
|
456
|
-
Note: Ignore the warning about "Symmetric Encryption config not found" since it is
|
457
|
-
being generated
|
458
|
-
|
459
|
-
#### Save to version control
|
460
|
-
|
461
|
-
This configuration file should be checked into the source code control system.
|
462
|
-
It does Not include the Symmetric Encryption keys. They will be generated in the
|
463
|
-
next step.
|
464
|
-
|
465
|
-
### Generating and securing the Symmetric Encryption keys
|
466
|
-
|
467
|
-
Once development and testing is complete we need to generate secure encryption
|
468
|
-
key files for production. It is recommended that the step below be run on only
|
469
|
-
one of the production servers. The generated key files must then be copied to
|
470
|
-
all the production web servers.
|
471
|
-
|
472
|
-
Note: Do not run this step more than once, otherwise new keys will be generated
|
473
|
-
and any encrypted data will no longer be accessible.
|
474
|
-
|
475
|
-
Note: Do not run this step on more than one server in each environment otherwise
|
476
|
-
each server will be encrypting with it's own key and the servers will not be able
|
477
|
-
to decrypt data encrypted on another server. Just copy the generated files to each
|
478
|
-
server
|
479
|
-
|
480
|
-
The symmetric encryption key consists of the key itself and an optional
|
481
|
-
initialization vector.
|
482
|
-
|
483
|
-
To generate the keys run the following Rake task once only in each environment:
|
484
|
-
|
485
|
-
rails generate symmetric_encryption:new_keys production
|
486
|
-
|
487
|
-
Replace 'production' as necessary for each environment.
|
488
|
-
|
489
|
-
Make sure that the current user has read and write access to the folder listed
|
490
|
-
in the config file option key_filename.
|
491
|
-
|
492
|
-
Note: Ignore the warning about the key files "not found or readable" since they
|
493
|
-
are being generated
|
494
|
-
|
495
|
-
Once the Symmetric Encryption keys have been generated, secure them further by
|
496
|
-
making the files read-only to the Rails user and not readable by any other user.
|
497
|
-
Change ownership of the keys to the rails user and only give it access to read the key files:
|
498
|
-
|
499
|
-
chown rails /etc/rails/keys/*
|
500
|
-
chmod 0400 /etc/rails/keys/*
|
501
|
-
|
502
|
-
Change 'rails' above to the userid under which your Rails processes are run
|
503
|
-
and update the path to the one supplied when generating the config file or
|
504
|
-
look in the config file itself
|
505
|
-
|
506
|
-
When running multiple Rails servers in a particular environment copy the same
|
507
|
-
key files to every server in that environment. I.e. All Rails servers in each
|
508
|
-
environment must run the same encryption keys.
|
509
|
-
|
510
|
-
Note: The generate step above must only be run once in each environment
|
511
|
-
|
512
|
-
## Rails Configuration for a Heroku deployment
|
513
|
-
|
514
|
-
Deploying to Heroku requires the encrypted key to be stored in an environment
|
515
|
-
variable rather than as a file on disk.
|
516
|
-
|
517
|
-
Generate the configuration file:
|
518
|
-
|
519
|
-
rails g symmetric_encryption:heroku_config
|
520
|
-
|
521
|
-
Note: Ignore the warning about "Symmetric Encryption config not found" since it is
|
522
|
-
being generated.
|
523
|
-
|
524
|
-
Note: The encrypted keys for the release and production environments are displayed on
|
525
|
-
screen and must be entered manually as environment variables into Heroku so that the
|
526
|
-
application can find them when it starts.
|
527
|
-
|
528
|
-
#### Save to version control
|
529
|
-
|
530
|
-
This configuration file should be checked into the source code control system.
|
531
|
-
It does Not include the Symmetric Encryption keys.
|
532
|
-
|
533
|
-
## Using in non-Rails environments
|
534
|
-
|
535
|
-
SymmetricEncryption can also be used in non-Rails environment.
|
536
|
-
|
537
|
-
Install SymmetricEncryption
|
538
|
-
|
539
|
-
gem install symmetric-encryption
|
540
|
-
|
541
|
-
Manually create a symmetric-encryption.yml configuration file based on the
|
542
|
-
one supplied in examples/symmetric-encryption.yml.
|
543
|
-
|
544
|
-
At application startup, run the code below to initialize symmetric-encryption prior to
|
545
|
-
attempting to encrypt or decrypt any data
|
546
|
-
|
547
|
-
```ruby
|
548
|
-
require 'symmetric-encryption'
|
549
|
-
SymmetricEncryption.load!('config/symmetric-encryption.yml', 'production')
|
550
|
-
```
|
551
|
-
|
552
|
-
Parameters:
|
553
|
-
|
554
|
-
* Filename of the configuration file created above
|
555
|
-
* Name of the environment to load the configuration for
|
556
|
-
|
557
|
-
To manually generate the symmetric encryption keys, run the code below
|
558
|
-
|
559
|
-
```ruby
|
560
|
-
require 'symmetric-encryption'
|
561
|
-
SymmetricEncryption.generate_symmetric_key_files('config/symmetric-encryption.yml', 'production')
|
562
|
-
```
|
563
|
-
|
564
|
-
Parameters:
|
565
|
-
|
566
|
-
* Filename of the configuration file created above
|
567
|
-
* Name of the environment to load the configuration for
|
568
|
-
|
569
|
-
## Supporting Multiple Encryption Keys
|
570
|
-
|
571
|
-
According to the PCI Compliance documentation: "Cryptographic keys must be changed on an annual basis."
|
572
|
-
|
573
|
-
During the transition period of moving from one encryption key to another
|
574
|
-
symmetric-encryption supports multiple Symmetric Encryption keys. If decryption
|
575
|
-
with the current key fails, any previous keys will also be tried automatically.
|
576
|
-
|
577
|
-
By default the latest key is used for encrypting data. Another key can be specified
|
578
|
-
for encryption so that old data can be looked in queries, etc.
|
579
|
-
|
580
|
-
Since just the Symmetric Encryption keys are being changed, we can still continue to
|
581
|
-
use the same RSA Private key for gaining access to the Symmetric Encryption Keys
|
582
|
-
|
583
|
-
### Configuring multiple Symmetric Encryption keys
|
584
|
-
|
585
|
-
Create a configuration file in config/symmetric-encryption.yml per the following example:
|
586
|
-
|
587
|
-
```yaml
|
588
|
-
#
|
589
|
-
# Symmetric Encryption for Ruby
|
590
|
-
#
|
591
|
-
---
|
592
|
-
# For the development and test environments the test symmetric encryption keys
|
593
|
-
# can be placed directly in the source code.
|
594
|
-
# And therefore no RSA private key is required
|
595
|
-
development: &development_defaults
|
596
|
-
key: 1234567890ABCDEF1234567890ABCDEF
|
597
|
-
iv: 1234567890ABCDEF
|
598
|
-
cipher_name: aes-128-cbc
|
599
|
-
|
600
|
-
test:
|
601
|
-
<<: *development_defaults
|
602
|
-
|
603
|
-
production:
|
604
|
-
# Since the key to encrypt and decrypt with must NOT be stored along with the
|
605
|
-
# source code, we only hold a RSA key that is used to unlock the file
|
606
|
-
# containing the actual symmetric encryption key
|
607
|
-
#
|
608
|
-
# Sample RSA Key, DO NOT use this RSA key, generate a new one using
|
609
|
-
# openssl genrsa 2048
|
610
|
-
private_rsa_key: |
|
611
|
-
-----BEGIN RSA PRIVATE KEY-----
|
612
|
-
MIIEpAIBAAKCAQEAxIL9H/jYUGpA38v6PowRSRJEo3aNVXULNM/QNRpx2DTf++KH
|
613
|
-
6DcuFTFcNSSSxG9n4y7tKi755be8N0uwCCuOzvXqfWmXYjbLwK3Ib2vm0btpHyvA
|
614
|
-
qxgqeJOOCxKdW/cUFLWn0tACUcEjVCNfWEGaFyvkOUuR7Ub9KfhbW9cZO3BxZMUf
|
615
|
-
IPGlHl/gWyf484sXygd+S7cpDTRRzo9RjG74DwfE0MFGf9a1fTkxnSgeOJ6asTOy
|
616
|
-
fp9tEToUlbglKaYGpOGHYQ9TV5ZsyJ9jRUyb4SP5wK2eK6dHTxTcHvT03kD90Hv4
|
617
|
-
WeKIXv3WOjkwNEyMdpnJJfSDb5oquQvCNi7ZSQIDAQABAoIBAQCbzR7TUoBugU+e
|
618
|
-
ICLvpC2wOYOh9kRoFLwlyv3QnH7WZFWRZzFJszYeJ1xr5etXQtyjCnmOkGAg+WOI
|
619
|
-
k8GlOKOpAuA/PpB/leJFiYL4lBwU/PmDdTT0cdx6bMKZlNCeMW8CXGQKiFDOcMqJ
|
620
|
-
0uGtH5YD+RChPIEeFsJxnC8SyZ9/t2ra7XnMGiCZvRXIUDSEIIsRx/mOymJ7bL+h
|
621
|
-
Lbp46IfXf6ZuIzwzoIk0JReV/r+wdmkAVDkrrMkCmVS4/X1wN/Tiik9/yvbsh/CL
|
622
|
-
ztC55eSIEjATkWxnXfPASZN6oUfQPEveGH3HzNjdncjH/Ho8FaNMIAfFpBhhLPi9
|
623
|
-
nG5sbH+BAoGBAOdoUyVoAA/QUa3/FkQaa7Ajjehe5MR5k6VtaGtcxrLiBjrNR7x+
|
624
|
-
nqlZlGvWDMiCz49dgj+G1Qk1bbYrZLRX/Hjeqy5dZOGLMfgf9eKUmS1rDwAzBMcj
|
625
|
-
M9jnnJEBx8HIlNzaR6wzp3GMd0rrccs660A8URvzkgo9qNbvMLq9vyUtAoGBANll
|
626
|
-
SY1Iv9uaIz8klTXU9YzYtsfUmgXzw7K8StPdbEbo8F1J3JPJB4D7QHF0ObIaSWuf
|
627
|
-
suZqLsvWlYGuJeyX2ntlBN82ORfvUdOrdrbDlmPyj4PfFVl0AK3U3Ai374DNrjKR
|
628
|
-
hF6YFm4TLDaJhUjeV5C43kbE1N2FAMS9LYtPJ44NAoGAFDGHZ/E+aCLerddfwwun
|
629
|
-
MBS6MnftcLPHTZ1RimTrNfsBXipBw1ItWEvn5s0kCm9X24PmdNK4TnhqHYaF4DL5
|
630
|
-
ZjbQK1idEA2Mi8GGPIKJJ2x7P6I0HYiV4qy7fe/w1ZlCXE90B7PuPbtrQY9wO7Ll
|
631
|
-
ipJ45X6I1PnyfOcckn8yafUCgYACtPAlgjJhWZn2v03cTbqA9nHQKyV/zXkyUIXd
|
632
|
-
/XPLrjrP7ouAi5A8WuSChR/yx8ECRgrEM65Be3qBEtoGCB4AS1G0NcigM6qhKBFi
|
633
|
-
VS0aMXr3+V8argcUIwJaWW/x+p2go48yXlJpLHPweeXe8mXEt4iM+QZte6p2yKQ4
|
634
|
-
h9PGQQKBgQCqSydmXBnXGIVTp2sH/2GnpxLYnDBpcJE0tM8bJ42HEQQgRThIChsn
|
635
|
-
PnGA91G9MVikYapgI0VYBHQOTsz8rTIUzsKwXG+TIaK+W84nxH5y6jUkjqwxZmAz
|
636
|
-
r1URaMAun2PfAB4g2N/kEZTExgeOGqXjFhvvjdzl97ux2cTyZhaTXg==
|
637
|
-
-----END RSA PRIVATE KEY-----
|
638
|
-
|
639
|
-
# List Symmetric Key files in the order of current / latest first
|
640
|
-
ciphers:
|
641
|
-
-
|
642
|
-
# Filename containing Symmetric Encryption Key encrypted using the
|
643
|
-
# RSA public key derived from the private key above
|
644
|
-
key_filename: /etc/rails/.rails.key
|
645
|
-
iv_filename: /etc/rails/.rails.iv
|
646
|
-
|
647
|
-
# Encryption cipher_name
|
648
|
-
# Recommended values:
|
649
|
-
# aes-256-cbc
|
650
|
-
# 256 AES CBC Algorithm. Very strong
|
651
|
-
# Ruby 1.8.7 MRI Approximately 100,000 encryptions or decryptions per second
|
652
|
-
# JRuby 1.6.7 with Ruby 1.8.7 Approximately 22,000 encryptions or decryptions per second
|
653
|
-
# aes-128-cbc
|
654
|
-
# 128 AES CBC Algorithm. Less strong.
|
655
|
-
# Ruby 1.8.7 MRI Approximately 100,000 encryptions or decryptions per second
|
656
|
-
# JRuby 1.6.7 with Ruby 1.8.7 Approximately 22,000 encryptions or decryptions per second
|
657
|
-
cipher_name: aes-256-cbc
|
658
|
-
|
659
|
-
-
|
660
|
-
# OPTIONAL:
|
661
|
-
#
|
662
|
-
# Any previous Symmetric Encryption Keys
|
663
|
-
#
|
664
|
-
# Only used when old data still exists that requires old decryption keys
|
665
|
-
# to be used
|
666
|
-
key_filename: /etc/rails/.rails_old.key
|
667
|
-
iv_filename: /etc/rails/.rails_old.iv
|
668
|
-
cipher_name: aes-256-cbc
|
669
|
-
```
|
24
|
+
* V4 takes advantage of Ruby V2 named parameters and as such only works with
|
25
|
+
Ruby V2, and greater. This also means that for JRuby users it must be run in
|
26
|
+
V2 mode if not already running JRuby 9.0.0.0 or greater.
|
27
|
+
Users requiring compatibility with Ruby 1.8.7 and JRuby 1.7 ( 1.9 mode )
|
28
|
+
should continue to run Symmetric Encryption V3
|
670
29
|
|
671
30
|
## New features in V1.1 and V2
|
672
31
|
|
data/lib/_test_empty
ADDED
Binary file
|