attr_encrypted 1.3.5 → 2.0.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 +7 -0
- checksums.yaml.gz.sig +1 -0
- data/.gitignore +6 -0
- data/.travis.yml +24 -0
- data/CHANGELOG.md +71 -0
- data/Gemfile +3 -0
- data/README.md +420 -0
- data/Rakefile +3 -15
- data/attr_encrypted.gemspec +60 -0
- data/certs/saghaulor.pem +21 -0
- data/lib/attr_encrypted/adapters/active_record.rb +22 -9
- data/lib/attr_encrypted/adapters/data_mapper.rb +1 -0
- data/lib/attr_encrypted/adapters/sequel.rb +1 -0
- data/lib/attr_encrypted/version.rb +3 -3
- data/lib/attr_encrypted.rb +197 -114
- data/test/active_record_test.rb +55 -18
- data/test/attr_encrypted_test.rb +101 -39
- data/test/compatibility_test.rb +19 -36
- data/test/data_mapper_test.rb +1 -1
- data/test/legacy_active_record_test.rb +11 -7
- data/test/legacy_attr_encrypted_test.rb +17 -16
- data/test/legacy_compatibility_test.rb +21 -30
- data/test/legacy_data_mapper_test.rb +6 -3
- data/test/legacy_sequel_test.rb +8 -4
- data/test/run.sh +12 -52
- data/test/sequel_test.rb +1 -1
- data/test/test_helper.rb +27 -17
- data.tar.gz.sig +0 -0
- metadata +92 -84
- metadata.gz.sig +2 -0
- data/README.rdoc +0 -344
metadata
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: attr_encrypted
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
5
|
-
prerelease:
|
|
4
|
+
version: 2.0.0
|
|
6
5
|
platform: ruby
|
|
7
6
|
authors:
|
|
8
7
|
- Sean Huber
|
|
@@ -11,204 +10,202 @@ authors:
|
|
|
11
10
|
- Stephen Aghaulor
|
|
12
11
|
autorequire:
|
|
13
12
|
bindir: bin
|
|
14
|
-
cert_chain:
|
|
15
|
-
|
|
13
|
+
cert_chain:
|
|
14
|
+
- |
|
|
15
|
+
-----BEGIN CERTIFICATE-----
|
|
16
|
+
MIIDdDCCAlygAwIBAgIBATANBgkqhkiG9w0BAQUFADBAMRIwEAYDVQQDDAlzYWdo
|
|
17
|
+
YXVsb3IxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
|
|
18
|
+
bTAeFw0xNjAxMTEyMjQyMDFaFw0xNzAxMTAyMjQyMDFaMEAxEjAQBgNVBAMMCXNh
|
|
19
|
+
Z2hhdWxvcjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYD
|
|
20
|
+
Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx0xdQYk2GwCpQ1n/
|
|
21
|
+
n2mPVYHLYqU5TAn/82t5kbqBUWjbcj8tHAi41tJ19+fT/hH0dog8JHvho1zmOr71
|
|
22
|
+
ZIqreJQo60TqP6oE9a5HncUpjqbRp7tOmHo9E+mOW1yT4NiXqFf1YINExQKy2XND
|
|
23
|
+
WPQ+T50ZNUsGMfHFWB4NAymejRWXlOEY3bvKW0UHFeNmouP5he51TjoP8uCc9536
|
|
24
|
+
4AIWVP/zzzjwrFtC7av7nRw4Y+gX2bQjrkK2k2JS0ejiGzKBIEMJejcI2B+t79zT
|
|
25
|
+
kUQq9SFwp2BrKSIy+4kh4CiF20RT/Hfc1MbvTxSIl/bbIxCYEOhmtHExHi0CoCWs
|
|
26
|
+
YCGCXQIDAQABo3kwdzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU
|
|
27
|
+
SCpVzSBvYbO6B3oT3n3RCZmurG8wHgYDVR0RBBcwFYETc2FnaGF1bG9yQGdtYWls
|
|
28
|
+
LmNvbTAeBgNVHRIEFzAVgRNzYWdoYXVsb3JAZ21haWwuY29tMA0GCSqGSIb3DQEB
|
|
29
|
+
BQUAA4IBAQAeiGdC3e0WiZpm0cF/b7JC6hJYXC9Yv9VsRAWD9ROsLjFKwOhmonnc
|
|
30
|
+
+l/QrmoTjMakYXBCai/Ca3L+k5eRrKilgyITILsmmFxK8sqPJXUw2Jmwk/dAky6x
|
|
31
|
+
hHKVZAofT1OrOOPJ2USoZyhR/VI8epLaD5wUmkVDNqtZWviW+dtRa55aPYjRw5Pj
|
|
32
|
+
wuj9nybhZr+BbEbmZE//2nbfkM4hCuMtxxxilPrJ22aYNmeWU0wsPpDyhPYxOUgU
|
|
33
|
+
ZjeLmnSDiwL6doiP5IiwALH/dcHU67ck3NGf6XyqNwQrrmtPY0mv1WVVL4Uh+vYE
|
|
34
|
+
kHoFzE2no0BfBg78Re8fY69P5yES5ncC
|
|
35
|
+
-----END CERTIFICATE-----
|
|
36
|
+
date: 2016-02-23 00:00:00.000000000 Z
|
|
16
37
|
dependencies:
|
|
17
38
|
- !ruby/object:Gem::Dependency
|
|
18
39
|
name: encryptor
|
|
19
40
|
requirement: !ruby/object:Gem::Requirement
|
|
20
|
-
none: false
|
|
21
41
|
requirements:
|
|
22
|
-
- - ~>
|
|
42
|
+
- - "~>"
|
|
23
43
|
- !ruby/object:Gem::Version
|
|
24
|
-
version:
|
|
44
|
+
version: 2.0.0
|
|
25
45
|
type: :runtime
|
|
26
46
|
prerelease: false
|
|
27
47
|
version_requirements: !ruby/object:Gem::Requirement
|
|
28
|
-
none: false
|
|
29
48
|
requirements:
|
|
30
|
-
- - ~>
|
|
49
|
+
- - "~>"
|
|
31
50
|
- !ruby/object:Gem::Version
|
|
32
|
-
version:
|
|
51
|
+
version: 2.0.0
|
|
33
52
|
- !ruby/object:Gem::Dependency
|
|
34
53
|
name: activerecord
|
|
35
54
|
requirement: !ruby/object:Gem::Requirement
|
|
36
|
-
none: false
|
|
37
55
|
requirements:
|
|
38
|
-
- -
|
|
56
|
+
- - ">="
|
|
39
57
|
- !ruby/object:Gem::Version
|
|
40
58
|
version: 2.0.0
|
|
41
59
|
type: :development
|
|
42
60
|
prerelease: false
|
|
43
61
|
version_requirements: !ruby/object:Gem::Requirement
|
|
44
|
-
none: false
|
|
45
62
|
requirements:
|
|
46
|
-
- -
|
|
63
|
+
- - ">="
|
|
47
64
|
- !ruby/object:Gem::Version
|
|
48
65
|
version: 2.0.0
|
|
49
66
|
- !ruby/object:Gem::Dependency
|
|
50
|
-
name:
|
|
67
|
+
name: actionpack
|
|
51
68
|
requirement: !ruby/object:Gem::Requirement
|
|
52
|
-
none: false
|
|
53
69
|
requirements:
|
|
54
|
-
- -
|
|
70
|
+
- - ">="
|
|
55
71
|
- !ruby/object:Gem::Version
|
|
56
|
-
version:
|
|
72
|
+
version: 2.0.0
|
|
57
73
|
type: :development
|
|
58
74
|
prerelease: false
|
|
59
75
|
version_requirements: !ruby/object:Gem::Requirement
|
|
60
|
-
none: false
|
|
61
76
|
requirements:
|
|
62
|
-
- -
|
|
77
|
+
- - ">="
|
|
63
78
|
- !ruby/object:Gem::Version
|
|
64
|
-
version:
|
|
79
|
+
version: 2.0.0
|
|
65
80
|
- !ruby/object:Gem::Dependency
|
|
66
81
|
name: datamapper
|
|
67
82
|
requirement: !ruby/object:Gem::Requirement
|
|
68
|
-
none: false
|
|
69
83
|
requirements:
|
|
70
|
-
- -
|
|
84
|
+
- - ">="
|
|
71
85
|
- !ruby/object:Gem::Version
|
|
72
86
|
version: '0'
|
|
73
87
|
type: :development
|
|
74
88
|
prerelease: false
|
|
75
89
|
version_requirements: !ruby/object:Gem::Requirement
|
|
76
|
-
none: false
|
|
77
90
|
requirements:
|
|
78
|
-
- -
|
|
91
|
+
- - ">="
|
|
79
92
|
- !ruby/object:Gem::Version
|
|
80
93
|
version: '0'
|
|
81
94
|
- !ruby/object:Gem::Dependency
|
|
82
|
-
name:
|
|
95
|
+
name: rake
|
|
83
96
|
requirement: !ruby/object:Gem::Requirement
|
|
84
|
-
none: false
|
|
85
97
|
requirements:
|
|
86
|
-
- -
|
|
98
|
+
- - ">="
|
|
87
99
|
- !ruby/object:Gem::Version
|
|
88
|
-
version:
|
|
100
|
+
version: '0'
|
|
89
101
|
type: :development
|
|
90
102
|
prerelease: false
|
|
91
103
|
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
-
none: false
|
|
93
104
|
requirements:
|
|
94
|
-
- -
|
|
105
|
+
- - ">="
|
|
95
106
|
- !ruby/object:Gem::Version
|
|
96
|
-
version:
|
|
107
|
+
version: '0'
|
|
97
108
|
- !ruby/object:Gem::Dependency
|
|
98
|
-
name:
|
|
109
|
+
name: minitest
|
|
99
110
|
requirement: !ruby/object:Gem::Requirement
|
|
100
|
-
none: false
|
|
101
111
|
requirements:
|
|
102
|
-
- -
|
|
112
|
+
- - ">="
|
|
103
113
|
- !ruby/object:Gem::Version
|
|
104
|
-
version:
|
|
114
|
+
version: '0'
|
|
105
115
|
type: :development
|
|
106
116
|
prerelease: false
|
|
107
117
|
version_requirements: !ruby/object:Gem::Requirement
|
|
108
|
-
none: false
|
|
109
118
|
requirements:
|
|
110
|
-
- -
|
|
119
|
+
- - ">="
|
|
111
120
|
- !ruby/object:Gem::Version
|
|
112
|
-
version:
|
|
121
|
+
version: '0'
|
|
113
122
|
- !ruby/object:Gem::Dependency
|
|
114
123
|
name: sequel
|
|
115
124
|
requirement: !ruby/object:Gem::Requirement
|
|
116
|
-
none: false
|
|
117
125
|
requirements:
|
|
118
|
-
- -
|
|
126
|
+
- - ">="
|
|
119
127
|
- !ruby/object:Gem::Version
|
|
120
128
|
version: '0'
|
|
121
129
|
type: :development
|
|
122
130
|
prerelease: false
|
|
123
131
|
version_requirements: !ruby/object:Gem::Requirement
|
|
124
|
-
none: false
|
|
125
132
|
requirements:
|
|
126
|
-
- -
|
|
133
|
+
- - ">="
|
|
127
134
|
- !ruby/object:Gem::Version
|
|
128
135
|
version: '0'
|
|
129
136
|
- !ruby/object:Gem::Dependency
|
|
130
137
|
name: sqlite3
|
|
131
138
|
requirement: !ruby/object:Gem::Requirement
|
|
132
|
-
none: false
|
|
133
139
|
requirements:
|
|
134
|
-
- -
|
|
140
|
+
- - ">="
|
|
135
141
|
- !ruby/object:Gem::Version
|
|
136
142
|
version: '0'
|
|
137
143
|
type: :development
|
|
138
144
|
prerelease: false
|
|
139
145
|
version_requirements: !ruby/object:Gem::Requirement
|
|
140
|
-
none: false
|
|
141
146
|
requirements:
|
|
142
|
-
- -
|
|
147
|
+
- - ">="
|
|
143
148
|
- !ruby/object:Gem::Version
|
|
144
149
|
version: '0'
|
|
145
150
|
- !ruby/object:Gem::Dependency
|
|
146
151
|
name: dm-sqlite-adapter
|
|
147
152
|
requirement: !ruby/object:Gem::Requirement
|
|
148
|
-
none: false
|
|
149
153
|
requirements:
|
|
150
|
-
- -
|
|
154
|
+
- - ">="
|
|
151
155
|
- !ruby/object:Gem::Version
|
|
152
156
|
version: '0'
|
|
153
157
|
type: :development
|
|
154
158
|
prerelease: false
|
|
155
159
|
version_requirements: !ruby/object:Gem::Requirement
|
|
156
|
-
none: false
|
|
157
160
|
requirements:
|
|
158
|
-
- -
|
|
161
|
+
- - ">="
|
|
159
162
|
- !ruby/object:Gem::Version
|
|
160
163
|
version: '0'
|
|
161
164
|
- !ruby/object:Gem::Dependency
|
|
162
|
-
name:
|
|
165
|
+
name: simplecov
|
|
163
166
|
requirement: !ruby/object:Gem::Requirement
|
|
164
|
-
none: false
|
|
165
167
|
requirements:
|
|
166
|
-
- -
|
|
168
|
+
- - ">="
|
|
167
169
|
- !ruby/object:Gem::Version
|
|
168
|
-
version: 0
|
|
170
|
+
version: '0'
|
|
169
171
|
type: :development
|
|
170
172
|
prerelease: false
|
|
171
173
|
version_requirements: !ruby/object:Gem::Requirement
|
|
172
|
-
none: false
|
|
173
174
|
requirements:
|
|
174
|
-
- -
|
|
175
|
+
- - ">="
|
|
175
176
|
- !ruby/object:Gem::Version
|
|
176
|
-
version: 0
|
|
177
|
+
version: '0'
|
|
177
178
|
- !ruby/object:Gem::Dependency
|
|
178
|
-
name: simplecov
|
|
179
|
+
name: simplecov-rcov
|
|
179
180
|
requirement: !ruby/object:Gem::Requirement
|
|
180
|
-
none: false
|
|
181
181
|
requirements:
|
|
182
|
-
- -
|
|
182
|
+
- - ">="
|
|
183
183
|
- !ruby/object:Gem::Version
|
|
184
184
|
version: '0'
|
|
185
185
|
type: :development
|
|
186
186
|
prerelease: false
|
|
187
187
|
version_requirements: !ruby/object:Gem::Requirement
|
|
188
|
-
none: false
|
|
189
188
|
requirements:
|
|
190
|
-
- -
|
|
189
|
+
- - ">="
|
|
191
190
|
- !ruby/object:Gem::Version
|
|
192
191
|
version: '0'
|
|
193
192
|
- !ruby/object:Gem::Dependency
|
|
194
|
-
name:
|
|
193
|
+
name: codeclimate-test-reporter
|
|
195
194
|
requirement: !ruby/object:Gem::Requirement
|
|
196
|
-
none: false
|
|
197
195
|
requirements:
|
|
198
|
-
- -
|
|
196
|
+
- - ">="
|
|
199
197
|
- !ruby/object:Gem::Version
|
|
200
198
|
version: '0'
|
|
201
199
|
type: :development
|
|
202
200
|
prerelease: false
|
|
203
201
|
version_requirements: !ruby/object:Gem::Requirement
|
|
204
|
-
none: false
|
|
205
202
|
requirements:
|
|
206
|
-
- -
|
|
203
|
+
- - ">="
|
|
207
204
|
- !ruby/object:Gem::Version
|
|
208
205
|
version: '0'
|
|
209
206
|
description: Generates attr_accessors that encrypt and decrypt attributes transparently
|
|
210
207
|
email:
|
|
211
|
-
- shuber
|
|
208
|
+
- seah@shuber.io
|
|
212
209
|
- sbfaulkner@gmail.com
|
|
213
210
|
- billy.monk@gmail.com
|
|
214
211
|
- saghaulor@gmail.com
|
|
@@ -216,14 +213,20 @@ executables: []
|
|
|
216
213
|
extensions: []
|
|
217
214
|
extra_rdoc_files: []
|
|
218
215
|
files:
|
|
216
|
+
- ".gitignore"
|
|
217
|
+
- ".travis.yml"
|
|
218
|
+
- CHANGELOG.md
|
|
219
|
+
- Gemfile
|
|
220
|
+
- MIT-LICENSE
|
|
221
|
+
- README.md
|
|
222
|
+
- Rakefile
|
|
223
|
+
- attr_encrypted.gemspec
|
|
224
|
+
- certs/saghaulor.pem
|
|
225
|
+
- lib/attr_encrypted.rb
|
|
219
226
|
- lib/attr_encrypted/adapters/active_record.rb
|
|
220
227
|
- lib/attr_encrypted/adapters/data_mapper.rb
|
|
221
228
|
- lib/attr_encrypted/adapters/sequel.rb
|
|
222
229
|
- lib/attr_encrypted/version.rb
|
|
223
|
-
- lib/attr_encrypted.rb
|
|
224
|
-
- MIT-LICENSE
|
|
225
|
-
- Rakefile
|
|
226
|
-
- README.rdoc
|
|
227
230
|
- test/active_record_test.rb
|
|
228
231
|
- test/attr_encrypted_test.rb
|
|
229
232
|
- test/compatibility_test.rb
|
|
@@ -238,31 +241,36 @@ files:
|
|
|
238
241
|
- test/test_helper.rb
|
|
239
242
|
homepage: http://github.com/attr-encrypted/attr_encrypted
|
|
240
243
|
licenses: []
|
|
241
|
-
|
|
244
|
+
metadata: {}
|
|
245
|
+
post_install_message: |2+
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
WARNING: Several insecure default options and features have been deprecated in attr_encrypted v2.0.0. Please see the README for more details.
|
|
250
|
+
|
|
251
|
+
|
|
242
252
|
rdoc_options:
|
|
243
|
-
- --line-numbers
|
|
244
|
-
- --inline-source
|
|
245
|
-
- --main
|
|
253
|
+
- "--line-numbers"
|
|
254
|
+
- "--inline-source"
|
|
255
|
+
- "--main"
|
|
246
256
|
- README.rdoc
|
|
247
257
|
require_paths:
|
|
248
258
|
- lib
|
|
249
259
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
250
|
-
none: false
|
|
251
260
|
requirements:
|
|
252
|
-
- -
|
|
261
|
+
- - ">="
|
|
253
262
|
- !ruby/object:Gem::Version
|
|
254
|
-
version:
|
|
263
|
+
version: 2.0.0
|
|
255
264
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
256
|
-
none: false
|
|
257
265
|
requirements:
|
|
258
|
-
- -
|
|
266
|
+
- - ">="
|
|
259
267
|
- !ruby/object:Gem::Version
|
|
260
268
|
version: '0'
|
|
261
269
|
requirements: []
|
|
262
270
|
rubyforge_project:
|
|
263
|
-
rubygems_version:
|
|
271
|
+
rubygems_version: 2.4.5.1
|
|
264
272
|
signing_key:
|
|
265
|
-
specification_version:
|
|
273
|
+
specification_version: 4
|
|
266
274
|
summary: Encrypt and decrypt attributes
|
|
267
275
|
test_files:
|
|
268
276
|
- test/active_record_test.rb
|
metadata.gz.sig
ADDED
data/README.rdoc
DELETED
|
@@ -1,344 +0,0 @@
|
|
|
1
|
-
= attr_encrypted {<img src="https://travis-ci.org/attr-encrypted/attr_encrypted.png" />}[https://travis-ci.org/attr-encrypted/attr_encrypted]
|
|
2
|
-
|
|
3
|
-
Generates attr_accessors that encrypt and decrypt attributes transparently
|
|
4
|
-
|
|
5
|
-
It works with ANY class, however, you get a few extra features when you're using it with <tt>ActiveRecord</tt>, <tt>DataMapper</tt>, or <tt>Sequel</tt>
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
== Installation
|
|
9
|
-
|
|
10
|
-
gem install attr_encrypted
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
== Usage
|
|
14
|
-
|
|
15
|
-
=== Basic
|
|
16
|
-
|
|
17
|
-
Encrypting attributes has never been easier:
|
|
18
|
-
|
|
19
|
-
class User
|
|
20
|
-
attr_accessor :name
|
|
21
|
-
attr_encrypted :ssn, :key => 'a secret key'
|
|
22
|
-
|
|
23
|
-
def load
|
|
24
|
-
# loads the stored data
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def save
|
|
28
|
-
# saves the :name and :encrypted_ssn attributes somewhere (e.g. filesystem, database, etc)
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
@user = User.new
|
|
33
|
-
@user.ssn = '123-45-6789'
|
|
34
|
-
@user.encrypted_ssn # returns the encrypted version of :ssn
|
|
35
|
-
@user.save
|
|
36
|
-
|
|
37
|
-
@user = User.load
|
|
38
|
-
@user.ssn # decrypts :encrypted_ssn and returns '123-45-6789'
|
|
39
|
-
|
|
40
|
-
The <tt>attr_encrypted</tt> method is also aliased as <tt>attr_encryptor</tt> to conform to Ruby's <tt>attr_</tt> naming conventions. I should have called this project <tt>attr_encryptor</tt> but it was too late when I realized it ='(.
|
|
41
|
-
|
|
42
|
-
=== Adding required columns via database migration
|
|
43
|
-
|
|
44
|
-
By default, <tt>attr_encrypted</tt> uses the <tt>:single_iv_and_salt</tt>
|
|
45
|
-
encryption mode for compatibility with previous versions of the gem. This mode
|
|
46
|
-
uses a single IV and salt for each encrypted column. Create or modify your model
|
|
47
|
-
to add a column with the <tt>encrypted_</tt> prefix (which can be modified, see
|
|
48
|
-
below), e.g. <tt>encrypted_ssn</tt> via a migration like the following:
|
|
49
|
-
|
|
50
|
-
create_table :users do |t|
|
|
51
|
-
t.string :name
|
|
52
|
-
t.string :encrypted_ssn
|
|
53
|
-
t.timestamps
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
For enhanced security, you can use the <tt>:per_attribute_iv_and_salt</tt> mode.
|
|
57
|
-
This requires additional <tt>_salt</tt> and <tt>_iv</tt> columns with the
|
|
58
|
-
<tt>encrypted_</tt> prefix as follows and generates a unique salt and IV per
|
|
59
|
-
attribute:
|
|
60
|
-
|
|
61
|
-
create_table :users do |t|
|
|
62
|
-
t.string :name
|
|
63
|
-
t.string :encrypted_ssn
|
|
64
|
-
t.string :encrypted_ssn_salt
|
|
65
|
-
t.string :encrypted_ssn_iv
|
|
66
|
-
t.string :domain
|
|
67
|
-
t.timestamps
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
This mode is enabled by specifying a value of <tt>:per_attribute_iv_and_salt</tt>
|
|
71
|
-
via the <tt>:mode</tt> option as follows:
|
|
72
|
-
|
|
73
|
-
class User
|
|
74
|
-
attr_accessor :name
|
|
75
|
-
attr_encrypted :ssn, :key => 'a secret key', :mode => :per_attribute_iv_and_salt
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
Note that there are alternatives to storing the IV and salt in separate columns:
|
|
79
|
-
for example, see here[https://github.com/attr-encrypted/attr_encrypted/issues/118#issuecomment-45806629].
|
|
80
|
-
Note that migration from the old encryption scheme to the new is nontrivial. One
|
|
81
|
-
approach is described here[http://jjasonclark.com/switching_from_attr_encrypted_to_attr_encryptor],
|
|
82
|
-
though these instructions describe the now-defunct <tt>attr_encryptor</tt> gem
|
|
83
|
-
whose functionality has been merged into this project.
|
|
84
|
-
|
|
85
|
-
=== Specifying the encrypted attribute name
|
|
86
|
-
|
|
87
|
-
By default, the encrypted attribute name is <tt>encrypted_#{attribute}</tt> (e.g. <tt>attr_encrypted :email</tt> would create an attribute named <tt>encrypted_email</tt>). So, if you're storing the encrypted attribute in the database, you need to make sure the <tt>encrypted_#{attribute}</tt> field exists in your table. You have a couple of options if you want to name your attribute something else.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
==== The <tt>:attribute</tt> option
|
|
91
|
-
|
|
92
|
-
You can simply pass the name of the encrypted attribute as the <tt>:attribute</tt> option:
|
|
93
|
-
|
|
94
|
-
class User
|
|
95
|
-
attr_encrypted :email, :key => 'a secret key', :attribute => 'email_encrypted'
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
This would generate an attribute named <tt>email_encrypted</tt>
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
==== The <tt>:prefix</tt> and <tt>:suffix</tt> options
|
|
102
|
-
|
|
103
|
-
If you're planning on encrypting a few different attributes and you don't like the <tt>encrypted_#{attribute}</tt> naming convention then you can specify your own:
|
|
104
|
-
|
|
105
|
-
class User
|
|
106
|
-
attr_encrypted :email, :credit_card, :ssn, :key => 'a secret key', :prefix => 'secret_', :suffix => '_crypted'
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
This would generate the following attributes: <tt>secret_email_crypted</tt>, <tt>secret_credit_card_crypted</tt>, and <tt>secret_ssn_crypted</tt>.
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
=== Encryption keys
|
|
113
|
-
|
|
114
|
-
Although a <tt>:key</tt> option may not be required (see custom encryptor below), it has a few special features
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
==== Unique keys for each attribute
|
|
118
|
-
|
|
119
|
-
You can specify unique keys for each attribute if you'd like:
|
|
120
|
-
|
|
121
|
-
class User
|
|
122
|
-
attr_encrypted :email, :key => 'a secret key'
|
|
123
|
-
attr_encrypted :ssn, :key => 'a different secret key'
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
==== Symbols representing instance methods as keys
|
|
128
|
-
|
|
129
|
-
If your class has an instance method that determines the encryption key to use, simply pass a symbol representing it like so:
|
|
130
|
-
|
|
131
|
-
class User
|
|
132
|
-
attr_encrypted :email, :key => :encryption_key
|
|
133
|
-
|
|
134
|
-
def encryption_key
|
|
135
|
-
# does some fancy logic and returns an encryption key
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
==== Procs as keys
|
|
141
|
-
|
|
142
|
-
You can pass a proc/lambda object as the <tt>:key</tt> option as well:
|
|
143
|
-
|
|
144
|
-
class User
|
|
145
|
-
attr_encrypted :email, :key => proc { |user| user.key }
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
This can be used to create asymmetrical encryption by requiring users to provide their own encryption keys.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
=== Conditional encrypting
|
|
152
|
-
|
|
153
|
-
There may be times that you want to only encrypt when certain conditions are met. For example maybe you're using rails and you don't want to encrypt
|
|
154
|
-
attributes when you're in development mode. You can specify conditions like this:
|
|
155
|
-
|
|
156
|
-
class User < ActiveRecord::Base
|
|
157
|
-
attr_encrypted :email, :key => 'a secret key', :unless => Rails.env.development?
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
You can specify both <tt>:if</tt> and <tt>:unless</tt> options. If you pass a symbol representing an instance method then the result of the method will be evaluated. Any objects that respond to <tt>:call</tt> are evaluated as well.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
=== Custom encryptor
|
|
164
|
-
|
|
165
|
-
The <tt>Encryptor</tt> (see http://github.com/shuber/encryptor) class is used by default. You may use your own custom encryptor by specifying
|
|
166
|
-
the <tt>:encryptor</tt>, <tt>:encrypt_method</tt>, and <tt>:decrypt_method</tt> options
|
|
167
|
-
|
|
168
|
-
Lets suppose you'd like to use this custom encryptor class:
|
|
169
|
-
|
|
170
|
-
class SillyEncryptor
|
|
171
|
-
def self.silly_encrypt(options)
|
|
172
|
-
(options[:value] + options[:secret_key]).reverse
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
def self.silly_decrypt(options)
|
|
176
|
-
options[:value].reverse.gsub(/#{options[:secret_key]}$/, '')
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
Simply set up your class like so:
|
|
181
|
-
|
|
182
|
-
class User
|
|
183
|
-
attr_encrypted :email, :secret_key => 'a secret key', :encryptor => SillyEncryptor, :encrypt_method => :silly_encrypt, :decrypt_method => :silly_decrypt
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
Any options that you pass to <tt>attr_encrypted</tt> will be passed to the encryptor along with the <tt>:value</tt> option which contains the string to encrypt/decrypt. Notice it uses <tt>:secret_key</tt> instead of <tt>:key</tt>.
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
=== Custom algorithms
|
|
190
|
-
|
|
191
|
-
The default <tt>Encryptor</tt> uses the standard ruby OpenSSL library. It's default algorithm is <tt>aes-256-cbc</tt>. You can modify this by passing the <tt>:algorithm</tt> option to the <tt>attr_encrypted</tt> call like so:
|
|
192
|
-
|
|
193
|
-
class User
|
|
194
|
-
attr_encrypted :email, :key => 'a secret key', :algorithm => 'bf'
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
Run <tt>openssl list-cipher-commands</tt> to view a list of algorithms supported on your platform. See http://github.com/shuber/encryptor for more information.
|
|
198
|
-
|
|
199
|
-
aes-128-cbc
|
|
200
|
-
aes-128-ecb
|
|
201
|
-
aes-192-cbc
|
|
202
|
-
aes-192-ecb
|
|
203
|
-
aes-256-cbc
|
|
204
|
-
aes-256-ecb
|
|
205
|
-
base64
|
|
206
|
-
bf
|
|
207
|
-
bf-cbc
|
|
208
|
-
bf-cfb
|
|
209
|
-
bf-ecb
|
|
210
|
-
bf-ofb
|
|
211
|
-
cast
|
|
212
|
-
cast-cbc
|
|
213
|
-
cast5-cbc
|
|
214
|
-
cast5-cfb
|
|
215
|
-
cast5-ecb
|
|
216
|
-
cast5-ofb
|
|
217
|
-
des
|
|
218
|
-
des-cbc
|
|
219
|
-
des-cfb
|
|
220
|
-
des-ecb
|
|
221
|
-
des-ede
|
|
222
|
-
des-ede-cbc
|
|
223
|
-
des-ede-cfb
|
|
224
|
-
des-ede-ofb
|
|
225
|
-
des-ede3
|
|
226
|
-
des-ede3-cbc
|
|
227
|
-
des-ede3-cfb
|
|
228
|
-
des-ede3-ofb
|
|
229
|
-
des-ofb
|
|
230
|
-
des3
|
|
231
|
-
desx
|
|
232
|
-
idea
|
|
233
|
-
idea-cbc
|
|
234
|
-
idea-cfb
|
|
235
|
-
idea-ecb
|
|
236
|
-
idea-ofb
|
|
237
|
-
rc2
|
|
238
|
-
rc2-40-cbc
|
|
239
|
-
rc2-64-cbc
|
|
240
|
-
rc2-cbc
|
|
241
|
-
rc2-cfb
|
|
242
|
-
rc2-ecb
|
|
243
|
-
rc2-ofb
|
|
244
|
-
rc4
|
|
245
|
-
rc4-40
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
=== Default options
|
|
249
|
-
|
|
250
|
-
Let's imagine that you have a few attributes that you want to encrypt with different keys, but you don't like the <tt>encrypted_#{attribute}</tt> naming convention. Instead of having to define your class like this:
|
|
251
|
-
|
|
252
|
-
class User
|
|
253
|
-
attr_encrypted :email, :key => 'a secret key', :prefix => '', :suffix => '_crypted'
|
|
254
|
-
attr_encrypted :ssn, :key => 'a different secret key', :prefix => '', :suffix => '_crypted'
|
|
255
|
-
attr_encrypted :credit_card, :key => 'another secret key', :prefix => '', :suffix => '_crypted'
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
You can simply define some default options like so:
|
|
259
|
-
|
|
260
|
-
class User
|
|
261
|
-
attr_encrypted_options.merge!(:prefix => '', :suffix => '_crypted')
|
|
262
|
-
attr_encrypted :email, :key => 'a secret key'
|
|
263
|
-
attr_encrypted :ssn, :key => 'a different secret key'
|
|
264
|
-
attr_encrypted :credit_card, :key => 'another secret key'
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
This should help keep your classes clean and DRY.
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
=== Encoding
|
|
271
|
-
|
|
272
|
-
You're probably going to be storing your encrypted attributes somehow (e.g. filesystem, database, etc) and may run into some issues trying to store a weird
|
|
273
|
-
encrypted string. I've had this problem myself using MySQL. You can simply pass the <tt>:encode</tt> option to automatically encode/decode when encrypting/decrypting.
|
|
274
|
-
|
|
275
|
-
class User
|
|
276
|
-
attr_encrypted :email, :key => 'some secret key', :encode => true
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
The default encoding is <tt>m*</tt> (base64). You can change this by setting <tt>:encode => 'some encoding'</tt>. See the <tt>Array#pack</tt> method at http://www.ruby-doc.org/core/classes/Array.html#M002245 for more encoding options.
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
=== Marshaling
|
|
283
|
-
|
|
284
|
-
You may want to encrypt objects other than strings (e.g. hashes, arrays, etc). If this is the case, simply pass the <tt>:marshal</tt> option to automatically marshal when encrypting/decrypting.
|
|
285
|
-
|
|
286
|
-
class User
|
|
287
|
-
attr_encrypted :credentials, :key => 'some secret key', :marshal => true
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
You may also optionally specify <tt>:marshaler</tt>, <tt>:dump_method</tt>, and <tt>:load_method</tt> if you want to use something other than the default <tt>Marshal</tt> object.
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
=== Encrypt/decrypt attribute methods
|
|
294
|
-
|
|
295
|
-
If you use the same key to encrypt every record (per attribute) like this:
|
|
296
|
-
|
|
297
|
-
class User
|
|
298
|
-
attr_encrypted :email, :key => 'a secret key'
|
|
299
|
-
end
|
|
300
|
-
|
|
301
|
-
Then you'll have these two class methods available for each attribute: <tt>User.encrypt_email(email_to_encrypt)</tt> and <tt>User.decrypt_email(email_to_decrypt)</tt>. This can be useful when you're using <tt>ActiveRecord</tt> (see below).
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
=== ActiveRecord
|
|
305
|
-
|
|
306
|
-
If you're using this gem with <tt>ActiveRecord</tt>, you get a few extra features:
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
==== Default options
|
|
310
|
-
|
|
311
|
-
For your convenience, the <tt>:encode</tt> option is set to true by default since you'll be storing everything in a database.
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
==== Dynamic find_by_ and scoped_by_ methods
|
|
315
|
-
|
|
316
|
-
Let's say you'd like to encrypt your user's email addresses, but you also need a way for them to login. Simply set up your class like so:
|
|
317
|
-
|
|
318
|
-
class User < ActiveRecord::Base
|
|
319
|
-
attr_encrypted :email, :key => 'a secret key'
|
|
320
|
-
attr_encrypted :password, :key => 'some other secret key'
|
|
321
|
-
end
|
|
322
|
-
|
|
323
|
-
You can now lookup and login users like so:
|
|
324
|
-
|
|
325
|
-
User.find_by_email_and_password('test@example.com', 'testing')
|
|
326
|
-
|
|
327
|
-
The call to <tt>find_by_email_and_password</tt> is intercepted and modified to <tt>find_by_encrypted_email_and_encrypted_password('ENCRYPTED EMAIL', 'ENCRYPTED PASSWORD')</tt>. The dynamic scope methods like <tt>scoped_by_email_and_password</tt> work the same way.
|
|
328
|
-
|
|
329
|
-
NOTE: This only works if all records are encrypted with the same encryption key (per attribute).
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
=== DataMapper and Sequel
|
|
333
|
-
|
|
334
|
-
Just like the default options for <tt>ActiveRecord</tt>, the <tt>:encode</tt> option is set to true by default since you'll be storing everything in a database.
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
== Note on Patches/Pull Requests
|
|
338
|
-
|
|
339
|
-
* Fork the project.
|
|
340
|
-
* Make your feature addition or bug fix.
|
|
341
|
-
* Add tests for it. This is important so I don't break it in a
|
|
342
|
-
future version unintentionally.
|
|
343
|
-
* Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
|
344
|
-
* Send me a pull request. Bonus points for topic branches.
|