attr_encrypted 3.0.3 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5c1a2bcf5e2b7fc8937e96cb0fcd99926bd98d1e
4
- data.tar.gz: 40112aef07bda5ba8145b2fb634a9bdbfea34d7a
3
+ metadata.gz: f602391484e3437daae62ddb60596f0b4cbc83e0
4
+ data.tar.gz: 5e407d7e299a43380057a2f0fe816da3a6ad1fca
5
5
  SHA512:
6
- metadata.gz: cbb4fb1d4fa7e22f791139ab1b9a96324cbb8e07f7e8472561a3dd0ce1fcb0a7c048c0ba413b5bccb876dade09f9528ccc7d23caa4378de3da8ef2c540ba76ad
7
- data.tar.gz: ef6b487235f2f92ccdf73de3c806b3b3f9161c2ebcd78b2102e1975edc3150cda28a7b458136a051100e939a271b2e92ca690cd38360ec5c43c9c33db22dc1f4
6
+ metadata.gz: 77b697d9e450d6baae65fb3ed339824b8bf730898296f172c2ae6b4e0bd7368add0da29c76596b9bbf71d298fccd038195f7ffb7d153ffaeaf2aabc7bfc60f9f
7
+ data.tar.gz: 211f1c52e7f0505d55eef59f06bb139f47fb1ae0158b39a643b5c7c5251865f13b871ab7b3194d44cd2fc6a128e86a5c6b9c8669bab6d2870a7914ed5dacb6c3
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -6,6 +6,8 @@ rvm:
6
6
  - 2.1
7
7
  - 2.2.2
8
8
  - 2.3.0
9
+ - 2.4.0
10
+ - 2.5.0
9
11
  - rbx
10
12
  env:
11
13
  - ACTIVERECORD=3.0.0
@@ -15,14 +17,41 @@ env:
15
17
  - ACTIVERECORD=4.1.0
16
18
  - ACTIVERECORD=4.2.0
17
19
  - ACTIVERECORD=5.0.0
20
+ - ACTIVERECORD=5.1.1
18
21
  matrix:
19
22
  exclude:
20
23
  - rvm: 2.0
21
24
  env: ACTIVERECORD=5.0.0
25
+ - rvm: 2.0
26
+ env: ACTIVERECORD=5.1.1
22
27
  - rvm: 2.1
23
28
  env: ACTIVERECORD=5.0.0
29
+ - rvm: 2.1
30
+ env: ACTIVERECORD=5.1.1
31
+ - rvm: 2.4.0
32
+ env: ACTIVERECORD=3.0.0
33
+ - rvm: 2.4.0
34
+ env: ACTIVERECORD=3.1.0
35
+ - rvm: 2.4.0
36
+ env: ACTIVERECORD=3.2.0
37
+ - rvm: 2.4.0
38
+ env: ACTIVERECORD=4.0.0
39
+ - rvm: 2.4.0
40
+ env: ACTIVERECORD=4.1.0
41
+ - rvm: 2.5.0
42
+ env: ACTIVERECORD=3.0.0
43
+ - rvm: 2.5.0
44
+ env: ACTIVERECORD=3.1.0
45
+ - rvm: 2.5.0
46
+ env: ACTIVERECORD=3.2.0
47
+ - rvm: 2.5.0
48
+ env: ACTIVERECORD=4.0.0
49
+ - rvm: 2.5.0
50
+ env: ACTIVERECORD=4.1.0
24
51
  - rvm: rbx
25
52
  env: ACTIVERECORD=5.0.0
53
+ - rvm: rbx
54
+ env: ACTIVERECORD=5.1.1
26
55
  allow_failures:
27
56
  - rvm: rbx
28
57
  fast_finish: true
@@ -1,5 +1,16 @@
1
1
  # attr_encrypted #
2
2
 
3
+ ## 3.1.0 ##
4
+ * Added: Abitilty to encrypt empty values. (@tamird)
5
+ * Added: MIT license
6
+ * Added: MRI 2.5.x support (@saghaulor)
7
+ * Fixed: No long generate IV and salt if value is empty, unless :allow_empty_value options is passed. (@saghaulor)
8
+ * Fixed: Only generate IV and salt when :if and :unless options evaluate such that encryption should be performed. (@saghaulor)
9
+ * Fixed: Private methods are correctly evaluated as options. (@saghaulor)
10
+ * Fixed: Mark virtual attributes for Rails 5.x compatibility (@grosser)
11
+ * Fixed: Only check empty on strings, allows for encrypting non-string type objects
12
+ * Fixed: Fixed how accessors for db columns are defined in the ActiveRecord adapter, preventing premature definition. (@nagachika)
13
+
3
14
  ## 3.0.3 ##
4
15
  * Fixed: attr_was would decrypt the attribute upon every call. This is inefficient and introduces problems when the options change between decrypting an old value and encrypting a new value; for example, when rotating the encryption key. As such, the new approach caches the decrypted value of the old encrypted value such that the old options are no longer needed. (@johnny-lai) (@saghaulor)
5
16
 
data/README.md CHANGED
@@ -72,7 +72,7 @@ The `attr_encrypted` class method is also aliased as `attr_encryptor` to conform
72
72
 
73
73
  ### attr_encrypted with database persistence
74
74
 
75
- By default, `attr_encrypted` uses the `:per_attribute_iv` encryption mode. This mode requires a column to store your cipher text and a column to store your IV.
75
+ By default, `attr_encrypted` uses the `:per_attribute_iv` encryption mode. This mode requires a column to store your cipher text and a column to store your IV (initialization vector).
76
76
 
77
77
  Create or modify the table that your model uses to add a column with the `encrypted_` prefix (which can be modified, see below), e.g. `encrypted_ssn` via a migration like the following:
78
78
 
@@ -145,6 +145,7 @@ The following are the default options used by `attr_encrypted`:
145
145
  decrypt_method: 'decrypt',
146
146
  mode: :per_attribute_iv,
147
147
  algorithm: 'aes-256-gcm',
148
+ allow_empty_value: false
148
149
  ```
149
150
 
150
151
  All of the aforementioned options are explained in depth below.
@@ -195,7 +196,7 @@ If you don't like the `encrypted_#{attribute}` naming convention then you can sp
195
196
  end
196
197
  ```
197
198
 
198
- This would generate the following attributes: `secret_email_crypted`, `secret_credit_card_crypted`, and `secret_ssn_crypted`.
199
+ This would generate the following attribute: `secret_email_crypted`.
199
200
 
200
201
 
201
202
  ### The `:key` option
@@ -296,7 +297,7 @@ You're probably going to be storing your encrypted attributes somehow (e.g. file
296
297
  end
297
298
  ```
