attr_keyring 0.6.1 → 0.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/.github/workflows/tests.yml +6 -3
- data/README.md +15 -0
- data/gemfiles/6_1.gemfile +5 -0
- data/lib/attr_keyring/active_record.rb +1 -1
- data/lib/attr_keyring/encoders/json_encoder.rb +15 -0
- data/lib/attr_keyring/version.rb +1 -1
- data/lib/attr_keyring.rb +16 -5
- data/lib/keyring/encryptor/aes.rb +4 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a1335e867e0b79f0f8082b6cceaa30e40feeb7a9cb140dbb133989ad47af66f
|
4
|
+
data.tar.gz: fa5803034ce08ff55f515fc87e774eeb16b96597e229f55266bfdafd51225dd0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1d2bc02c88a3871191cc41e32707452f1df9c50040991a8b09394d06a7a06d83a84b3574ac2e1e291e41cb8525d190213e31066eb9922440bbbe3426271829eb
|
7
|
+
data.tar.gz: '00086d53fd3bd74cc0ab4a1e5b511b02ddb081dc01531df75999461200c15b5e87069e0b38eb62f5c353ed121cb8f4657ec1e130aebfc0d254528a9365896389'
|
data/.github/workflows/tests.yml
CHANGED
@@ -4,6 +4,8 @@ name: Tests
|
|
4
4
|
on:
|
5
5
|
pull_request:
|
6
6
|
push:
|
7
|
+
workflow_dispatch:
|
8
|
+
inputs: {}
|
7
9
|
|
8
10
|
jobs:
|
9
11
|
build:
|
@@ -12,9 +14,10 @@ jobs:
|
|
12
14
|
strategy:
|
13
15
|
fail-fast: false
|
14
16
|
matrix:
|
15
|
-
ruby: ["2.7", "3.0"]
|
17
|
+
ruby: ["2.7", "3.0", "3.1"]
|
16
18
|
gemfile:
|
17
19
|
- gemfiles/7_0.gemfile
|
20
|
+
- gemfiles/6_1.gemfile
|
18
21
|
- gemfiles/6_0.gemfile
|
19
22
|
|
20
23
|
services:
|
@@ -26,9 +29,9 @@ jobs:
|
|
26
29
|
--health-retries 5
|
27
30
|
|
28
31
|
steps:
|
29
|
-
- uses: actions/checkout@
|
32
|
+
- uses: actions/checkout@v3.0.2
|
30
33
|
|
31
|
-
- uses: actions/cache@
|
34
|
+
- uses: actions/cache@v3.0.1
|
32
35
|
with:
|
33
36
|
path: vendor/bundle
|
34
37
|
key: >
|
data/README.md
CHANGED
@@ -144,6 +144,21 @@ user.encrypted_email
|
|
144
144
|
#=> WG8Epo0ABz0Z1X5gX7kttc98w9Ei59B5uXGK36Zin9G0VqbxX3naOWOm4RI6w6Uu
|
145
145
|
```
|
146
146
|
|
147
|
+
If you want to store a hash, you can use the `encoder:` option.
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
class User < ApplicationRecord
|
151
|
+
attr_keyring ENV["USER_KEYRING"],
|
152
|
+
digest_salt: "<custom salt>"
|
153
|
+
|
154
|
+
attr_encrypt :data, encoder: JSON
|
155
|
+
end
|
156
|
+
```
|
157
|
+
|
158
|
+
An encoder is just an object that responds to the methods `dump(data)` and
|
159
|
+
`parse(data)`, just like the `JSON` interface. Alternatively, you can use
|
160
|
+
`AttrKeyring::Encoders::JSON`, which returns hashes with symbolized keys.
|
161
|
+
|
147
162
|
### Encryption
|
148
163
|
|
149
164
|
By default, AES-128-CBC is the algorithm used for encryption. This algorithm
|
data/lib/attr_keyring/version.rb
CHANGED
data/lib/attr_keyring.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
module AttrKeyring
|
4
4
|
require "attr_keyring/version"
|
5
5
|
require "keyring"
|
6
|
+
require "attr_keyring/encoders/json_encoder"
|
6
7
|
|
7
8
|
def self.active_record
|
8
9
|
require "attr_keyring/active_record"
|
@@ -23,7 +24,7 @@ module AttrKeyring
|
|
23
24
|
attr_accessor :encrypted_attributes, :keyring, :keyring_column_name
|
24
25
|
end
|
25
26
|
|
26
|
-
self.encrypted_attributes =
|
27
|
+
self.encrypted_attributes = {}
|
27
28
|
self.keyring = Keyring.new({}, digest_salt: "")
|
28
29
|
self.keyring_column_name = :keyring_id
|
29
30
|
end
|
@@ -42,11 +43,12 @@ module AttrKeyring
|
|
42
43
|
self.keyring = Keyring.new(keyring, options)
|
43
44
|
end
|
44
45
|
|
45
|
-
def attr_encrypt(*attributes)
|
46
|
-
self.encrypted_attributes ||=
|
47
|
-
encrypted_attributes.push(*attributes)
|
46
|
+
def attr_encrypt(*attributes, encoder: nil)
|
47
|
+
self.encrypted_attributes ||= {}
|
48
48
|
|
49
49
|
attributes.each do |attribute|
|
50
|
+
encrypted_attributes[attribute.to_sym] = {encoder: encoder}
|
51
|
+
|
50
52
|
define_attr_encrypt_writer(attribute)
|
51
53
|
define_attr_encrypt_reader(attribute)
|
52
54
|
end
|
@@ -70,6 +72,8 @@ module AttrKeyring
|
|
70
72
|
clear_decrypted_column_cache(attribute)
|
71
73
|
return reset_encrypted_column(attribute) unless encryptable_value?(value)
|
72
74
|
|
75
|
+
encoder = self.class.encrypted_attributes[attribute][:encoder]
|
76
|
+
value = encoder.dump(value) if encoder
|
73
77
|
value = value.to_s
|
74
78
|
|
75
79
|
previous_keyring_id = public_send(self.class.keyring_column_name)
|
@@ -86,6 +90,7 @@ module AttrKeyring
|
|
86
90
|
|
87
91
|
private def attr_decrypt_column(attribute)
|
88
92
|
cache_name = :"@#{attribute}"
|
93
|
+
|
89
94
|
if instance_variable_defined?(cache_name)
|
90
95
|
return instance_variable_get(cache_name)
|
91
96
|
end
|
@@ -99,6 +104,9 @@ module AttrKeyring
|
|
99
104
|
public_send(self.class.keyring_column_name)
|
100
105
|
)
|
101
106
|
|
107
|
+
encoder = self.class.encrypted_attributes[attribute][:encoder]
|
108
|
+
decrypted_value = encoder.parse(decrypted_value) if encoder
|
109
|
+
|
102
110
|
instance_variable_set(cache_name, decrypted_value)
|
103
111
|
end
|
104
112
|
|
@@ -123,10 +131,13 @@ module AttrKeyring
|
|
123
131
|
|
124
132
|
keyring_id = self.class.keyring.current_key.id
|
125
133
|
|
126
|
-
self.class.encrypted_attributes.each do |attribute|
|
134
|
+
self.class.encrypted_attributes.each do |attribute, options|
|
127
135
|
value = public_send(attribute)
|
128
136
|
next unless encryptable_value?(value)
|
129
137
|
|
138
|
+
encoder = options[:encoder]
|
139
|
+
value = encoder.dump(value) if encoder
|
140
|
+
|
130
141
|
encrypted_value, _, digest = self.class.keyring.encrypt(value)
|
131
142
|
|
132
143
|
public_send("encrypted_#{attribute}=", encrypted_value)
|
@@ -38,7 +38,10 @@ module Keyring
|
|
38
38
|
expected_hmac = hmac_digest(key.signing_key, encrypted_payload)
|
39
39
|
|
40
40
|
unless verify_signature(expected_hmac, hmac)
|
41
|
-
raise InvalidAuthentication,
|
41
|
+
raise InvalidAuthentication,
|
42
|
+
"Expected HMAC to be " \
|
43
|
+
"#{Base64.strict_encode64(expected_hmac)}; " \
|
44
|
+
"got #{Base64.strict_encode64(hmac)} instead"
|
42
45
|
end
|
43
46
|
|
44
47
|
cipher.iv = iv
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attr_keyring
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nando Vieira
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-07-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -204,9 +204,11 @@ files:
|
|
204
204
|
- examples/keyring_sample.rb
|
205
205
|
- examples/sequel_sample.rb
|
206
206
|
- gemfiles/6_0.gemfile
|
207
|
+
- gemfiles/6_1.gemfile
|
207
208
|
- gemfiles/7_0.gemfile
|
208
209
|
- lib/attr_keyring.rb
|
209
210
|
- lib/attr_keyring/active_record.rb
|
211
|
+
- lib/attr_keyring/encoders/json_encoder.rb
|
210
212
|
- lib/attr_keyring/sequel.rb
|
211
213
|
- lib/attr_keyring/version.rb
|
212
214
|
- lib/keyring.rb
|
@@ -231,7 +233,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
231
233
|
- !ruby/object:Gem::Version
|
232
234
|
version: '0'
|
233
235
|
requirements: []
|
234
|
-
rubygems_version: 3.
|
236
|
+
rubygems_version: 3.3.7
|
235
237
|
signing_key:
|
236
238
|
specification_version: 4
|
237
239
|
summary: Simple encryption-at-rest plugin for ActiveRecord.
|