symmetric-encryption 3.6.0 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|