298
299
 
299
- The default encoding is `m` (base64). You can change this by setting `encode: 'some encoding'`. See [`Arrary#pack`](http://ruby-doc.org/core-2.3.0/Array.html#method-i-pack) for more encoding options.
300
+ The default encoding is `m` (base64). You can change this by setting `encode: 'some encoding'`. See [`Array#pack`](http://ruby-doc.org/core-2.3.0/Array.html#method-i-pack) for more encoding options.
300
301
 
301
302
 
302
303
  ### The `:marshal`, `:dump_method`, and `:load_method` options
@@ -311,6 +312,16 @@ You may want to encrypt objects other than strings (e.g. hashes, arrays, etc). I
311
312
 
312
313
  You may also optionally specify `:marshaler`, `:dump_method`, and `:load_method` if you want to use something other than the default `Marshal` object.
313
314
 
315
+ ### The `:allow_empty_value` option
316
+
317
+ You may want to encrypt empty strings or nil so as to not reveal which records are populated and which records are not.
318
+
319
+ ```ruby
320
+ class User
321
+ attr_encrypted :credentials, key: 'some secret key', marshal: true, allow_empty_value: true
322
+ end
323
+ ```
324
+
314
325
 
315
326
  ## ORMs
316
327
 
@@ -400,7 +411,7 @@ It is recommended that you implement a strategy to insure that you do not mix th
400
411
 
401
412
  ```ruby
402
413
  class User
403
- attr_encrypted :ssn, key: :encryption_key, v2_gcm_iv: :is_decrypting?(:ssn)
414
+ attr_encrypted :ssn, key: :encryption_key, v2_gcm_iv: is_decrypting?(:ssn)
404
415
 
405
416
  def is_decrypting?(attribute)
406
417
  encrypted_attributes[attribute][:operation] == :decrypting
data/Rakefile CHANGED
@@ -6,6 +6,7 @@ desc 'Test the attr_encrypted gem.'
6
6
  Rake::TestTask.new(:test) do |t|
7
7
  t.libs << 'lib'
8
8
  t.pattern = 'test/**/*_test.rb'
9
+ t.warning = false
9
10
  t.verbose = true
10
11
  end
11
12
 
@@ -17,6 +17,7 @@ Gem::Specification.new do |s|
17
17
  s.authors = ['Sean Huber', 'S. Brent Faulkner', 'William Monk', 'Stephen Aghaulor']
18
18
  s.email = ['seah@shuber.io', 'sbfaulkner@gmail.com', 'billy.monk@gmail.com', 'saghaulor@gmail.com']
19
19
  s.homepage = 'http://github.com/attr-encrypted/attr_encrypted'
20
+ s.license = 'MIT'
20
21
 
21
22
  s.has_rdoc = false
22
23
  s.rdoc_options = ['--line-numbers', '--inline-source', '--main', 'README.rdoc']
@@ -41,6 +42,10 @@ Gem::Specification.new do |s|
41
42
  s.add_development_dependency('rake')
42
43
  s.add_development_dependency('minitest')
43
44
  s.add_development_dependency('sequel')
45
+ if RUBY_VERSION < '2.1.0'
46
+ s.add_development_dependency('nokogiri', '< 1.7.0')
47
+ s.add_development_dependency('public_suffix', '< 3.0.0')
48
+ end
44
49
  if defined?(RUBY_ENGINE) && RUBY_ENGINE.to_sym == :jruby
45
50
  s.add_development_dependency('activerecord-jdbcsqlite3-adapter')
46
51
  s.add_development_dependency('jdbc-sqlite3', '< 3.8.7') # 3.8.7 is nice and broke
@@ -50,7 +55,7 @@ Gem::Specification.new do |s|
50
55
  s.add_development_dependency('dm-sqlite-adapter')
51
56
  s.add_development_dependency('simplecov')
52
57
  s.add_development_dependency('simplecov-rcov')
53
- s.add_development_dependency("codeclimate-test-reporter")
58
+ s.add_development_dependency("codeclimate-test-reporter", '<= 0.6.0')
54
59
 
55
60
  s.cert_chain = ['certs/saghaulor.pem']
56
61
  s.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/
@@ -1,21 +1,21 @@
1
1
  -----BEGIN CERTIFICATE-----
2
2
  MIIDdDCCAlygAwIBAgIBATANBgkqhkiG9w0BAQUFADBAMRIwEAYDVQQDDAlzYWdo
3
3
  YXVsb3IxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
4
- bTAeFw0xNjAxMTEyMjQyMDFaFw0xNzAxMTAyMjQyMDFaMEAxEjAQBgNVBAMMCXNh
4
+ bTAeFw0xODAyMTIwMzMzMThaFw0xOTAyMTIwMzMzMThaMEAxEjAQBgNVBAMMCXNh
5
5
  Z2hhdWxvcjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYD
6
- Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx0xdQYk2GwCpQ1n/
7
- n2mPVYHLYqU5TAn/82t5kbqBUWjbcj8tHAi41tJ19+fT/hH0dog8JHvho1zmOr71
8
- ZIqreJQo60TqP6oE9a5HncUpjqbRp7tOmHo9E+mOW1yT4NiXqFf1YINExQKy2XND
9
- WPQ+T50ZNUsGMfHFWB4NAymejRWXlOEY3bvKW0UHFeNmouP5he51TjoP8uCc9536
10
- 4AIWVP/zzzjwrFtC7av7nRw4Y+gX2bQjrkK2k2JS0ejiGzKBIEMJejcI2B+t79zT
11
- kUQq9SFwp2BrKSIy+4kh4CiF20RT/Hfc1MbvTxSIl/bbIxCYEOhmtHExHi0CoCWs
12
- YCGCXQIDAQABo3kwdzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU
13
- SCpVzSBvYbO6B3oT3n3RCZmurG8wHgYDVR0RBBcwFYETc2FnaGF1bG9yQGdtYWls
6
+ Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvOLqbSmj5txfw39a
7
+ Ki0g3BJWGrfGBiSRq9aThUGzoiaqyDo/m1WMQdgPioZG+P923okChEWFjhSymBQU
8
+ eMdys6JRPm5ortp5sh9gesOWoozqb8R55d8rr1V7pY533cCut53Kb1wiitjkfXjR
9
+ efT2HPh6nV6rYjGMJek/URaCNzsZo7HCkRsKdezP+BKr4V4wOka69tfJX5pcvFvR
10
+ iiqfaiP4RK12hYdsFnSVKiKP7SAFTFiYcohbL8TUW6ezQQqJCK0M6fu74EWVCnBS
11
+ gFVjj931BuD8qhuxMiB6uC6FKxemB5TRGBLzn7RcrOMAo2inMAopjkGeQJUAyVCm
12
+ J5US3wIDAQABo3kwdzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU
13
+ hJEuSZgvuuIhIsxQ/0pRQTBVzokwHgYDVR0RBBcwFYETc2FnaGF1bG9yQGdtYWls
14
14
  LmNvbTAeBgNVHRIEFzAVgRNzYWdoYXVsb3JAZ21haWwuY29tMA0GCSqGSIb3DQEB
15
- BQUAA4IBAQAeiGdC3e0WiZpm0cF/b7JC6hJYXC9Yv9VsRAWD9ROsLjFKwOhmonnc
16
- +l/QrmoTjMakYXBCai/Ca3L+k5eRrKilgyITILsmmFxK8sqPJXUw2Jmwk/dAky6x
17
- hHKVZAofT1OrOOPJ2USoZyhR/VI8epLaD5wUmkVDNqtZWviW+dtRa55aPYjRw5Pj
18
- wuj9nybhZr+BbEbmZE//2nbfkM4hCuMtxxxilPrJ22aYNmeWU0wsPpDyhPYxOUgU
19
- ZjeLmnSDiwL6doiP5IiwALH/dcHU67ck3NGf6XyqNwQrrmtPY0mv1WVVL4Uh+vYE
20
- kHoFzE2no0BfBg78Re8fY69P5yES5ncC
15
+ BQUAA4IBAQCsBS2cxqTmV4nXJEH/QbdgjVDAZbK6xf2gpM3vCRlYsy7Wz6GEoOpD
16
+ bzRkjxZwGNbhXShMUZwm6zahYQ/L1/HFztLoMBMkm8EIfPxH0PDrP4aWl0oyWxmU
17
+ OLm0/t9icSWRPPJ1tLJvuAaDdVpY5dEHd6VdnNJGQC5vHKRInt1kEyqEttIJ/xmJ
18
+ leSEFyMeoFsR+C/WPG9WSC+xN0eXqakCu6YUJoQzCn/7znv8WxpHEbeZjNIHq0qb
19
+ nbqZ/ZW1bwzj1T/NIbnMr37wqV29XwkI4+LbewMkb6/bDPYl0qZpAkCxKtGYCCJp
20
+ l6KPs9K/72yH00dxuAhiTXikTkcLXeQJ
21
21
  -----END CERTIFICATE-----
@@ -0,0 +1 @@
1
+ 6d84c64852c4bbc0926b92fe7a93295671a9e69cb2939b96fb1e4b5e8a5b33b6
@@ -0,0 +1 @@
1
+ 0f960e8a2f63c747c273241f7395dcceb0dd8a6f79349bee453db741fc7ea5ceb4342d7d5908e540e3b5acea2216ff38bef8c743e6e7c8559bacb4a731ab27c4
@@ -16,90 +16,93 @@ module AttrEncrypted
16
16
  #
17
17
  # Options (any other options you specify are passed to the Encryptor's encrypt and decrypt methods)
18
18
  #
19
- # attribute: The name of the referenced encrypted attribute. For example
20
- # <tt>attr_accessor :email, attribute: :ee</tt> would generate an
21
- # attribute named 'ee' to store the encrypted email. This is useful when defining
22
- # one attribute to encrypt at a time or when the :prefix and :suffix options
23
- # aren't enough.
24
- # Defaults to nil.
25
- #
26
- # prefix: A prefix used to generate the name of the referenced encrypted attributes.
27
- # For example <tt>attr_accessor :email, prefix: 'crypted_'</tt> would
28
- # generate attributes named 'crypted_email' to store the encrypted
29
- # email and password.
30
- # Defaults to 'encrypted_'.
31
- #
32
- # suffix: A suffix used to generate the name of the referenced encrypted attributes.
33
- # For example <tt>attr_accessor :email, prefix: '', suffix: '_encrypted'</tt>
34
- # would generate attributes named 'email_encrypted' to store the
35
- # encrypted email.
36
- # Defaults to ''.
37
- #
38
- # key: The encryption key. This option may not be required if
39
- # you're using a custom encryptor. If you pass a symbol
40
- # representing an instance method then the :key option
41
- # will be replaced with the result of the method before
42
- # being passed to the encryptor. Objects that respond
43
- # to :call are evaluated as well (including procs).
44
- # Any other key types will be passed directly to the encryptor.
45
- # Defaults to nil.
46
- #
47
- # encode: If set to true, attributes will be encoded as well as
48
- # encrypted. This is useful if you're planning on storing
49
- # the encrypted attributes in a database. The default
50
- # encoding is 'm' (base64), however this can be overwritten
51
- # by setting the :encode option to some other encoding
52
- # string instead of just 'true'. See
53
- # http://www.ruby-doc.org/core/classes/Array.html#M002245
54
- # for more encoding directives.
55
- # Defaults to false unless you're using it with ActiveRecord, DataMapper, or Sequel.
56
- #
57
- # encode_iv: Defaults to true.
58
-
59
- # encode_salt: Defaults to true.
60
- #
61
- # default_encoding: Defaults to 'm' (base64).
62
- #
63
- # marshal: If set to true, attributes will be marshaled as well
64
- # as encrypted. This is useful if you're planning on
65
- # encrypting something other than a string.
66
- # Defaults to false.
67
- #
68
- # marshaler: The object to use for marshaling.
69
- # Defaults to Marshal.
70
- #
71
- # dump_method: The dump method name to call on the <tt>:marshaler</tt> object to.
72
- # Defaults to 'dump'.
73
- #
74
- # load_method: The load method name to call on the <tt>:marshaler</tt> object.
75
- # Defaults to 'load'.
76
- #
77
- # encryptor: The object to use for encrypting.
78
- # Defaults to Encryptor.
79
- #
80
- # encrypt_method: The encrypt method name to call on the <tt>:encryptor</tt> object.
81
- # Defaults to 'encrypt'.
82
- #
83
- # decrypt_method: The decrypt method name to call on the <tt>:encryptor</tt> object.
84
- # Defaults to 'decrypt'.
85
- #
86
- # if: Attributes are only encrypted if this option evaluates
87
- # to true. If you pass a symbol representing an instance
88
- # method then the result of the method will be evaluated.
89
- # Any objects that respond to <tt>:call</tt> are evaluated as well.
90
- # Defaults to true.
91
- #
92
- # unless: Attributes are only encrypted if this option evaluates
93
- # to false. If you pass a symbol representing an instance
94
- # method then the result of the method will be evaluated.
95
- # Any objects that respond to <tt>:call</tt> are evaluated as well.
96
- # Defaults to false.
97
- #
98
- # mode: Selects encryption mode for attribute: choose <tt>:single_iv_and_salt</tt> for compatibility
99
- # with the old attr_encrypted API: the IV is derived from the encryption key by the underlying Encryptor class; salt is not used.
100
- # The <tt>:per_attribute_iv_and_salt</tt> mode uses a per-attribute IV and salt. The salt is used to derive a unique key per attribute.
101
- # A <tt>:per_attribute_iv</default> mode derives a unique IV per attribute; salt is not used.
102
- # Defaults to <tt>:per_attribute_iv</tt>.
19
+ # attribute: The name of the referenced encrypted attribute. For example
20
+ # <tt>attr_accessor :email, attribute: :ee</tt> would generate an
21
+ # attribute named 'ee' to store the encrypted email. This is useful when defining
22
+ # one attribute to encrypt at a time or when the :prefix and :suffix options
23
+ # aren't enough.
24
+ # Defaults to nil.
25
+ #
26
+ # prefix: A prefix used to generate the name of the referenced encrypted attributes.
27
+ # For example <tt>attr_accessor :email, prefix: 'crypted_'</tt> would
28
+ # generate attributes named 'crypted_email' to store the encrypted
29
+ # email and password.
30
+ # Defaults to 'encrypted_'.
31
+ #
32
+ # suffix: A suffix used to generate the name of the referenced encrypted attributes.
33
+ # For example <tt>attr_accessor :email, prefix: '', suffix: '_encrypted'</tt>
34
+ # would generate attributes named 'email_encrypted' to store the
35
+ # encrypted email.
36
+ # Defaults to ''.
37
+ #
38
+ # key: The encryption key. This option may not be required if
39
+ # you're using a custom encryptor. If you pass a symbol
40
+ # representing an instance method then the :key option
41
+ # will be replaced with the result of the method before
42
+ # being passed to the encryptor. Objects that respond
43
+ # to :call are evaluated as well (including procs).
44
+ # Any other key types will be passed directly to the encryptor.
45
+ # Defaults to nil.
46
+ #
47
+ # encode: If set to true, attributes will be encoded as well as
48
+ # encrypted. This is useful if you're planning on storing
49
+ # the encrypted attributes in a database. The default
50
+ # encoding is 'm' (base64), however this can be overwritten
51
+ # by setting the :encode option to some other encoding
52
+ # string instead of just 'true'. See
53
+ # http://www.ruby-doc.org/core/classes/Array.html#M002245
54
+ # for more encoding directives.
55
+ # Defaults to false unless you're using it with ActiveRecord, DataMapper, or Sequel.
56
+ #
57
+ # encode_iv: Defaults to true.
58
+
59
+ # encode_salt: Defaults to true.
60
+ #
61
+ # default_encoding: Defaults to 'm' (base64).
62
+ #
63
+ # marshal: If set to true, attributes will be marshaled as well
64
+ # as encrypted. This is useful if you're planning on
65
+ # encrypting something other than a string.
66
+ # Defaults to false.
67
+ #
68
+ # marshaler: The object to use for marshaling.
69
+ # Defaults to Marshal.
70
+ #
71
+ # dump_method: The dump method name to call on the <tt>:marshaler</tt> object to.
72
+ # Defaults to 'dump'.
73
+ #
74
+ # load_method: The load method name to call on the <tt>:marshaler</tt> object.
75
+ # Defaults to 'load'.
76
+ #
77
+ # encryptor: The object to use for encrypting.
78
+ # Defaults to Encryptor.
79
+ #
80
+ # encrypt_method: The encrypt method name to call on the <tt>:encryptor</tt> object.
81
+ # Defaults to 'encrypt'.
82
+ #
83
+ # decrypt_method: The decrypt method name to call on the <tt>:encryptor</tt> object.
84
+ # Defaults to 'decrypt'.
85
+ #
86
+ # if: Attributes are only encrypted if this option evaluates
87
+ # to true. If you pass a symbol representing an instance
88
+ # method then the result of the method will be evaluated.
89
+ # Any objects that respond to <tt>:call</tt> are evaluated as well.
90
+ # Defaults to true.
91
+ #
92
+ # unless: Attributes are only encrypted if this option evaluates
93
+ # to false. If you pass a symbol representing an instance
94
+ # method then the result of the method will be evaluated.
95
+ # Any objects that respond to <tt>:call</tt> are evaluated as well.
96
+ # Defaults to false.
97
+ #
98
+ # mode: Selects encryption mode for attribute: choose <tt>:single_iv_and_salt</tt> for compatibility
99
+ # with the old attr_encrypted API: the IV is derived from the encryption key by the underlying Encryptor class; salt is not used.
100
+ # The <tt>:per_attribute_iv_and_salt</tt> mode uses a per-attribute IV and salt. The salt is used to derive a unique key per attribute.
101
+ # A <tt>:per_attribute_iv</default> mode derives a unique IV per attribute; salt is not used.
102
+ # Defaults to <tt>:per_attribute_iv</tt>.
103
+ #
104
+ # allow_empty_value: Attributes which have nil or empty string values will not be encrypted unless this option
105
+ # has a truthy value.
103
106
  #
104
107
  # You can specify your own default options
105
108
  #
@@ -140,16 +143,19 @@ module AttrEncrypted
140
143
  encrypted_attribute_name = (options[:attribute] ? options[:attribute] : [options[:prefix], attribute, options[:suffix]].join).to_sym
141
144
 
142
145
  instance_methods_as_symbols = attribute_instance_methods_as_symbols
143
- attr_reader encrypted_attribute_name unless instance_methods_as_symbols.include?(encrypted_attribute_name)
144
- attr_writer encrypted_attribute_name unless instance_methods_as_symbols.include?(:"#{encrypted_attribute_name}=")
145
146
 
146
- iv_name = "#{encrypted_attribute_name}_iv".to_sym
147
- attr_reader iv_name unless instance_methods_as_symbols.include?(iv_name)
148
- attr_writer iv_name unless instance_methods_as_symbols.include?(:"#{iv_name}=")
147
+ if attribute_instance_methods_as_symbols_available?
148
+ attr_reader encrypted_attribute_name unless instance_methods_as_symbols.include?(encrypted_attribute_name)
149
+ attr_writer encrypted_attribute_name unless instance_methods_as_symbols.include?(:"#{encrypted_attribute_name}=")
149
150
 
150
- salt_name = "#{encrypted_attribute_name}_salt".to_sym
151
- attr_reader salt_name unless instance_methods_as_symbols.include?(salt_name)
152
- attr_writer salt_name unless instance_methods_as_symbols.include?(:"#{salt_name}=")
151
+ iv_name = "#{encrypted_attribute_name}_iv".to_sym
152
+ attr_reader iv_name unless instance_methods_as_symbols.include?(iv_name)
153
+ attr_writer iv_name unless instance_methods_as_symbols.include?(:"#{iv_name}=")
154
+
155
+ salt_name = "#{encrypted_attribute_name}_salt".to_sym
156
+ attr_reader salt_name unless instance_methods_as_symbols.include?(salt_name)
157
+ attr_writer salt_name unless instance_methods_as_symbols.include?(:"#{salt_name}=")
158
+ end
153
159
 
154
160
  define_method(attribute) do
155
161
  instance_variable_get("@#{attribute}") || instance_variable_set("@#{attribute}", decrypt(attribute, send(encrypted_attribute_name)))
@@ -197,6 +203,7 @@ module AttrEncrypted
197
203
  decrypt_method: 'decrypt',
198
204
  mode: :per_attribute_iv,
199
205
  algorithm: 'aes-256-gcm',
206
+ allow_empty_value: false,
200
207
  }
201
208
  end
202
209
 
@@ -228,7 +235,7 @@ module AttrEncrypted
228
235
  # email = User.decrypt(:email, 'SOME_ENCRYPTED_EMAIL_STRING')
229
236
  def decrypt(attribute, encrypted_value, options = {})
230
237
  options = encrypted_attributes[attribute.to_sym].merge(options)
231
- if options[:if] && !options[:unless] && !encrypted_value.nil? && !(encrypted_value.is_a?(String) && encrypted_value.empty?)
238
+ if options[:if] && !options[:unless] && not_empty?(encrypted_value)
232
239
  encrypted_value = encrypted_value.unpack(options[:encode]).first if options[:encode]
233
240
  value = options[:encryptor].send(options[:decrypt_method], options.merge!(value: encrypted_value))
234
241
  if options[:marshal]
@@ -254,7 +261,7 @@ module AttrEncrypted
254
261
  # encrypted_email = User.encrypt(:email, 'test@example.com')
255
262
  def encrypt(attribute, value, options = {})
256
263
  options = encrypted_attributes[attribute.to_sym].merge(options)
257
- if options[:if] && !options[:unless] && !value.nil? && !(value.is_a?(String) && value.empty?)
264
+ if options[:if] && !options[:unless] && (options[:allow_empty_value] || not_empty?(value))
258
265
  value = options[:marshal] ? options[:marshaler].send(options[:dump_method], value) : value.to_s
259
266
  encrypted_value = options[:encryptor].send(options[:encrypt_method], options.merge!(value: value))
260
267
  encrypted_value = [encrypted_value].pack(options[:encode]) if options[:encode]
@@ -264,6 +271,10 @@ module AttrEncrypted
264
271
  end
265
272
  end
266
273
 
274
+ def not_empty?(value)
275
+ !value.nil? && !(value.is_a?(String) && value.empty?)
276
+ end
277
+
267
278
  # Contains a hash of encrypted attributes with virtual attribute names as keys
268
279
  # and their corresponding options as values
269
280
  #
@@ -314,6 +325,7 @@ module AttrEncrypted
314
325
  # @user.decrypt(:email, 'SOME_ENCRYPTED_EMAIL_STRING')
315
326
  def decrypt(attribute, encrypted_value)
316
327
  encrypted_attributes[attribute.to_sym][:operation] = :decrypting
328
+ encrypted_attributes[attribute.to_sym][:value_present] = self.class.not_empty?(encrypted_value)
317
329
  self.class.decrypt(attribute, encrypted_value, evaluated_attr_encrypted_options_for(attribute))
318
330
  end
319
331
 
@@ -334,6 +346,7 @@ module AttrEncrypted
334
346
  # @user.encrypt(:email, 'test@example.com')
335
347
  def encrypt(attribute, value)
336
348
  encrypted_attributes[attribute.to_sym][:operation] = :encrypting
349
+ encrypted_attributes[attribute.to_sym][:value_present] = self.class.not_empty?(value)
337
350
  self.class.encrypt(attribute, value, evaluated_attr_encrypted_options_for(attribute))
338
351
  end
339
352
 
@@ -357,12 +370,14 @@ module AttrEncrypted
357
370
  evaluated_options[:attribute] = attribute_option_value
358
371
 
359
372
  evaluated_options.tap do |options|
360
- unless options[:mode] == :single_iv_and_salt
361
- load_iv_for_attribute(attribute, options)
362
- end
363
-
364
- if options[:mode] == :per_attribute_iv_and_salt
365
- load_salt_for_attribute(attribute, options)
373
+ if options[:if] && !options[:unless] && options[:value_present] || options[:allow_empty_value]
374
+ unless options[:mode] == :single_iv_and_salt
375
+ load_iv_for_attribute(attribute, options)
376
+ end
377
+
378
+ if options[:mode] == :per_attribute_iv_and_salt
379
+ load_salt_for_attribute(attribute, options)
380
+ end
366
381
  end
367
382
  end
368
383
  end
@@ -371,7 +386,7 @@ module AttrEncrypted
371
386
  #
372
387
  # If the option is not a symbol or proc then the original option is returned
373
388
  def evaluate_attr_encrypted_option(option)
374
- if option.is_a?(Symbol) && respond_to?(option)
389
+ if option.is_a?(Symbol) && respond_to?(option, true)
375
390
  send(option)
376
391
  elsif option.respond_to?(:call)
377
392
  option.call(self)
@@ -408,7 +423,7 @@ module AttrEncrypted
408
423
  encrypted_attribute_name = options[:attribute]
409
424
  encode_salt = options[:encode_salt]
410
425
  salt = options[:salt] || send("#{encrypted_attribute_name}_salt")
411
- if (salt == nil)
426
+ if options[:operation] == :encrypting
412
427
  salt = SecureRandom.random_bytes
413
428
  salt = prefix_and_encode_salt(salt, encode_salt) if encode_salt
414
429
  send("#{encrypted_attribute_name}_salt=", salt)
@@ -436,6 +451,10 @@ module AttrEncrypted
436
451
  instance_methods.collect { |method| method.to_sym }
437
452
  end
438
453
 
454
+ def attribute_instance_methods_as_symbols_available?
455
+ true
456
+ end
457
+
439
458
  end
440
459
 
441
460
 
@@ -51,6 +51,7 @@ if defined?(ActiveRecord::Base)
51
51
  super
52
52
  options = attrs.extract_options!
53
53
  attr = attrs.pop
54
+ attribute attr if ::ActiveRecord::VERSION::STRING >= "5.1.0"
54
55
  options.merge! encrypted_attributes[attr]
55
56
 
56
57
  define_method("#{attr}_was") do
@@ -87,16 +88,17 @@ if defined?(ActiveRecord::Base)
87
88
  # methods returned to let ActiveRecord define the accessor methods
88
89
  # for the db columns
89
90
 
90
- # Use with_connection so the connection doesn't stay pinned to the thread.
91
- connected = ::ActiveRecord::Base.connection_pool.with_connection(&:active?) rescue false
92
-
93
- if connected && table_exists?
91
+ if connected? && table_exists?
94
92
  columns_hash.keys.inject(super) {|instance_methods, column_name| instance_methods.concat [column_name.to_sym, :"#{column_name}="]}
95
93
  else
96
94
  super
97
95
  end
98
96
  end
99
97
 
98
+ def attribute_instance_methods_as_symbols_available?
99
+ connected? && table_exists?
100
+ end
101
+
100
102
  # Allows you to use dynamic methods like <tt>find_by_email</tt> or <tt>scoped_by_email</tt> for
101
103
  # encrypted attributes
102
104
  #
@@ -2,8 +2,8 @@ module AttrEncrypted
2
2
  # Contains information about this gem's version
3
3
  module Version
4
4
  MAJOR = 3
5
- MINOR = 0
6
- PATCH = 3
5
+ MINOR = 1
6
+ PATCH = 0
7
7
 
8
8
  # Returns a version string by joining <tt>MAJOR</tt>, <tt>MINOR</tt>, and <tt>PATCH</tt> with <tt>'.'</tt>
9
9
  #
@@ -4,6 +4,7 @@ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:'
4
4
 
5
5
  def create_tables
6
6
  ActiveRecord::Schema.define(version: 1) do
7
+ self.verbose = false
7
8
  create_table :people do |t|
8
9
  t.string :encrypted_email
9
10
  t.string :password
@@ -19,7 +20,7 @@ def create_tables
19
20
  t.string :encrypted_password
20
21
  t.string :encrypted_password_iv
21
22
  t.string :encrypted_password_salt
22
- t.binary :key
23
+ t.string :key
23
24
  end
24
25
  create_table :users do |t|
25
26
  t.string :login
@@ -40,9 +41,6 @@ def create_tables
40
41
  end
41
42
  end
42
43
 
43
- # The table needs to exist before defining the class
44
- create_tables
45
-
46
44
  ActiveRecord::MissingAttributeError = ActiveModel::MissingAttributeError unless defined?(ActiveRecord::MissingAttributeError)
47
45
 
48
46
  if ::ActiveRecord::VERSION::STRING > "4.0"
@@ -81,7 +79,7 @@ class PersonWithProcMode < Person
81
79
  end
82
80
 
83
81
  class Account < ActiveRecord::Base
84
- ACCOUNT_ENCRYPTION_KEY = SecureRandom.base64(32)
82
+ ACCOUNT_ENCRYPTION_KEY = SecureRandom.urlsafe_base64(24)
85
83
  attr_encrypted :password, key: :password_encryption_key
86
84
 
87
85
  def encrypting?(attr)
@@ -128,7 +126,7 @@ end
128
126
  class ActiveRecordTest < Minitest::Test
129
127
 
130
128
  def setup
131
- ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
129
+ drop_all_tables
132
130
  create_tables
133
131
  end
134
132
 
@@ -206,7 +204,7 @@ class ActiveRecordTest < Minitest::Test
206
204
 
207
205
  def test_attribute_was_works_when_options_for_old_encrypted_value_are_different_than_options_for_new_encrypted_value
208
206
  pw = 'password'
209
- crypto_key = SecureRandom.base64(32)
207
+ crypto_key = SecureRandom.urlsafe_base64(24)
210
208
  old_iv = SecureRandom.random_bytes(12)
211
209
  account = Account.create
212
210
  encrypted_value = Encryptor.encrypt(value: pw, iv: old_iv, key: crypto_key)
@@ -332,7 +330,9 @@ class ActiveRecordTest < Minitest::Test
332
330
  def test_should_evaluate_proc_based_mode
333
331
  street = '123 Elm'
334
332
  zipcode = '12345'
335
- address = Address.new(street: street, zipcode: zipcode, mode: :single_iv_and_salt)
336
- assert_nil address.encrypted_zipcode_iv
333
+ address = Address.create(street: street, zipcode: zipcode, mode: :single_iv_and_salt)
334
+ address.reload
335
+ refute_equal address.encrypted_zipcode, zipcode
336
+ assert_equal address.zipcode, zipcode
337
337
  end
338
338
  end
@@ -23,11 +23,12 @@ class User
23
23
  attr_encrypted :with_encoding, :key => SECRET_KEY, :encode => true
24
24
  attr_encrypted :with_custom_encoding, :key => SECRET_KEY, :encode => 'm'
25
25
  attr_encrypted :with_marshaling, :key => SECRET_KEY, :marshal => true
26
- attr_encrypted :with_true_if, :key => SECRET_KEY, :if => true
27
- attr_encrypted :with_false_if, :key => SECRET_KEY, :if => false
28
- attr_encrypted :with_true_unless, :key => SECRET_KEY, :unless => true
29
- attr_encrypted :with_false_unless, :key => SECRET_KEY, :unless => false
26
+ attr_encrypted :with_true_if, :key => SECRET_KEY, :if => true, mode: :per_attribute_iv_and_salt
27
+ attr_encrypted :with_false_if, :key => SECRET_KEY, :if => false, mode: :per_attribute_iv_and_salt
28
+ attr_encrypted :with_true_unless, :key => SECRET_KEY, :unless => true, mode: :per_attribute_iv_and_salt
29
+ attr_encrypted :with_false_unless, :key => SECRET_KEY, :unless => false, mode: :per_attribute_iv_and_salt
30
30
  attr_encrypted :with_if_changed, :key => SECRET_KEY, :if => :should_encrypt
31
+ attr_encrypted :with_allow_empty_value, key: SECRET_KEY, allow_empty_value: true, marshal: true
31
32
 
32
33
  attr_encryptor :aliased, :key => SECRET_KEY
33
34
 
@@ -40,6 +41,7 @@ class User
40
41
  self.should_encrypt = true
41
42
  end
42
43
 
44
+ private
43
45
  def secret_key
44
46
  SECRET_KEY
45
47
  end
@@ -114,7 +116,7 @@ class AttrEncryptedTest < Minitest::Test
114
116
  assert_nil User.encrypt_email(nil, iv: @iv)
115
117
  end
116
118
 
117
- def test_should_not_encrypt_empty_string
119
+ def test_should_not_encrypt_empty_string_by_default
118
120
  assert_equal '', User.encrypt_email('', iv: @iv)
119
121
  end
120
122
 
@@ -150,9 +152,14 @@ class AttrEncryptedTest < Minitest::Test
150
152
  def test_should_decrypt_email_when_reading
151
153
  @user = User.new
152
154
  assert_nil @user.email
153
- iv = @user.encrypted_email_iv.unpack('m').first
154
- salt = @user.encrypted_email_salt[1..-1].unpack('m').first
155
+ options = @user.encrypted_attributes[:email]
156
+ iv = @user.send(:generate_iv, options[:algorithm])
157
+ encoded_iv = [iv].pack(options[:encode_iv])
158
+ salt = SecureRandom.random_bytes
159
+ encoded_salt = @user.send(:prefix_and_encode_salt, salt, options[:encode_salt])
155
160
  @user.encrypted_email = User.encrypt_email('test@example.com', iv: iv, salt: salt)
161
+ @user.encrypted_email_iv = encoded_iv
162
+ @user.encrypted_email_salt = encoded_salt
156
163
  assert_equal 'test@example.com', @user.email
157
164
  end
158
165
 
@@ -282,6 +289,18 @@ class AttrEncryptedTest < Minitest::Test
282
289
  assert_equal 'testing', @user.encrypted_with_true_unless
283
290
  end
284
291
 
292
+ def test_should_encrypt_empty_with_truthy_allow_empty_value_option
293
+ @user = User.new
294
+ assert_nil @user.encrypted_with_allow_empty_value
295
+ @user.with_allow_empty_value = ''
296
+ refute_nil @user.encrypted_with_allow_empty_value
297
+ assert_equal '', @user.with_allow_empty_value
298
+ @user = User.new
299
+ @user.with_allow_empty_value = nil
300
+ refute_nil @user.encrypted_with_allow_empty_value
301
+ assert_nil @user.with_allow_empty_value
302
+ end
303
+
285
304
  def test_should_work_with_aliased_attr_encryptor
286
305
  assert User.encrypted_attributes.include?(:aliased)
287
306
  end
@@ -390,4 +409,61 @@ class AttrEncryptedTest < Minitest::Test
390
409
  user.email = 'revised_value@test.com'
391
410
  refute_equal original_iv, user.encrypted_email_iv
392
411
  end
412
+
413
+ def test_should_not_generate_iv_for_attribute_when_if_option_is_false
414
+ user = User.new
415
+ user.with_false_if = 'derp'
416
+ assert_nil user.encrypted_with_false_if_iv
417
+ end
418
+
419
+ def test_should_generate_iv_for_attribute_when_if_option_is_true
420
+ user = User.new
421
+ user.with_true_if = 'derp'
422
+ refute_nil user.encrypted_with_true_if_iv
423
+
424
+ user.with_true_if = Object.new
425
+ refute_nil user.encrypted_with_true_if_iv
426
+ end
427
+
428
+ def test_should_not_generate_salt_for_attribute_when_if_option_is_false
429
+ user = User.new
430
+ user.with_false_if = 'derp'
431
+ assert_nil user.encrypted_with_false_if_salt
432
+ end
433
+
434
+ def test_should_generate_salt_for_attribute_when_if_option_is_true
435
+ user = User.new
436
+ user.with_true_if = 'derp'
437
+ refute_nil user.encrypted_with_true_if_salt
438
+ end
439
+
440
+ def test_should_generate_iv_for_attribute_when_unless_option_is_false
441
+ user = User.new
442
+ user.with_false_unless = 'derp'
443
+ refute_nil user.encrypted_with_false_unless_iv
444
+ end
445
+
446
+ def test_should_not_generate_iv_for_attribute_when_unless_option_is_true
447
+ user = User.new
448
+ user.with_true_unless = 'derp'
449
+ assert_nil user.encrypted_with_true_unless_iv
450
+ end
451
+
452
+ def test_should_generate_salt_for_attribute_when_unless_option_is_false
453
+ user = User.new
454
+ user.with_false_unless = 'derp'
455
+ refute_nil user.encrypted_with_false_unless_salt
456
+ end
457
+
458
+ def test_should_not_generate_salt_for_attribute_when_unless_option_is_true
459
+ user = User.new
460
+ user.with_true_unless = 'derp'
461
+ assert_nil user.encrypted_with_true_unless_salt
462
+ end
463
+
464
+ def test_should_not_by_default_generate_iv_when_attribute_is_empty
465
+ user = User.new
466
+ user.with_true_if = nil
467
+ assert_nil user.encrypted_with_true_if_iv
468
+ end
393
469
  end
@@ -41,7 +41,7 @@ class CompatibilityTest < Minitest::Test
41
41
  end
42
42
 
43
43
  def setup
44
- ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
44
+ drop_all_tables
45
45
  create_tables
46
46
  end
47
47
 
@@ -50,7 +50,7 @@ end
50
50
  class LegacyActiveRecordTest < Minitest::Test
51
51
 
52
52
  def setup
53
- ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
53
+ drop_all_tables
54
54
  create_people_table
55
55
  end
56
56
 
@@ -41,7 +41,7 @@ class LegacyCompatibilityTest < Minitest::Test
41
41
  end
42
42
 
43
43
  def setup
44
- ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
44
+ drop_all_tables
45
45
  create_tables
46
46
  end
47
47
 
@@ -27,6 +27,7 @@ require 'active_record'
27
27
  require 'data_mapper'
28
28
  require 'digest/sha2'
29
29
  require 'sequel'
30
+ ActiveSupport::Deprecation.behavior = :raise
30
31
 
31
32
  $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
32
33
  $:.unshift(File.dirname(__FILE__))
@@ -49,3 +50,9 @@ SECRET_KEY = SecureRandom.random_bytes(32)
49
50
  def base64_encoding_regex
50
51
  /^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$/
51
52
  end
53
+
54
+ def drop_all_tables
55
+ connection = ActiveRecord::Base.connection
56
+ tables = (ActiveRecord::VERSION::MAJOR >= 5 ? connection.data_sources : connection.tables)
57
+ tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
58
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attr_encrypted
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.3
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Huber
@@ -15,25 +15,25 @@ cert_chain:
15
15
  -----BEGIN CERTIFICATE-----
16
16
  MIIDdDCCAlygAwIBAgIBATANBgkqhkiG9w0BAQUFADBAMRIwEAYDVQQDDAlzYWdo
17
17
  YXVsb3IxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
18
- bTAeFw0xNjAxMTEyMjQyMDFaFw0xNzAxMTAyMjQyMDFaMEAxEjAQBgNVBAMMCXNh
18
+ bTAeFw0xODAyMTIwMzMzMThaFw0xOTAyMTIwMzMzMThaMEAxEjAQBgNVBAMMCXNh
19
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
20
+ Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvOLqbSmj5txfw39a
21
+ Ki0g3BJWGrfGBiSRq9aThUGzoiaqyDo/m1WMQdgPioZG+P923okChEWFjhSymBQU
22
+ eMdys6JRPm5ortp5sh9gesOWoozqb8R55d8rr1V7pY533cCut53Kb1wiitjkfXjR
23
+ efT2HPh6nV6rYjGMJek/URaCNzsZo7HCkRsKdezP+BKr4V4wOka69tfJX5pcvFvR
24
+ iiqfaiP4RK12hYdsFnSVKiKP7SAFTFiYcohbL8TUW6ezQQqJCK0M6fu74EWVCnBS
25
+ gFVjj931BuD8qhuxMiB6uC6FKxemB5TRGBLzn7RcrOMAo2inMAopjkGeQJUAyVCm
26
+ J5US3wIDAQABo3kwdzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU
27
+ hJEuSZgvuuIhIsxQ/0pRQTBVzokwHgYDVR0RBBcwFYETc2FnaGF1bG9yQGdtYWls
28
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
29
+ BQUAA4IBAQCsBS2cxqTmV4nXJEH/QbdgjVDAZbK6xf2gpM3vCRlYsy7Wz6GEoOpD
30
+ bzRkjxZwGNbhXShMUZwm6zahYQ/L1/HFztLoMBMkm8EIfPxH0PDrP4aWl0oyWxmU
31
+ OLm0/t9icSWRPPJ1tLJvuAaDdVpY5dEHd6VdnNJGQC5vHKRInt1kEyqEttIJ/xmJ
32
+ leSEFyMeoFsR+C/WPG9WSC+xN0eXqakCu6YUJoQzCn/7znv8WxpHEbeZjNIHq0qb
33
+ nbqZ/ZW1bwzj1T/NIbnMr37wqV29XwkI4+LbewMkb6/bDPYl0qZpAkCxKtGYCCJp
34
+ l6KPs9K/72yH00dxuAhiTXikTkcLXeQJ
35
35
  -----END CERTIFICATE-----
36
- date: 2016-07-22 00:00:00.000000000 Z
36
+ date: 2018-02-11 00:00:00.000000000 Z
37
37
  dependencies:
38
38
  - !ruby/object:Gem::Dependency
39
39
  name: encryptor
@@ -53,30 +53,30 @@ dependencies:
53
53
  name: activerecord
54
54
  requirement: !ruby/object:Gem::Requirement
55
55
  requirements:
56
- - - ">="
56
+ - - "~>"
57
57
  - !ruby/object:Gem::Version
58
- version: 2.0.0
58
+ version: 4.1.16
59
59
  type: :development
60
60
  prerelease: false
61
61
  version_requirements: !ruby/object:Gem::Requirement
62
62
  requirements:
63
- - - ">="
63
+ - - "~>"
64
64
  - !ruby/object:Gem::Version
65
- version: 2.0.0
65
+ version: 4.1.16
66
66
  - !ruby/object:Gem::Dependency
67
67
  name: actionpack
68
68
  requirement: !ruby/object:Gem::Requirement
69
69
  requirements:
70
- - - ">="
70
+ - - "~>"
71
71
  - !ruby/object:Gem::Version
72
- version: 2.0.0
72
+ version: 4.1.16
73
73
  type: :development
74
74
  prerelease: false
75
75
  version_requirements: !ruby/object:Gem::Requirement
76
76
  requirements:
77
- - - ">="
77
+ - - "~>"
78
78
  - !ruby/object:Gem::Version
79
- version: 2.0.0
79
+ version: 4.1.16
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: datamapper
82
82
  requirement: !ruby/object:Gem::Requirement
@@ -193,16 +193,16 @@ dependencies:
193
193
  name: codeclimate-test-reporter
194
194
  requirement: !ruby/object:Gem::Requirement
195
195
  requirements:
196
- - - ">="
196
+ - - "<="
197
197
  - !ruby/object:Gem::Version
198
- version: '0'
198
+ version: 0.6.0
199
199
  type: :development
200
200
  prerelease: false
201
201
  version_requirements: !ruby/object:Gem::Requirement
202
202
  requirements:
203
- - - ">="
203
+ - - "<="
204
204
  - !ruby/object:Gem::Version
205
- version: '0'
205
+ version: 0.6.0
206
206
  description: Generates attr_accessors that encrypt and decrypt attributes transparently
207
207
  email:
208
208
  - seah@shuber.io
@@ -228,6 +228,8 @@ files:
228
228
  - checksum/attr_encrypted-3.0.1.gem.sha512
229
229
  - checksum/attr_encrypted-3.0.2.gem.sha256
230
230
  - checksum/attr_encrypted-3.0.2.gem.sha512
231
+ - checksum/attr_encrypted-3.0.3.gem.sha256
232
+ - checksum/attr_encrypted-3.0.3.gem.sha512
231
233
  - lib/attr_encrypted.rb
232
234
  - lib/attr_encrypted/adapters/active_record.rb
233
235
  - lib/attr_encrypted/adapters/data_mapper.rb
@@ -246,7 +248,8 @@ files:
246
248
  - test/sequel_test.rb
247
249
  - test/test_helper.rb
248
250
  homepage: http://github.com/attr-encrypted/attr_encrypted
249
- licenses: []
251
+ licenses:
252
+ - MIT
250
253
  metadata: {}
251
254
  post_install_message: |2+
252
255
 
@@ -280,7 +283,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
280
283
  version: '0'
281
284
  requirements: []
282
285
  rubyforge_project:
283
- rubygems_version: 2.4.5.1
286
+ rubygems_version: 2.6.13
284
287
  signing_key:
285
288
  specification_version: 4
286
289
  summary: Encrypt and decrypt attributes
@@ -297,4 +300,3 @@ test_files:
297
300
  - test/run.sh
298
301
  - test/sequel_test.rb
299
302
  - test/test_helper.rb
300
- has_rdoc: false
metadata.gz.sig CHANGED
Binary file