symmetric-encryption 3.4.0 → 3.6.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 +102 -55
- data/Rakefile +13 -8
- data/lib/rails/generators/symmetric_encryption/config/config_generator.rb +1 -1
- data/lib/rails/generators/symmetric_encryption/heroku_config/templates/symmetric-encryption.yml +2 -2
- data/lib/rails/generators/symmetric_encryption/new_keys/new_keys_generator.rb +2 -2
- data/lib/symmetric_encryption.rb +7 -6
- data/lib/symmetric_encryption/cipher.rb +4 -4
- data/lib/symmetric_encryption/extensions/active_record/base.rb +6 -46
- data/lib/symmetric_encryption/extensions/mongo_mapper/plugins/encrypted_key.rb +129 -0
- data/lib/symmetric_encryption/{mongoid.rb → extensions/mongoid/encrypted.rb} +12 -46
- data/lib/symmetric_encryption/generator.rb +54 -0
- data/lib/symmetric_encryption/railtie.rb +3 -3
- data/lib/symmetric_encryption/railties/symmetric_encryption.rake +1 -1
- data/lib/symmetric_encryption/railties/symmetric_encryption_validator.rb +1 -1
- data/lib/symmetric_encryption/reader.rb +3 -3
- data/lib/symmetric_encryption/symmetric_encryption.rb +25 -15
- data/lib/symmetric_encryption/version.rb +1 -1
- data/lib/symmetric_encryption/writer.rb +4 -4
- data/test/active_record_test.rb +474 -0
- data/test/cipher_test.rb +15 -15
- data/test/config/mongo_mapper.yml +7 -0
- data/test/{field_encrypted_test.rb → mongo_mapper_test.rb} +68 -67
- data/test/mongoid_test.rb +535 -0
- data/test/reader_test.rb +10 -10
- data/test/symmetric_encryption_test.rb +27 -27
- data/test/test_db.sqlite3 +0 -0
- data/test/test_helper.rb +0 -1
- data/test/writer_test.rb +2 -2
- metadata +14 -8
- data/test/attr_encrypted_test.rb +0 -622
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 888fb42ac32f310999fea9a5cfa4449e6c3802df
|
4
|
+
data.tar.gz: 4709db73139a8c5654b37f7fd8a8a2dd8cb2f00b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 85cc771aa2e69f51a386880353f42a5253974b89cd2fc5153dfe3ab5a01d5e43aad7b1fb995f961579271d245a0477bbc926cbc860896ad26a7ebed92e755103
|
7
|
+
data.tar.gz: bc0ca28f71e48111c594439de184ebe6b46110b0ce25c93da96afc01c2ceeeed21d46daa11ec91c626fb14147dc3ed2c8e932f541e765b0225ee0d03bbb2dc78
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
symmetric-encryption
|
1
|
+
symmetric-encryption [](http://travis-ci.org/reidmorrison/symmetric-encryption)
|
2
2
|
====================
|
3
3
|
|
4
4
|
* http://github.com/reidmorrison/symmetric-encryption
|
@@ -15,30 +15,6 @@ 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
|
-
## Upgrading from earlier versions to SymmetricEncryption V3
|
19
|
-
|
20
|
-
In version 3 of SymmetricEncryption, the following changes have been made that
|
21
|
-
may have backward compatibility issues:
|
22
|
-
|
23
|
-
* SymmetricEncryption.decrypt no longer rotates through all the decryption keys
|
24
|
-
when previous ciphers fail to decrypt the encrypted string.
|
25
|
-
In a very small, yet significant number of cases it was possible to decrypt data
|
26
|
-
using the incorrect key. Clearly the data returned was garbage, but it still
|
27
|
-
returned a string of data instead of throwing an exception.
|
28
|
-
See SymmetricEncryption.select_cipher to supply your own custom logic to
|
29
|
-
determine the correct cipher to use when the encrypted string does not have a
|
30
|
-
header and multiple ciphers are defined.
|
31
|
-
|
32
|
-
* Configuration file format prior to V1 is no longer supported
|
33
|
-
|
34
|
-
* New configuration option has been added to support setting encryption keys
|
35
|
-
from environment variables
|
36
|
-
|
37
|
-
* Cipher.parse_magic_header! now returns a Struct instead of an Array
|
38
|
-
|
39
|
-
* New config options :encrypted_key and :encrypted_iv to support setting
|
40
|
-
the encryption key in environment variables
|
41
|
-
|
42
18
|
## Security
|
43
19
|
|
44
20
|
Many solutions that encrypt data require the encryption keys to be stored in the
|
@@ -100,7 +76,7 @@ is available when reading back the encrypted file/stream. The key is placed
|
|
100
76
|
in a header on the file in encrypted form using the current global key/cipher.
|
101
77
|
|
102
78
|
The ActiveRecord attr_encrypted method supports the :random_iv => true option.
|
103
|
-
Similarly for Mongoid the :random_iv => true option can be added.
|
79
|
+
Similarly for MongoMapper and Mongoid the :random_iv => true option can be added.
|
104
80
|
|
105
81
|
Note that encrypting the same input string with the same key and :random_iv => true
|
106
82
|
option will result in different encrypted output every time it is encrypted.
|
@@ -110,6 +86,7 @@ option will result in different encrypted output every time it is encrypted.
|
|
110
86
|
* Encryption of passwords in configuration files
|
111
87
|
* Encryption of ActiveRecord model attributes by prefixing attributes / column
|
112
88
|
names with encrypted_
|
89
|
+
* Encryption of MongoMapper keys by using :encrypted_key
|
113
90
|
* Encryption of Mongoid model fields by adding :encrypted option to field
|
114
91
|
definitions
|
115
92
|
* Externalization of symmetric encryption keys so that they are not in the
|
@@ -134,8 +111,8 @@ option will result in different encrypted output every time it is encrypted.
|
|
134
111
|
* Add the encryption header to all encrypted strings.
|
135
112
|
See the _always_add_header_ option in the configuration file.
|
136
113
|
|
137
|
-
*
|
138
|
-
which are not used in indexes and will not be used as part of a query.
|
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.
|
139
116
|
|
140
117
|
## Binary Data
|
141
118
|
|
@@ -174,19 +151,19 @@ class User < ActiveRecord::Base
|
|
174
151
|
# encrypted string
|
175
152
|
#
|
176
153
|
# Requires users table to have a column called encrypted_age of type string
|
177
|
-
attr_encrypted :age, :
|
154
|
+
attr_encrypted :age, type: integer
|
178
155
|
|
179
156
|
# Since string and long_string are not used in the where clause of any SQL
|
180
157
|
# queries it is better to ensure that the encrypted value is always different
|
181
158
|
# by encrypting every value with a random Initialization Vector.
|
182
159
|
#
|
183
160
|
# Note: Encrypting the same value twice will result in different encrypted
|
184
|
-
# values when :random_iv
|
185
|
-
attr_encrypted :string, :
|
161
|
+
# values when :random_iv is true
|
162
|
+
attr_encrypted :string, random_iv: true
|
186
163
|
|
187
164
|
# Long encrypted strings can also be compressed prior to encryption to save
|
188
165
|
# disk space
|
189
|
-
attr_encrypted :long_string, :
|
166
|
+
attr_encrypted :long_string, random_iv: true, compress: true
|
190
167
|
|
191
168
|
# By specifying the type as :json the value will be serialized to JSON
|
192
169
|
# before encryption and deserialized from JSON after decryption.
|
@@ -195,10 +172,10 @@ class User < ActiveRecord::Base
|
|
195
172
|
# compression before the string is encrypted
|
196
173
|
#
|
197
174
|
# Requires users table to have a column called encrypted_values of type string
|
198
|
-
attr_encrypted :values, :
|
175
|
+
attr_encrypted :values, type: :json, compress: true
|
199
176
|
|
200
|
-
validates :encrypted_bank_account_number, :
|
201
|
-
validates :encrypted_social_security_number, :
|
177
|
+
validates :encrypted_bank_account_number, symmetric_encryption: true
|
178
|
+
validates :encrypted_social_security_number, symmetric_encryption: true
|
202
179
|
end
|
203
180
|
|
204
181
|
# Create a new user instance assigning a bank account number
|
@@ -210,7 +187,7 @@ user.bank_account_number = '12345'
|
|
210
187
|
user.save!
|
211
188
|
|
212
189
|
# Short example using create
|
213
|
-
User.create(:
|
190
|
+
User.create(bank_account_number: '12345')
|
214
191
|
```
|
215
192
|
|
216
193
|
Several types are supported for ActiveRecord models when encrypting or decrypting data.
|
@@ -226,9 +203,57 @@ Each type maps to the built-in Ruby types as follows:
|
|
226
203
|
- :json => Uses JSON serialization, useful for hashes and arrays
|
227
204
|
- :yaml => Uses YAML serialization, useful for hashes and arrays
|
228
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
|
+
|
229
254
|
### Mongoid Example
|
230
255
|
|
231
|
-
To encrypt a field in a Mongoid document, just add ":
|
256
|
+
To encrypt a field in a Mongoid document, just add "encrypted: true" at the end
|
232
257
|
of the field specifier. The field name must currently begin with "encrypted_"
|
233
258
|
|
234
259
|
```ruby
|
@@ -236,36 +261,34 @@ of the field specifier. The field name must currently begin with "encrypted_"
|
|
236
261
|
class User
|
237
262
|
include Mongoid::Document
|
238
263
|
|
239
|
-
field :name, :
|
240
|
-
field :encrypted_bank_account_number, :
|
241
|
-
field :encrypted_social_security_number, :
|
242
|
-
field :encrypted_life_history, :
|
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}
|
243
268
|
|
244
269
|
# Encrypted fields are _always_ stored in Mongo as a String
|
245
270
|
# To get the result back as an Integer, Symmetric Encryption can do the
|
246
271
|
# necessary conversions by specifying the internal type as an option
|
247
272
|
# to :encrypted
|
248
273
|
# #see SymmetricEncryption::COERCION_TYPES for full list of types
|
249
|
-
field :encrypted_age, :
|
274
|
+
field :encrypted_age, type: String, encrypted: {type: :integer}
|
250
275
|
end
|
251
276
|
|
252
277
|
# Create a new user document
|
253
|
-
User.create(:
|
278
|
+
User.create(bank_account_number: '12345')
|
254
279
|
|
255
280
|
# When finding a document, always use the encrypted form of the field name
|
256
|
-
user = User.where(:
|
281
|
+
user = User.where(encrypted_bank_account_number: SymmetricEncryption.encrypt('12345')).first
|
257
282
|
|
258
283
|
# Fields can be accessed using their unencrypted names
|
259
284
|
puts user.bank_account_number
|
260
285
|
```
|
261
286
|
|
262
|
-
Note: At this time Symmetric Encryption only supports Mongoid fields with a type of String
|
263
|
-
|
264
287
|
### Validation Example
|
265
288
|
|
266
289
|
```ruby
|
267
290
|
class MyModel < ActiveRecord::Base
|
268
|
-
validates :encrypted_ssn, :
|
291
|
+
validates :encrypted_ssn, symmetric_encryption: true
|
269
292
|
end
|
270
293
|
|
271
294
|
m = MyModel.new
|
@@ -330,7 +353,7 @@ end
|
|
330
353
|
Example: Compress, Encrypt and write data to a file
|
331
354
|
|
332
355
|
```ruby
|
333
|
-
SymmetricEncryption::Writer.open('encrypted_compressed.zip', :
|
356
|
+
SymmetricEncryption::Writer.open('encrypted_compressed.zip', compress: true) do |file|
|
334
357
|
file.write "Hello World\n"
|
335
358
|
file.write "Compress this\n"
|
336
359
|
file.write "Keep this safe and secure\n"
|
@@ -344,9 +367,9 @@ Before generating keys we can use SymmetricEncryption in a standalone test envir
|
|
344
367
|
```ruby
|
345
368
|
# Use test encryption keys
|
346
369
|
SymmetricEncryption.cipher = SymmetricEncryption::Cipher.new(
|
347
|
-
:
|
348
|
-
:
|
349
|
-
:
|
370
|
+
key: '1234567890ABCDEF1234567890ABCDEF',
|
371
|
+
iv: '1234567890ABCDEF',
|
372
|
+
cipher_name: 'aes-128-cbc'
|
350
373
|
)
|
351
374
|
encrypted = SymmetricEncryption.encrypt('hello world')
|
352
375
|
puts SymmetricEncryption.decrypt(encrypted)
|
@@ -685,6 +708,30 @@ production:
|
|
685
708
|
Default: false
|
686
709
|
```
|
687
710
|
|
711
|
+
## Upgrading from earlier versions to SymmetricEncryption V3
|
712
|
+
|
713
|
+
In version 3 of SymmetricEncryption, the following changes have been made that
|
714
|
+
may have backward compatibility issues:
|
715
|
+
|
716
|
+
* SymmetricEncryption.decrypt no longer rotates through all the decryption keys
|
717
|
+
when previous ciphers fail to decrypt the encrypted string.
|
718
|
+
In a very small, yet significant number of cases it was possible to decrypt data
|
719
|
+
using the incorrect key. Clearly the data returned was garbage, but it still
|
720
|
+
returned a string of data instead of throwing an exception.
|
721
|
+
See SymmetricEncryption.select_cipher to supply your own custom logic to
|
722
|
+
determine the correct cipher to use when the encrypted string does not have a
|
723
|
+
header and multiple ciphers are defined.
|
724
|
+
|
725
|
+
* Configuration file format prior to V1 is no longer supported
|
726
|
+
|
727
|
+
* New configuration option has been added to support setting encryption keys
|
728
|
+
from environment variables
|
729
|
+
|
730
|
+
* Cipher.parse_magic_header! now returns a Struct instead of an Array
|
731
|
+
|
732
|
+
* New config options :encrypted_key and :encrypted_iv to support setting
|
733
|
+
the encryption key in environment variables
|
734
|
+
|
688
735
|
Meta
|
689
736
|
----
|
690
737
|
|
@@ -695,16 +742,16 @@ Meta
|
|
695
742
|
|
696
743
|
This project uses [Semantic Versioning](http://semver.org/).
|
697
744
|
|
698
|
-
|
699
|
-
|
745
|
+
Author
|
746
|
+
------
|
700
747
|
|
701
748
|
[Reid Morrison](https://github.com/reidmorrison)
|
702
749
|
|
703
750
|
Contributors
|
704
751
|
------------
|
705
752
|
|
706
|
-
[M. Scott Ford](https://github.com/mscottford)
|
707
|
-
[Adam St. John](https://github.com/astjohn)
|
753
|
+
* [M. Scott Ford](https://github.com/mscottford)
|
754
|
+
* [Adam St. John](https://github.com/astjohn)
|
708
755
|
|
709
756
|
License
|
710
757
|
-------
|
data/Rakefile
CHANGED
@@ -1,15 +1,18 @@
|
|
1
|
-
lib = File.expand_path('../lib/', __FILE__)
|
2
|
-
$:.unshift lib unless $:.include?(lib)
|
3
|
-
|
4
|
-
require 'rubygems'
|
5
|
-
require 'rubygems/package'
|
6
1
|
require 'rake/clean'
|
7
2
|
require 'rake/testtask'
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
8
5
|
require 'symmetric_encryption/version'
|
9
6
|
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
task :gem do
|
8
|
+
system "gem build symmetric-encryption.gemspec"
|
9
|
+
end
|
10
|
+
|
11
|
+
task :publish => :gem do
|
12
|
+
system "git tag -a v#{SymmetricEncryption::VERSION} -m 'Tagging #{SymmetricEncryption::VERSION}'"
|
13
|
+
system "git push --tags"
|
14
|
+
system "gem push symmetric-encryption-#{SymmetricEncryption::VERSION}.gem"
|
15
|
+
system "rm symmetric-encryption-#{SymmetricEncryption::VERSION}.gem"
|
13
16
|
end
|
14
17
|
|
15
18
|
desc "Run Test Suite"
|
@@ -24,3 +27,5 @@ task :test do
|
|
24
27
|
|
25
28
|
Rake::Task['functional'].invoke
|
26
29
|
end
|
30
|
+
|
31
|
+
task :default => :test
|
@@ -3,7 +3,7 @@ module SymmetricEncryption
|
|
3
3
|
class ConfigGenerator < Rails::Generators::Base
|
4
4
|
desc "Creates a SymmetricEncryption configuration file at config/symmetric-encryption.yml"
|
5
5
|
|
6
|
-
argument :key_path, :
|
6
|
+
argument :key_path, type: :string, optional: false
|
7
7
|
|
8
8
|
def self.source_root
|
9
9
|
@_symmetric_encryption_source_root ||= File.expand_path("../templates", __FILE__)
|
data/lib/rails/generators/symmetric_encryption/heroku_config/templates/symmetric-encryption.yml
CHANGED
@@ -23,7 +23,7 @@ encrypted_key = ::Base64.strict_encode64(rsa_key.public_encrypt(key_pair[:key]))
|
|
23
23
|
|
24
24
|
puts "\n\n********************************************************************************"
|
25
25
|
puts "Add the release environment key to Heroku: (Optional)\n\n"
|
26
|
-
puts " heroku config:add RELEASE_KEY1
|
26
|
+
puts " heroku config:add RELEASE_KEY1=#{encrypted_key}\n\n"
|
27
27
|
-%>
|
28
28
|
release:
|
29
29
|
# Since the key to encrypt and decrypt with must NOT be stored along with the
|
@@ -52,7 +52,7 @@ iv = ::Base64.strict_encode64(key_pair[:iv])
|
|
52
52
|
encrypted_key = ::Base64.strict_encode64(rsa_key.public_encrypt(key_pair[:key]))
|
53
53
|
|
54
54
|
puts "Add the production key to Heroku:\n\n"
|
55
|
-
puts " heroku config:add PRODUCTION_KEY1
|
55
|
+
puts " heroku config:add PRODUCTION_KEY1=#{encrypted_key}\n\n"
|
56
56
|
puts "********************************************************************************\n\n\n"
|
57
57
|
-%>
|
58
58
|
production:
|
@@ -2,8 +2,8 @@ module SymmetricEncryption
|
|
2
2
|
module Generators
|
3
3
|
class NewKeysGenerator < Rails::Generators::Base
|
4
4
|
desc "Generate new Symmetric key and initialization vector based on values in config/symmetric-encryption.yml"
|
5
|
-
|
6
|
-
argument :environment, :
|
5
|
+
|
6
|
+
argument :environment, type: :string, optional: false
|
7
7
|
|
8
8
|
def create_config_file
|
9
9
|
SymmetricEncryption.generate_symmetric_key_files(File.join('config', "symmetric-encryption.yml"), environment)
|
data/lib/symmetric_encryption.rb
CHANGED
@@ -8,13 +8,14 @@ require 'symmetric_encryption/cipher'
|
|
8
8
|
require 'symmetric_encryption/symmetric_encryption'
|
9
9
|
|
10
10
|
module SymmetricEncryption
|
11
|
-
autoload :Reader,
|
12
|
-
autoload :Writer,
|
13
|
-
|
14
|
-
if defined?(Rails)
|
15
|
-
require 'symmetric_encryption/railtie'
|
11
|
+
autoload :Reader, 'symmetric_encryption/reader'
|
12
|
+
autoload :Writer, 'symmetric_encryption/writer'
|
13
|
+
autoload :Generator, 'symmetric_encryption/generator'
|
16
14
|
end
|
17
15
|
|
16
|
+
# Add support for other libraries only if they have already been loaded
|
17
|
+
require 'symmetric_encryption/railtie' if defined?(Rails)
|
18
18
|
require 'symmetric_encryption/extensions/active_record/base' if defined?(ActiveRecord::Base)
|
19
19
|
require 'symmetric_encryption/railties/symmetric_encryption_validator' if defined?(ActiveModel)
|
20
|
-
require 'symmetric_encryption/mongoid' if defined?(Mongoid)
|
20
|
+
require 'symmetric_encryption/extensions/mongoid/encrypted' if defined?(Mongoid)
|
21
|
+
require 'symmetric_encryption/extensions/mongo_mapper/plugins/encrypted_key' if defined?(MongoMapper)
|
@@ -23,7 +23,7 @@ module SymmetricEncryption
|
|
23
23
|
:key, # [String] Key used to encrypt the data, if supplied in the header
|
24
24
|
:cipher_name, # [String] Name of the cipher used, if supplied in the header
|
25
25
|
:version, # [Integer] Version of the cipher used, if supplied in the header
|
26
|
-
:decryption_cipher
|
26
|
+
:decryption_cipher # [SymmetricEncryption::Cipher] Cipher matching the header, or SymmetricEncryption.cipher(default_version)
|
27
27
|
)
|
28
28
|
|
29
29
|
# Generate a new Symmetric Key pair
|
@@ -36,9 +36,9 @@ module SymmetricEncryption
|
|
36
36
|
openssl_cipher.encrypt
|
37
37
|
|
38
38
|
{
|
39
|
-
:
|
40
|
-
:
|
41
|
-
:
|
39
|
+
key: openssl_cipher.random_key,
|
40
|
+
iv: openssl_cipher.random_iv,
|
41
|
+
cipher_name: cipher_name
|
42
42
|
}
|
43
43
|
end
|
44
44
|
|
@@ -42,51 +42,9 @@ module ActiveRecord #:nodoc:
|
|
42
42
|
define_attribute_methods rescue nil
|
43
43
|
|
44
44
|
options = params.last.is_a?(Hash) ? params.pop.dup : {}
|
45
|
-
random_iv = options.delete(:random_iv) || false
|
46
|
-
compress = options.delete(:compress) || false
|
47
|
-
type = options.delete(:type) || :string
|
48
|
-
|
49
|
-
raise "Invalid type: #{type.inspect}. Valid types: #{SymmetricEncryption::COERCION_TYPES.inspect}" unless SymmetricEncryption::COERCION_TYPES.include?(type)
|
50
|
-
|
51
|
-
# For backward compatibility
|
52
|
-
if options.delete(:marshal) == true
|
53
|
-
warn("The :marshal option has been deprecated in favor of :type. For example: attr_encrypted name, :type => :yaml")
|
54
|
-
raise "Marshal is depreacted and cannot be used in conjunction with :type, just use :type. For #{params.inspect}" if type != :string
|
55
|
-
type = :yaml
|
56
|
-
end
|
57
|
-
|
58
|
-
options.each {|option| warn "Ignoring unknown option #{option.inspect} supplied to attr_encrypted with #{params.inspect}"}
|
59
|
-
|
60
|
-
if const_defined?(:EncryptedAttributes, _search_ancestors = false)
|
61
|
-
mod = const_get(:EncryptedAttributes)
|
62
|
-
else
|
63
|
-
mod = const_set(:EncryptedAttributes, Module.new)
|
64
|
-
include mod
|
65
|
-
end
|
66
45
|
|
67
46
|
params.each do |attribute|
|
68
|
-
|
69
|
-
mod.module_eval(<<-UNENCRYPTED, __FILE__, __LINE__ + 1)
|
70
|
-
# Returns the decrypted value for the encrypted attribute
|
71
|
-
# The decrypted value is cached and is only decrypted if the encrypted value has changed
|
72
|
-
# If this method is not called, then the encrypted value is never decrypted
|
73
|
-
def #{attribute}
|
74
|
-
if @stored_encrypted_#{attribute} != self.encrypted_#{attribute}
|
75
|
-
@#{attribute} = ::SymmetricEncryption.decrypt(self.encrypted_#{attribute},version=nil,:#{type}).freeze
|
76
|
-
@stored_encrypted_#{attribute} = self.encrypted_#{attribute}
|
77
|
-
end
|
78
|
-
@#{attribute}
|
79
|
-
end
|
80
|
-
|
81
|
-
# Set the un-encrypted attribute
|
82
|
-
# Also updates the encrypted field with the encrypted value
|
83
|
-
def #{attribute}=(value)
|
84
|
-
v = SymmetricEncryption::coerce(value, :#{type})
|
85
|
-
self.encrypted_#{attribute} = @stored_encrypted_#{attribute} = ::SymmetricEncryption.encrypt(v,#{random_iv},#{compress},:#{type})
|
86
|
-
@#{attribute} = v.freeze
|
87
|
-
end
|
88
|
-
UNENCRYPTED
|
89
|
-
|
47
|
+
SymmetricEncryption::Generator.generate_decrypted_accessors(self, attribute, "encrypted_#{attribute}", options)
|
90
48
|
encrypted_attributes[attribute.to_sym] = "encrypted_#{attribute}".to_sym
|
91
49
|
end
|
92
50
|
end
|
@@ -100,7 +58,7 @@ module ActiveRecord #:nodoc:
|
|
100
58
|
# attr_encrypted :email
|
101
59
|
# end
|
102
60
|
#
|
103
|
-
# User.encrypted_attributes
|
61
|
+
# User.encrypted_attributes => { email: encrypted_email }
|
104
62
|
def encrypted_attributes
|
105
63
|
@encrypted_attributes ||= superclass.respond_to?(:encrypted_attributes) ? superclass.encrypted_attributes.dup : {}
|
106
64
|
end
|
@@ -180,8 +138,10 @@ module ActiveRecord #:nodoc:
|
|
180
138
|
method_missing_without_attr_encrypted(method, *args, &block)
|
181
139
|
end
|
182
140
|
|
183
|
-
|
184
|
-
|
141
|
+
# Dynamic finders dropped in Rails 4.1
|
142
|
+
if ActiveRecord::VERSION::STRING.to_f < 4.1
|
143
|
+
alias_method_chain :method_missing, :attr_encrypted
|
144
|
+
end
|
185
145
|
end
|
186
146
|
end
|
187
147
|
end
|