crypt_keeper 1.1.1 → 2.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -8
- data/Appraisals +5 -0
- data/README.md +35 -10
- data/crypt_keeper.gemspec +2 -1
- data/gemfiles/activerecord_5_0.gemfile +8 -0
- data/gemfiles/activerecord_5_1.gemfile +2 -2
- data/lib/crypt_keeper.rb +1 -1
- data/lib/crypt_keeper/helper.rb +1 -0
- data/lib/crypt_keeper/model.rb +1 -1
- data/lib/crypt_keeper/provider/active_support.rb +51 -0
- data/lib/crypt_keeper/provider/mysql_aes_new.rb +1 -1
- data/lib/crypt_keeper/provider/postgres_pgp.rb +1 -1
- data/lib/crypt_keeper/provider/postgres_pgp_public_key.rb +1 -1
- data/lib/crypt_keeper/version.rb +1 -1
- data/spec/crypt_keeper/model_spec.rb +5 -5
- data/spec/crypt_keeper/provider/active_support_spec.rb +37 -0
- metadata +11 -22
- data/lib/crypt_keeper/provider/aes_new.rb +0 -53
- data/spec/crypt_keeper/provider/aes_new_spec.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 177d3771b01336174fdcc4db5f237335f8f206cd
|
4
|
+
data.tar.gz: 5f0f53fd0e3fcae45bae65fa63276067e651682c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cbce4c1e8e9665441bc3660542eb83c34efb66894ed0be3888ab03860831067a6d275bef837df62636278056524c4aae2522ef26479502815f3a5313c42fa9d1
|
7
|
+
data.tar.gz: 81429db29edfea6bdcfd6934926dec0c3f84e79268017d056c9351fcbeeaf00f2f29a5506f3100cd428321e438fda081c72d5ced47b88229d84a8ff860102999
|
data/.travis.yml
CHANGED
@@ -1,19 +1,15 @@
|
|
1
1
|
language: ruby
|
2
2
|
|
3
3
|
rvm:
|
4
|
-
- 2.
|
5
|
-
- 2.
|
6
|
-
- 2.
|
4
|
+
- 2.2.7
|
5
|
+
- 2.3.4
|
6
|
+
- 2.4.1
|
7
7
|
|
8
8
|
gemfile:
|
9
9
|
- gemfiles/activerecord_4_2.gemfile
|
10
|
+
- gemfiles/activerecord_5_0.gemfile
|
10
11
|
- gemfiles/activerecord_5_1.gemfile
|
11
12
|
|
12
|
-
matrix:
|
13
|
-
exclude:
|
14
|
-
- gemfile: gemfiles/activerecord_5_1.gemfile
|
15
|
-
rvm: 2.1.10
|
16
|
-
|
17
13
|
addons:
|
18
14
|
postgresql: 9.3
|
19
15
|
|
data/Appraisals
CHANGED
data/README.md
CHANGED
@@ -15,7 +15,7 @@ is a simple class that does 3 things.
|
|
15
15
|
Note: Any options defined using `crypt_keeper` will be passed to `new` as a
|
16
16
|
hash.
|
17
17
|
|
18
|
-
You can see an
|
18
|
+
You can see an example [here](https://github.com/jmazzi/crypt_keeper/blob/master/lib/crypt_keeper/provider/active_support.rb).
|
19
19
|
|
20
20
|
## Why?
|
21
21
|
|
@@ -27,7 +27,7 @@ simple that *just works*.
|
|
27
27
|
|
28
28
|
```ruby
|
29
29
|
class MyModel < ActiveRecord::Base
|
30
|
-
crypt_keeper :field, :other_field, :
|
30
|
+
crypt_keeper :field, :other_field, encryptor: :active_support, key: 'super_good_password', salt: 'salt'
|
31
31
|
end
|
32
32
|
|
33
33
|
model = MyModel.new(field: 'sometext')
|
@@ -53,7 +53,7 @@ You can force an encoding on the plaintext before encryption and after decryptio
|
|
53
53
|
|
54
54
|
```ruby
|
55
55
|
class MyModel < ActiveRecord::Base
|
56
|
-
crypt_keeper :field, :other_field, :
|
56
|
+
crypt_keeper :field, :other_field, encryptor: :active_support, key: 'super_good_password', salt: 'salt', encoding: 'UTF-8'
|
57
57
|
end
|
58
58
|
|
59
59
|
model = MyModel.new(field: 'Tromsø')
|
@@ -68,7 +68,7 @@ If you are working with an existing table you would like to encrypt, you must us
|
|
68
68
|
|
69
69
|
```ruby
|
70
70
|
class MyExistingModel < ActiveRecord::Base
|
71
|
-
crypt_keeper :field, :other_field, :
|
71
|
+
crypt_keeper :field, :other_field, encryptor: :active_support, key: 'super_good_password', salt: 'salt'
|
72
72
|
end
|
73
73
|
|
74
74
|
MyExistingModel.encrypt_table!
|
@@ -78,10 +78,10 @@ Running `encrypt_table!` will encrypt all rows in the database using the encrypt
|
|
78
78
|
|
79
79
|
## Supported Available Encryptors
|
80
80
|
|
81
|
-
There are four supported encryptors: `
|
81
|
+
There are four supported encryptors: `active_support`, `mysql_aes_new`, `postgres_pgp`, `postgres_pgp_public_key`.
|
82
82
|
|
83
|
-
* [
|
84
|
-
* Encryption is
|
83
|
+
* [ActiveSupport](https://github.com/jmazzi/crypt_keeper/blob/master/lib/crypt_keeper/provider/active_support.rb)
|
84
|
+
* Encryption is performed using [ActiveSupport::MessageEncryptor](http://api.rubyonrails.org/classes/ActiveSupport/MessageEncryptor.html)
|
85
85
|
* Passphrases are derived using [PBKDF2](http://en.wikipedia.org/wiki/PBKDF2)
|
86
86
|
|
87
87
|
* [MySQL AES New](https://github.com/jmazzi/crypt_keeper/blob/master/lib/crypt_keeper/provider/mysql_aes_new.rb)
|
@@ -111,8 +111,8 @@ There are four supported encryptors: `aes_new`, `mysql_aes_new`, `postgres_pgp`,
|
|
111
111
|
## Searching
|
112
112
|
Searching ciphertext is a complex problem that varies depending on the encryption algorithm you choose. All of the bundled providers include search support, but they have some caveats.
|
113
113
|
|
114
|
-
*
|
115
|
-
*
|
114
|
+
* ActiveSupport::MessageEncryptor
|
115
|
+
* ActiveSupport's MessageEncryptor uses a random initialization vector when generating keys. The same plaintext encrypted multiple times will have different output each time for the ciphertext. Since this is the case, it is not possible to search leveraging the database. Database rows will need to be filtered in memory. It is suggested that you use a scope or ActiveRecord batches to narrow the results before seaching them.
|
116
116
|
|
117
117
|
* Mysql AES
|
118
118
|
* Surprisingly, MySQL's implementation of AES does not use a random initialization vector. The column containing the ciphertext can be indexed and searched quickly.
|
@@ -157,10 +157,35 @@ as a string or an underscored symbol
|
|
157
157
|
|
158
158
|
```ruby
|
159
159
|
class MyModel < ActiveRecord::Base
|
160
|
-
crypt_keeper :field, :other_field, :
|
160
|
+
crypt_keeper :field, :other_field, encryptor: :my_encryptor, key: 'super_good_password'
|
161
161
|
end
|
162
162
|
```
|
163
163
|
|
164
|
+
## Migrating from CryptKeeper 1.x to 2.0
|
165
|
+
|
166
|
+
CryptKeeper 2.0 removes the AES encryptor due to security issues in the
|
167
|
+
underlying AES gem. If you were previously using the `aes_new` encryptor, you
|
168
|
+
will need to follow these instructions to reencrypt your data.
|
169
|
+
|
170
|
+
The general migration path is as follows:
|
171
|
+
|
172
|
+
1. Enable maintenance mode in any live apps
|
173
|
+
2. Backup database
|
174
|
+
3. Decrypt tables: TableName.decrypt_table!
|
175
|
+
4. Update to 2.0.0.rc1 in your app. Update the encryptor to use :active_support
|
176
|
+
5. Encrypt tables: `TableName.encrypt_table!`
|
177
|
+
6. Verify data can be decrypted: `TableName.first`
|
178
|
+
7. Disable maintenance mode if necessary
|
179
|
+
|
180
|
+
In case you experience problems, the rollback procedure is as follows:
|
181
|
+
|
182
|
+
1. Enable maintenance mode
|
183
|
+
2. Backup database again
|
184
|
+
3. Restore first database dump, from before CryptKeeper 2.0.0.rc1
|
185
|
+
4. Verify data can be decrypted
|
186
|
+
5. Disable maintenance mode
|
187
|
+
6. Let us know what happened :(
|
188
|
+
|
164
189
|
## Requirements
|
165
190
|
|
166
191
|
CryptKeeper has been tested against ActiveRecord 4.2 and 5.0 using Ruby
|
data/crypt_keeper.gemspec
CHANGED
@@ -16,9 +16,10 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.require_paths = ["lib"]
|
17
17
|
gem.version = CryptKeeper::VERSION
|
18
18
|
|
19
|
+
gem.post_install_message = "WARNING: CryptKeeper 2.0 contains breaking changes and may require you to reencrypt your data! Please view the README at https://github.com/jmazzi/crypt_keeper for more information."
|
20
|
+
|
19
21
|
gem.add_runtime_dependency 'activerecord', '>= 4.2', '< 5.2'
|
20
22
|
gem.add_runtime_dependency 'activesupport', '>= 4.2', '< 5.2'
|
21
|
-
gem.add_runtime_dependency 'aes', '~> 0.5.0'
|
22
23
|
gem.add_runtime_dependency 'armor', '~> 0.0.2'
|
23
24
|
|
24
25
|
gem.add_development_dependency 'rspec', '~> 3.5.0'
|
data/lib/crypt_keeper.rb
CHANGED
@@ -4,7 +4,7 @@ require 'crypt_keeper/version'
|
|
4
4
|
require 'crypt_keeper/model'
|
5
5
|
require 'crypt_keeper/helper'
|
6
6
|
require 'crypt_keeper/provider/base'
|
7
|
-
require 'crypt_keeper/provider/
|
7
|
+
require 'crypt_keeper/provider/active_support'
|
8
8
|
require 'crypt_keeper/provider/mysql_aes_new'
|
9
9
|
require 'crypt_keeper/provider/postgres_base'
|
10
10
|
require 'crypt_keeper/provider/postgres_pgp'
|
data/lib/crypt_keeper/helper.rb
CHANGED
data/lib/crypt_keeper/model.rb
CHANGED
@@ -3,7 +3,7 @@ require 'active_support/core_ext/array/extract_options'
|
|
3
3
|
|
4
4
|
module CryptKeeper
|
5
5
|
module Model
|
6
|
-
extend ActiveSupport::Concern
|
6
|
+
extend ::ActiveSupport::Concern
|
7
7
|
|
8
8
|
# Public: Ensures that each field exist and is of type text. This prevents
|
9
9
|
# encrypted data from being truncated.
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require "active_support/message_encryptor"
|
2
|
+
|
3
|
+
module CryptKeeper
|
4
|
+
module Provider
|
5
|
+
class ActiveSupport < Base
|
6
|
+
attr_reader :encryptor
|
7
|
+
|
8
|
+
# Public: Initializes the encryptor
|
9
|
+
#
|
10
|
+
# options - A hash, :key and :salt are required
|
11
|
+
#
|
12
|
+
# Returns nothing.
|
13
|
+
def initialize(options = {})
|
14
|
+
key = options.fetch(:key)
|
15
|
+
salt = options.fetch(:salt)
|
16
|
+
|
17
|
+
@encryptor = ::ActiveSupport::MessageEncryptor.new \
|
18
|
+
::ActiveSupport::KeyGenerator.new(key).generate_key(salt, 32)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Public: Encrypts a string
|
22
|
+
#
|
23
|
+
# value - Plaintext value
|
24
|
+
#
|
25
|
+
# Returns an encrypted string
|
26
|
+
def encrypt(value)
|
27
|
+
encryptor.encrypt_and_sign(value)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Public: Decrypts a string
|
31
|
+
#
|
32
|
+
# value - Cipher text
|
33
|
+
#
|
34
|
+
# Returns a plaintext string
|
35
|
+
def decrypt(value)
|
36
|
+
encryptor.decrypt_and_verify(value)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Public: Searches the table
|
40
|
+
#
|
41
|
+
# records - ActiveRecord::Relation
|
42
|
+
# field - Field name to match
|
43
|
+
# criteria - Value to match
|
44
|
+
#
|
45
|
+
# Returns an Enumerable
|
46
|
+
def search(records, field, criteria)
|
47
|
+
records.select { |record| record[field] == criteria }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -12,7 +12,7 @@ module CryptKeeper
|
|
12
12
|
#
|
13
13
|
# options - A hash, :key and :salt are required
|
14
14
|
def initialize(options = {})
|
15
|
-
ActiveSupport.run_load_hooks(:crypt_keeper_mysql_aes_log, self)
|
15
|
+
::ActiveSupport.run_load_hooks(:crypt_keeper_mysql_aes_log, self)
|
16
16
|
@key = digest_passphrase(options[:key], options[:salt])
|
17
17
|
end
|
18
18
|
|
@@ -8,7 +8,7 @@ module CryptKeeper
|
|
8
8
|
#
|
9
9
|
# options - A hash, :key is required
|
10
10
|
def initialize(options = {})
|
11
|
-
ActiveSupport.run_load_hooks(:crypt_keeper_postgres_pgp_log, self)
|
11
|
+
::ActiveSupport.run_load_hooks(:crypt_keeper_postgres_pgp_log, self)
|
12
12
|
|
13
13
|
@key = options.fetch(:key) do
|
14
14
|
raise ArgumentError, "Missing :key"
|
@@ -4,7 +4,7 @@ module CryptKeeper
|
|
4
4
|
attr_accessor :key
|
5
5
|
|
6
6
|
def initialize(options = {})
|
7
|
-
ActiveSupport.run_load_hooks(:crypt_keeper_postgres_pgp_log, self)
|
7
|
+
::ActiveSupport.run_load_hooks(:crypt_keeper_postgres_pgp_log, self)
|
8
8
|
|
9
9
|
@key = options.fetch(:key) do
|
10
10
|
raise ArgumentError, "Missing :key"
|
data/lib/crypt_keeper/version.rb
CHANGED
@@ -120,7 +120,7 @@ describe CryptKeeper::Model do
|
|
120
120
|
end
|
121
121
|
|
122
122
|
context "Encodings" do
|
123
|
-
subject { create_encrypted_model :storage, key: 'tool', salt: 'salt', encryptor: :
|
123
|
+
subject { create_encrypted_model :storage, key: 'tool', salt: 'salt', encryptor: :active_support, encoding: 'utf-8' }
|
124
124
|
|
125
125
|
it "forces the encoding on decrypt" do
|
126
126
|
record = subject.create!(storage: 'Tromsø')
|
@@ -137,7 +137,7 @@ describe CryptKeeper::Model do
|
|
137
137
|
end
|
138
138
|
|
139
139
|
context "Initial Table Encryption" do
|
140
|
-
subject { create_encrypted_model :storage, key: 'tool', salt: 'salt', encryptor: :
|
140
|
+
subject { create_encrypted_model :storage, key: 'tool', salt: 'salt', encryptor: :active_support }
|
141
141
|
|
142
142
|
before do
|
143
143
|
subject.delete_all
|
@@ -146,14 +146,14 @@ describe CryptKeeper::Model do
|
|
146
146
|
end
|
147
147
|
|
148
148
|
it "encrypts the table" do
|
149
|
-
expect { subject.first(5).map(&:storage) }.to raise_error(
|
149
|
+
expect { subject.first(5).map(&:storage) }.to raise_error(ActiveSupport::MessageVerifier::InvalidSignature)
|
150
150
|
subject.encrypt_table!
|
151
151
|
expect { subject.first(5).map(&:storage) }.not_to raise_error
|
152
152
|
end
|
153
153
|
end
|
154
154
|
|
155
155
|
context "Table Decryption (Reverse of Initial Table Encryption)" do
|
156
|
-
subject { create_encrypted_model :storage, key: 'tool', salt: 'salt', encryptor: :
|
156
|
+
subject { create_encrypted_model :storage, key: 'tool', salt: 'salt', encryptor: :active_support }
|
157
157
|
let!(:storage_entries) { 5.times.map { |i| "testing#{i}" } }
|
158
158
|
|
159
159
|
before do
|
@@ -168,7 +168,7 @@ describe CryptKeeper::Model do
|
|
168
168
|
end
|
169
169
|
|
170
170
|
context "Missing Attributes" do
|
171
|
-
subject { create_encrypted_model :storage, key: 'tool', salt: 'salt', encryptor: :
|
171
|
+
subject { create_encrypted_model :storage, key: 'tool', salt: 'salt', encryptor: :active_support, encoding: 'utf-8' }
|
172
172
|
|
173
173
|
it "doesn't attempt decryption of missing attributes" do
|
174
174
|
subject.create!(storage: 'blah')
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CryptKeeper::Provider::ActiveSupport do
|
4
|
+
subject { described_class.new(key: 'cake', salt: 'salt') }
|
5
|
+
|
6
|
+
let :plaintext do
|
7
|
+
"string"
|
8
|
+
end
|
9
|
+
|
10
|
+
let :encrypted do
|
11
|
+
subject.encrypt plaintext
|
12
|
+
end
|
13
|
+
|
14
|
+
let :decrypted do
|
15
|
+
subject.decrypt encrypted
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#encrypt" do
|
19
|
+
specify { expect(encrypted).to_not eq(plaintext) }
|
20
|
+
specify { expect(encrypted).to_not be_blank }
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#decrypt" do
|
24
|
+
specify { expect(decrypted).to eq(plaintext) }
|
25
|
+
specify { expect(decrypted).to_not be_blank }
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#search" do
|
29
|
+
let :records do
|
30
|
+
[{ name: 'Bob' }, { name: 'Tim' }]
|
31
|
+
end
|
32
|
+
|
33
|
+
it "finds the matching record" do
|
34
|
+
expect(subject.search(records, :name, 'Bob')).to eql([records.first])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crypt_keeper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Mazzi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-12-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -50,20 +50,6 @@ dependencies:
|
|
50
50
|
- - "<"
|
51
51
|
- !ruby/object:Gem::Version
|
52
52
|
version: '5.2'
|
53
|
-
- !ruby/object:Gem::Dependency
|
54
|
-
name: aes
|
55
|
-
requirement: !ruby/object:Gem::Requirement
|
56
|
-
requirements:
|
57
|
-
- - "~>"
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
version: 0.5.0
|
60
|
-
type: :runtime
|
61
|
-
prerelease: false
|
62
|
-
version_requirements: !ruby/object:Gem::Requirement
|
63
|
-
requirements:
|
64
|
-
- - "~>"
|
65
|
-
- !ruby/object:Gem::Version
|
66
|
-
version: 0.5.0
|
67
53
|
- !ruby/object:Gem::Dependency
|
68
54
|
name: armor
|
69
55
|
requirement: !ruby/object:Gem::Requirement
|
@@ -236,13 +222,14 @@ files:
|
|
236
222
|
- Rakefile
|
237
223
|
- crypt_keeper.gemspec
|
238
224
|
- gemfiles/activerecord_4_2.gemfile
|
225
|
+
- gemfiles/activerecord_5_0.gemfile
|
239
226
|
- gemfiles/activerecord_5_1.gemfile
|
240
227
|
- lib/crypt_keeper.rb
|
241
228
|
- lib/crypt_keeper/helper.rb
|
242
229
|
- lib/crypt_keeper/log_subscriber/mysql_aes.rb
|
243
230
|
- lib/crypt_keeper/log_subscriber/postgres_pgp.rb
|
244
231
|
- lib/crypt_keeper/model.rb
|
245
|
-
- lib/crypt_keeper/provider/
|
232
|
+
- lib/crypt_keeper/provider/active_support.rb
|
246
233
|
- lib/crypt_keeper/provider/base.rb
|
247
234
|
- lib/crypt_keeper/provider/mysql_aes_new.rb
|
248
235
|
- lib/crypt_keeper/provider/postgres_base.rb
|
@@ -252,7 +239,7 @@ files:
|
|
252
239
|
- spec/crypt_keeper/log_subscriber/mysql_aes_spec.rb
|
253
240
|
- spec/crypt_keeper/log_subscriber/postgres_pgp_spec.rb
|
254
241
|
- spec/crypt_keeper/model_spec.rb
|
255
|
-
- spec/crypt_keeper/provider/
|
242
|
+
- spec/crypt_keeper/provider/active_support_spec.rb
|
256
243
|
- spec/crypt_keeper/provider/mysql_aes_new_spec.rb
|
257
244
|
- spec/crypt_keeper/provider/postgres_pgp_public_key_spec.rb
|
258
245
|
- spec/crypt_keeper/provider/postgres_pgp_spec.rb
|
@@ -267,7 +254,9 @@ homepage: http://jmazzi.github.com/crypt_keeper/
|
|
267
254
|
licenses:
|
268
255
|
- MIT
|
269
256
|
metadata: {}
|
270
|
-
post_install_message:
|
257
|
+
post_install_message: 'WARNING: CryptKeeper 2.0 contains breaking changes and may
|
258
|
+
require you to reencrypt your data! Please view the README at https://github.com/jmazzi/crypt_keeper
|
259
|
+
for more information.'
|
271
260
|
rdoc_options: []
|
272
261
|
require_paths:
|
273
262
|
- lib
|
@@ -278,9 +267,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
278
267
|
version: '0'
|
279
268
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
280
269
|
requirements:
|
281
|
-
- - "
|
270
|
+
- - ">"
|
282
271
|
- !ruby/object:Gem::Version
|
283
|
-
version:
|
272
|
+
version: 1.3.1
|
284
273
|
requirements: []
|
285
274
|
rubyforge_project:
|
286
275
|
rubygems_version: 2.6.11
|
@@ -291,7 +280,7 @@ test_files:
|
|
291
280
|
- spec/crypt_keeper/log_subscriber/mysql_aes_spec.rb
|
292
281
|
- spec/crypt_keeper/log_subscriber/postgres_pgp_spec.rb
|
293
282
|
- spec/crypt_keeper/model_spec.rb
|
294
|
-
- spec/crypt_keeper/provider/
|
283
|
+
- spec/crypt_keeper/provider/active_support_spec.rb
|
295
284
|
- spec/crypt_keeper/provider/mysql_aes_new_spec.rb
|
296
285
|
- spec/crypt_keeper/provider/postgres_pgp_public_key_spec.rb
|
297
286
|
- spec/crypt_keeper/provider/postgres_pgp_spec.rb
|
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'aes'
|
2
|
-
require 'armor'
|
3
|
-
|
4
|
-
module CryptKeeper
|
5
|
-
module Provider
|
6
|
-
class AesNew < Base
|
7
|
-
include CryptKeeper::Helper::DigestPassphrase
|
8
|
-
|
9
|
-
# Public: The encryption key
|
10
|
-
attr_accessor :key
|
11
|
-
|
12
|
-
# Public: Initializes the class
|
13
|
-
#
|
14
|
-
# options - A hash of options. :key and :salt are required
|
15
|
-
def initialize(options = {})
|
16
|
-
@key = digest_passphrase(options[:key], options[:salt])
|
17
|
-
end
|
18
|
-
|
19
|
-
# Public: Encrypt a string
|
20
|
-
#
|
21
|
-
# Note: nil and empty strings are not encryptable with AES.
|
22
|
-
# When they are encountered, the orignal value is returned.
|
23
|
-
# Otherwise, returns the encrypted string
|
24
|
-
#
|
25
|
-
# Returns a String
|
26
|
-
def encrypt(value)
|
27
|
-
AES.encrypt(value, key)
|
28
|
-
end
|
29
|
-
|
30
|
-
# Public: Decrypt a string
|
31
|
-
#
|
32
|
-
# Note: nil and empty strings are not encryptable with AES (and thus cannot be decrypted).
|
33
|
-
# When they are encountered, the orignal value is returned.
|
34
|
-
# Otherwise, returns the decrypted string
|
35
|
-
#
|
36
|
-
# Returns a String
|
37
|
-
def decrypt(value)
|
38
|
-
AES.decrypt(value, key)
|
39
|
-
end
|
40
|
-
|
41
|
-
# Public: Search for a record
|
42
|
-
#
|
43
|
-
# record - An ActiveRecord collection
|
44
|
-
# field - The field to search
|
45
|
-
# criteria - A string to search with
|
46
|
-
#
|
47
|
-
# Returns an Enumerable
|
48
|
-
def search(records, field, criteria)
|
49
|
-
records.select { |record| record[field] == criteria }
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe CryptKeeper::Provider::AesNew do
|
4
|
-
subject { described_class.new(key: 'cake', salt: 'salt') }
|
5
|
-
|
6
|
-
describe "#initialize" do
|
7
|
-
let(:digested_key) do
|
8
|
-
::Armor.digest('cake', 'salt')
|
9
|
-
end
|
10
|
-
|
11
|
-
specify { expect(subject.key).to eq(digested_key) }
|
12
|
-
specify { expect { described_class.new }.to raise_error(ArgumentError, "Missing :key") }
|
13
|
-
end
|
14
|
-
|
15
|
-
describe "#encrypt" do
|
16
|
-
let(:encrypted) do
|
17
|
-
subject.encrypt 'string'
|
18
|
-
end
|
19
|
-
|
20
|
-
specify { expect(encrypted).to_not eq('string') }
|
21
|
-
specify { expect(encrypted).to_not be_blank }
|
22
|
-
end
|
23
|
-
|
24
|
-
describe "#decrypt" do
|
25
|
-
let(:decrypted) do
|
26
|
-
subject.decrypt "V02ebRU2wLk25AizasROVg==$kE+IpRaUNdBfYqR+WjMqvA=="
|
27
|
-
end
|
28
|
-
|
29
|
-
specify { expect(decrypted).to eq('string') }
|
30
|
-
end
|
31
|
-
|
32
|
-
describe "#search" do
|
33
|
-
let(:records) do
|
34
|
-
[{ name: 'Bob' }, { name: 'Tim' }]
|
35
|
-
end
|
36
|
-
|
37
|
-
it "finds the matching record" do
|
38
|
-
expect(subject.search(records, :name, 'Bob')).to eql([records.first])
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|