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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d02280da9cb28259980ea283b6030672957657ead8b895594176eef09d78382b
4
- data.tar.gz: 88ddda0bb1d9a85869246e46ab49a8f4889bc0c398d616be9dd162eec239a177
3
+ metadata.gz: 4a1335e867e0b79f0f8082b6cceaa30e40feeb7a9cb140dbb133989ad47af66f
4
+ data.tar.gz: fa5803034ce08ff55f515fc87e774eeb16b96597e229f55266bfdafd51225dd0
5
5
  SHA512:
6
- metadata.gz: 6a3108027fac7dbfee097e7afa3227f58f33560e540f19bc0f0b63cb4e482e8315ffafdbd4360bc31724426c9150109c6b9e46e9ecdf70526ca13cb34a8bee93
7
- data.tar.gz: 16a5ca41d03b434dbf2eb4a5751af6595e7d00c93867159c3990a3e1d0a104d170dfd434580eff0420b1b966afe0877ec70362c6d66cad34e89e0f5fed8867d4
6
+ metadata.gz: 1d2bc02c88a3871191cc41e32707452f1df9c50040991a8b09394d06a7a06d83a84b3574ac2e1e291e41cb8525d190213e31066eb9922440bbbe3426271829eb
7
+ data.tar.gz: '00086d53fd3bd74cc0ab4a1e5b511b02ddb081dc01531df75999461200c15b5e87069e0b38eb62f5c353ed121cb8f4657ec1e130aebfc0d254528a9365896389'
@@ -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@v1
32
+ - uses: actions/checkout@v3.0.2
30
33
 
31
- - uses: actions/cache@v2
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
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+ gemspec path: ".."
5
+ gem "activerecord", "~> 6.1.0"
@@ -21,7 +21,7 @@ module AttrKeyring
21
21
  def reload(options = nil)
22
22
  instance = super
23
23
 
24
- self.class.encrypted_attributes.each do |attribute|
24
+ self.class.encrypted_attributes.each do |attribute, _options|
25
25
  clear_decrypted_column_cache(attribute)
26
26
  end
27
27
 
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AttrKeyring
4
+ module Encoders
5
+ module JSONEncoder
6
+ def self.dump(data)
7
+ ::JSON.dump(data)
8
+ end
9
+
10
+ def self.parse(data)
11
+ ::JSON.parse(data, symbolize_names: true)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AttrKeyring
4
- VERSION = "0.6.1"
4
+ VERSION = "0.7.0"
5
5
  end
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, "Expected HMAC to be #{Base64.strict_encode64(expected_hmac)}; got #{Base64.strict_encode64(hmac)} instead" # rubocop:disable Layout/LineLength
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.6.1
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: 2021-12-11 00:00:00.000000000 Z
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.2.32
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.