active_encryption 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3e69b6310ad07f84103d31671cdea752e0bd85a396f92a3505d2f2b99b8c7a7f
4
+ data.tar.gz: 5241fcd166545fe26cf890d6bd65a39ff980f8d827a2b9a1c69f4ad92710c920
5
+ SHA512:
6
+ metadata.gz: 721cdb68e2a9f525d77874da1bca8912d128a119d900c68a3aec87bfcfd373b544a75453f439707dda956490cb93512527c45419b5b7d838386822d0611167aa
7
+ data.tar.gz: 62d23edf54e20fc6e30ee8fe4974e3436076d31a3e63a59d37c765792082f722edeaf0b2b3731da20a2a48e00f49449ff06b57c30eeb713b097c3d88ea67b24c
@@ -0,0 +1,3 @@
1
+ ����o�^0�otʜ8��9"����"���n�$8��rkމ�Q�Y߹��
2
+ دK_%��;xe�(gm�2���?BVP|����V�e��"1��hi!F�z@d�+���|M�n��E-��&y��,�����|=[�F@�z+��j�0���N�6f�,�mk��~������!������\�f����M�bV�~h�H֓�]�
3
+ ѭt`�h���I0���Y6�#��� /���a3�/#ya�l��{e��0��vk��]��a�a �ȍ��Z���
Binary file
@@ -0,0 +1,10 @@
1
+ # see http://editorconfig.org/
2
+
3
+ root = true
4
+
5
+ [*]
6
+ indent_style = space
7
+ indent_size = 2
8
+ end_of_line = lf
9
+ charset = utf-8
10
+ insert_final_newline = true
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /active_encryption-*.gem
10
+ /Gemfile.lock
11
+
12
+ # rspec failure tracking
13
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,4 @@
1
+ require:
2
+ - rubocop-rspec
3
+ Metrics/BlockLength:
4
+ ExcludedMethods: ['describe', 'context'] # Rspec DSL has long blocks
@@ -0,0 +1,21 @@
1
+ ---
2
+ env:
3
+ global:
4
+ - CC_TEST_REPORTER_ID=84bb987517388fd3f106f685b088598f34db2dced78783e4c12963f1a475f3ae
5
+ sudo: false
6
+ language: ruby
7
+ cache: bundler
8
+ rvm:
9
+ - 2.6
10
+ - 2.5
11
+ - 2.4
12
+ - 2.3
13
+ before_install: gem install bundler -v 2.0.2
14
+ before_script:
15
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
16
+ - chmod +x ./cc-test-reporter
17
+ - ./cc-test-reporter before-build
18
+ script:
19
+ - bundle exec rspec
20
+ after_script:
21
+ - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
@@ -0,0 +1,20 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+
10
+
11
+ ## 0.1.0 2019-07-19
12
+
13
+ - Add signature to gem releases
14
+ - Add Rails generator to create default initializer and encryption_settings.yml
15
+ - Add ActiveRecord adapter
16
+ - Add ActiveEncryption::Encryptable concern to (en|de)crypt object attributes
17
+ - Add ActiveEncryption::Encryptor to abstract ActiveSupport::MessageEncryptor
18
+ - Add DSL to configure the gem
19
+ - Add encryption setting records and YAML-based store to persist them
20
+ - Basic gem skeleton
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at community@zircode.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
71
+ version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Zircode Ltd.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,208 @@
1
+ # ActiveEncryption
2
+
3
+ ActiveEncryption transparently encrypt (and decrypt!) attributes. It works with any class, but it's primarly intended to be used with ActiveRecord models. Under the hood, it doesn't reinvent the wheel and uses the tried and tested ActiveSupport::MessageEncryptor.
4
+
5
+ [![Build Status](https://travis-ci.com/Zircode/active_encryption.svg?branch=master)](https://travis-ci.com/Zircode/active_encryption) [![Test Coverage](https://api.codeclimate.com/v1/badges/08c66b215b98a395a0b8/test_coverage)](https://codeclimate.com/github/Zircode/active_encryption/test_coverage) [![Maintainability](https://api.codeclimate.com/v1/badges/08c66b215b98a395a0b8/maintainability)](https://codeclimate.com/github/Zircode/active_encryption/maintainability) [![security](https://hakiri.io/github/Zircode/active_encryption/master.svg)](https://hakiri.io/github/Zircode/active_encryption/master)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'active_encryption'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ ```shell
18
+ bundle
19
+ ```
20
+
21
+ Or install it yourself as:
22
+
23
+ ```shell
24
+ gem install active_encryption
25
+ ```
26
+
27
+ ### Security
28
+
29
+ ActiveEncryption is cryptographically signed. To be sure the gem you install
30
+ hasn’t been tampered with:
31
+
32
+ Add my public key (if you haven’t already) as a trusted certificate
33
+
34
+ ```shell
35
+ gem cert --add <(curl -Ls https://raw.github.com/Zircode/active_encryption/master/certs/garnu.pem)
36
+ gem install active_encryption -P MediumSecurity
37
+ ```
38
+
39
+ The ``MediumSecurity`` trust profile will verify signed gems, but allow the
40
+ installation of unsigned dependencies.
41
+
42
+ This is necessary because not all of dependencies are signed, so we cannot use
43
+ ``HighSecurity``.
44
+
45
+ ### Rails
46
+
47
+ ActiveEncryption works with Ruby on Rails 5.0 or higher.
48
+
49
+ Run the generator:
50
+
51
+ ```shell
52
+ rails generate active_encryption:install
53
+ ```
54
+
55
+ The generator creates two files:
56
+
57
+ - an initializer: ``config/initializers/active_encryption.rb``
58
+ - a encryption setting YAML file: ``config/encryption_settings.yml``
59
+
60
+ ## Usage
61
+
62
+ ```ruby
63
+ class User
64
+ encrypted_attr :ssn
65
+ end
66
+ ```
67
+
68
+ Or if you're using ActiveRecord:
69
+
70
+ ```ruby
71
+ class User < ApplicationRecord
72
+ encrypted_attr :ssn
73
+ end
74
+ ```
75
+
76
+ In this example, ActiveEncryption assumes that you have an attribute
77
+ ``ssn_encrypted``.
78
+ Therefore, you might need a database migration:
79
+
80
+ ```ruby
81
+ class CreateUsers < ActiveRecord::Migration[5.0]
82
+ def change
83
+ create_table :users do |t|
84
+ t.string :ssn_encrypted
85
+
86
+ t.timestamps
87
+ end
88
+ end
89
+ end
90
+ ```
91
+
92
+ When storing your encrypted data, please consider the length requirements
93
+ of the database column where you're storing the encrypted data.
94
+
95
+ ## Configuration
96
+
97
+ If you're using Rails, the generator created an initializer
98
+ ``config/initializers/active_encryption.rb``, otherwise you need to create
99
+ similar file to configure ActiveEncryption:
100
+
101
+ ```ruby
102
+ # frozen_string_literal: true
103
+
104
+ ActiveEncryption.configure do |config|
105
+ # Store containing the encryption settings
106
+ # Use "config/encryption_settings.yml" to store the settings:
107
+ config.encryption_setting_store =
108
+ ActiveEncryption::EncryptionSetting::YamlStore.new(
109
+ '/path/encryption_settings.yml' # CHANGE ME
110
+ )
111
+
112
+ # ID of the encryption setting to use by default:
113
+ config.default_encryption_setting_id = :default
114
+ end
115
+ ```
116
+
117
+ You also need a ``encryption_settings.yml`` file:
118
+
119
+ ```yaml
120
+ # WARNING: Changing these encryption settings prevents the decryption
121
+ # of already encrypted data.
122
+
123
+ # Default encryption setting
124
+ default:
125
+ # secret: must be a cryptographically random string.
126
+ # The secret is hashed with PBKDF2 to generate the encryption key.
127
+ #
128
+ # You can generate one with:
129
+ # - "rails secret"
130
+ # - SecureRandom.hex(64)
131
+ # - or, SecureRandom.urlsafe_base64(64)
132
+ #
133
+ ## WARNING ##
134
+ # The secret value should NOT be stored in this file directly.
135
+ # You should instead refer to where the secret value is stored
136
+ # e.g. refer to Rails credentials/secrets, an environment variable or
137
+ # a KMS/HSM, etc.
138
+ secret: <%= ENV['SECRET_KEY'] %>
139
+ # Salt used to generate the encryption key based on the secret
140
+ secret_salt: 'ActiveEncryption salt: RANDOM_SALT' # CHANGE ME
141
+ # Number of iterations for PBKDF2 on the secret.
142
+ secret_iterations: 65536
143
+ # Cipher to use. Can be any cipher returned by OpenSSL::Cipher.ciphers.
144
+ cipher: aes-256-gcm
145
+ # Digest to use to sign. Default is SHA1. Recommended is SHA256.
146
+ # Ignored when using an AEAD cipher like 'aes-256-gcm'.
147
+ digest: SHA256
148
+ ```
149
+
150
+ ### Attribute options
151
+
152
+ ``encrypted_attr`` accepts options to override the settings in
153
+ ``encryption_settings.yml``.
154
+
155
+ For example, you can override the ``secret`` and ``cipher`` with options:
156
+
157
+ ```ruby
158
+ encrypted_attr :ssn, secret: 'some secret', cipher: 'aes-128-gcm'
159
+ ```
160
+
161
+ ### Encryption setting
162
+
163
+ The following attributes are configurable in an encryption setting:
164
+
165
+ | Attribute | Description | Default value |
166
+ |-----------------|-------------|---------------|
167
+ | ``cipher`` | String with the encryption cipher to use. Can be any cipher returned by OpenSSL::Cipher.ciphers. | 'aes-256-gcm' |
168
+ | ``digest`` | String with the digest to use to sign. Ignored when using an AEAD cipher like 'aes-256-gcm'. | 'SHA1' |
169
+ | ``id`` | Unique ID to identify an encryption setting. It can be an Integer, String, or Symbol. | nil |
170
+ | ``key`` | Cryptographicaly random binary string of the exact size required by the cipher. E.g. 'aes-256-gcm' requires 32 bytes (256 bits). Can be generated with ``SecureRandom.bytes(32)``. It is STRONGLY recommended NOT to set this directly but to use a secret for key derivation. | nil |
171
+ | ``purpose`` | Confines the encrypted attribute to a specific purpose. See https://api.rubyonrails.org/classes/ActiveSupport/MessageEncryptor.html#method-i-encrypt_and_sign | nil |
172
+ | ``secret`` | String used to derive an encryption key with PBKDF2. Can be generated with ``SecureRandom.hex(64)`` or ``SecureRandom.urlsafe_base64(64)``. | nil |
173
+ | ``secret_iterations`` | Number of iterations of PBKDF2 to derive the key from the secret. See https://api.rubyonrails.org/classes/ActiveSupport/KeyGenerator.html | 65536 |
174
+ | ``secret_salt`` | Salt for PBKDF2 to derive the key from the secret. | 'ActiveEncryption default key salt' |
175
+ | ``serializer`` | Object serializer to use. E.g.: 'YAML'. | Marshal |
176
+
177
+ Keys or secrets must NEVER be stored in version control (e.g. git) or in the
178
+ database in an unencrypted form.
179
+
180
+ ## Development
181
+
182
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run
183
+ `rake spec` to run the tests. You can also run `bin/console` for an interactive
184
+ prompt that will allow you to experiment.
185
+
186
+ To install this gem onto your local machine, run `bundle exec rake install`.
187
+ To release a new version, update the version number in `version.rb`, and then run
188
+ `bundle exec rake release`, which will create a git tag for the version, push git
189
+ commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
190
+
191
+ ## Contributing
192
+
193
+ Bug reports and pull requests are welcome on
194
+ [GitHub](https://github.com/Zircode/active_encryption). This project is intended
195
+ to be a safe, welcoming space for collaboration, and contributors are expected
196
+ to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of
197
+ conduct.
198
+
199
+ ## License
200
+
201
+ The gem is available as open source under the terms of the
202
+ [MIT License](https://opensource.org/licenses/MIT).
203
+
204
+ ## Code of Conduct
205
+
206
+ Everyone interacting in the ActiveEncryption project’s codebases, issue trackers,
207
+ chat rooms and mailing lists is expected to follow the
208
+ [code of conduct](https://github.com/Zircode/active_encryption/blob/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'active_encryption/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'active_encryption'
9
+ spec.version = ActiveEncryption::VERSION
10
+ spec.authors = ['Arnaud Germis']
11
+ spec.email = ['hello@zircode.com', 'arnaud@zircode.com']
12
+
13
+ spec.summary = <<~SUMMARY
14
+ ActiveEncryption transparently encrypt (and decrypt!) attributes with\
15
+ ActiveSupport::MessageEncryptor
16
+ SUMMARY
17
+ spec.homepage = 'https://github.com/Zircode/active_encryption'
18
+ spec.license = 'MIT'
19
+
20
+ spec.metadata['homepage_uri'] = spec.homepage
21
+ spec.metadata['source_code_uri'] = 'https://github.com/Zircode/active_encryption'
22
+ spec.metadata['changelog_uri'] = 'https://github.com/Zircode/active_encryption/CHANGELOG.md'
23
+ spec.metadata['bug_tracker_uri'] = 'https://github.com/Zircode/active_encryption/issues'
24
+
25
+ # Specify which files should be added to the gem when it is released.
26
+ # The `git ls-files -z` loads the files in the RubyGem that have been added
27
+ # into git.
28
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
29
+ `git ls-files -z`.split("\x0")
30
+ .reject { |f| f.match(%r{^(test|spec|features)/}) }
31
+ end
32
+ spec.bindir = 'exe'
33
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
34
+ spec.require_paths = ['lib']
35
+ spec.cert_chain = ['certs/garnu.pem']
36
+ if $PROGRAM_NAME =~ /gem\z/
37
+ spec.signing_key = File.expand_path('~/.ssh/gem-private_key.pem')
38
+ end
39
+ spec.required_ruby_version = '>= 2.3'
40
+
41
+ spec.add_dependency 'activesupport', '>= 5.0.0', '<= 6.1'
42
+ spec.add_dependency 'railties', '>= 5.0.0', '<= 6.1'
43
+
44
+ spec.add_development_dependency 'bundler', '~> 2.0'
45
+ spec.add_development_dependency 'rake', '~> 10.0'
46
+ spec.add_development_dependency 'reek', '~> 5.4.0'
47
+ spec.add_development_dependency 'rspec', '~> 3.0'
48
+ spec.add_development_dependency 'rubocop', '~> 0.72.0'
49
+ spec.add_development_dependency 'rubocop-rspec', '~> 1.33.0'
50
+ spec.add_development_dependency 'simplecov', '~> 0.17.0'
51
+ end
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'active_encryption'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require 'pry'
12
+ # Pry.start
13
+
14
+ require 'irb'
15
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,25 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEODCCAqCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhhcm5h
3
+ dWQvREM9emlyY29kZS9EQz1jb20wHhcNMTkwNzE4MTQ0OTE4WhcNMjAwNzE3MTQ0
4
+ OTE4WjAjMSEwHwYDVQQDDBhhcm5hdWQvREM9emlyY29kZS9EQz1jb20wggGiMA0G
5
+ CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDltdBv6MnjmokVZEkhubGk0NfEiU4C
6
+ WZZLNgN+FpyK5VNDvGvs8+OTusYCw07HFkhKVF2T+3A1XlYZKOXozCFBoQtL5ted
7
+ Nxy8yo874kcF5M6EV22np8/SefOJrpk4Wgvz4xdwT24LjZpmLHWFPXuVuqI4LZ7Q
8
+ Eh6sjVfG1h0SBSF8RjCCmEXONsz+ceDWvBKdBUSYfVt0HGmDSXYJByF4I8onkeUc
9
+ xxmLCu8VxZvnHrEw94BRPiEI1oUJ+3etNu2MYcK3pnLc+p9zYQ/NjS0Bsa423fmZ
10
+ 5K0Z4qiN550vccPZxRoMk9eiZHL8dN+ZgxG4+2o+ouCYRkLnkCyDR4rr7zLIcojo
11
+ 53iJqFF8cJtkectMOhNOO9jh/FMsJZnKWBzJ4/J3xHSLz4gD4/47WSwjAJ4tLHGC
12
+ 4VpzfD53vdr3i5RvB7bv3QiePUR2vV5AUap2S7TKJ+ojQVoh7TfJP3N5nwVspQkh
13
+ C3goXVkz5Op9TkLN3oUGqnveL9nC4y6e180CAwEAAaN3MHUwCQYDVR0TBAIwADAL
14
+ BgNVHQ8EBAMCBLAwHQYDVR0OBBYEFBNAzBaMirBd5+1xszQeddjvuLdCMB0GA1Ud
15
+ EQQWMBSBEmFybmF1ZEB6aXJjb2RlLmNvbTAdBgNVHRIEFjAUgRJhcm5hdWRAemly
16
+ Y29kZS5jb20wDQYJKoZIhvcNAQELBQADggGBAGvmnHTVKwGAlqB93/QZ19MBUrFm
17
+ vIxkoWYi/GlZnJGsApFwZtOsNaAFxYIVfAR7fZjQtCB7B6ZyERZF+m8J3tC23eTG
18
+ PadrSjz3SPbFJlCIqJ0NllSvx5E+98b9pq9tIyaeFbYnII1qoy+SIiWOurVS4dWr
19
+ dkmUsJvxyNJ+3yoVt568UFSf/YZ88GaabEAL5JFwXIpv/cxaej9M2bALPkP7HUm/
20
+ rgSmTctYicJomzzQ5LSLhdVSV+z5w2L5roIu5bPEQJyWIj6pZCthACPMR/emsLQ2
21
+ T9JFyENPrM2CUtwBaLQacRInp5zRWueDKIf0I+vNjRKu5PwEeePVn2VlkcQTuhUT
22
+ Vgg0CeGsGrJdcSohxH13t3gx4QXH0SA+4HPW7uqEeIQLwmBA56nCi6jAgTGAZhjX
23
+ UsJ7gUgNcBEuCAwgXmVzhEQ50pTMVRAL2cQKqnFkqehpRJ+78n+psW480iLqmjq3
24
+ GzWvrPCkKt17EBe3MSjjMsq80n5C1eaKRQA9Vw==
25
+ -----END CERTIFICATE-----
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_encryption/version'
4
+ require 'active_encryption/configuration'
5
+ require 'active_encryption/adapters'
6
+
7
+ # The top-level ActiveEncryption module isolates the gem from the host
8
+ # application.
9
+ module ActiveEncryption
10
+ include Configuration
11
+ # The ActiveEncryption::Error is the base class for ActiveEncryption errors.
12
+ class Error < StandardError; end
13
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_encryption/encryptable'
4
+ require 'active_encryption/adapters/active_record'
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveEncryption
4
+ module Adapters
5
+ # Encapsulates the ActiveRecord adapter
6
+ class ActiveRecord
7
+ def initialize
8
+ ActiveSupport.on_load(:active_record) do
9
+ extend ActiveEncryption::Encryptable
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ ActiveEncryption::Adapters::ActiveRecord.new
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_encryption/configuration/store'
4
+
5
+ module ActiveEncryption
6
+ # The ActiveEncryption::Configuration module contains classes and methods
7
+ # to configure the gem.
8
+ #
9
+ # Usage:
10
+ # ActiveEncryption.configure |config|
11
+ # config.option_1 = true
12
+ # config.option_2 = false
13
+ # end
14
+ #
15
+ module Configuration
16
+ def self.included(klass)
17
+ klass.extend ClassMethods
18
+ end
19
+
20
+ # ClassMethods contains the class methods to extend when the module
21
+ # is included in ActiveEncryption.
22
+ module ClassMethods
23
+ def config
24
+ @config ||= Store.new
25
+ end
26
+
27
+ def configure
28
+ yield config
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_encryption/encryption_setting/yaml_store'
4
+
5
+ module ActiveEncryption
6
+ module Configuration
7
+ # The ActiveEncryption::Configuration::Store class stores the gem
8
+ # configuration.
9
+ class Store
10
+ DEFAULTS = {
11
+ encryption_setting_store: nil,
12
+ default_encryption_setting_id: :default
13
+ }.freeze
14
+
15
+ attr_accessor(*DEFAULTS.keys)
16
+
17
+ def initialize
18
+ reset
19
+ end
20
+
21
+ def reset
22
+ DEFAULTS.each do |key, value|
23
+ public_send("#{key}=", value)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_encryption/encryptable/instance_methods_on_activation'
4
+
5
+ module ActiveEncryption
6
+ # The ActiveEncryption::Encryptable encapsulates methods and classes to
7
+ # make a model attribute encryptable.
8
+ #
9
+ # Usage:
10
+ #
11
+ # class MyModel
12
+ # extend ActiveEncryption::Encryptable
13
+ # encrypted_attr :my_attribute
14
+ # end
15
+ #
16
+ module Encryptable
17
+ def encrypted_attr(attribute_name, options = {})
18
+ include InstanceMethodsOnActivation.new(attribute_name, options)
19
+ end
20
+
21
+ # :reek:UtilityFunction should be ok for ClassMethod modules?
22
+ def encryption_setting
23
+ config = ActiveEncryption.config
24
+ store = config.encryption_setting_store
25
+ id = config.default_encryption_setting_id
26
+ store.find(id)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_encryption/encryptor'
4
+
5
+ module ActiveEncryption
6
+ module Encryptable
7
+ # InstanceMethodsOnActivation adds instance methods for the attribute
8
+ # "attribute_name" to the including class.
9
+ class InstanceMethodsOnActivation < Module
10
+ def initialize(attribute_name, options)
11
+ define_generic_methods
12
+ define_attribute_accessors(attribute_name, options)
13
+ end
14
+
15
+ def define_generic_methods
16
+ define_encrypt
17
+ define_decrypt
18
+ end
19
+
20
+ def define_encrypt
21
+ define_method('encrypt') do |attribute_name, unencrypted_value|
22
+ setting = send("#{attribute_name}_encryption_setting")
23
+ encryptor = send("#{attribute_name}_encryptor")
24
+ encrypted_value = encryptor.encrypt(
25
+ unencrypted_value,
26
+ purpose: setting.purpose
27
+ )
28
+ send("#{attribute_name}_encrypted=", encrypted_value)
29
+ end
30
+ end
31
+
32
+ def define_decrypt
33
+ define_method('decrypt') do |attribute_name|
34
+ encrypted_value = send("#{attribute_name}_encrypted")
35
+ return nil unless encrypted_value
36
+
37
+ setting = send("#{attribute_name}_encryption_setting")
38
+ send("#{attribute_name}_encryptor")
39
+ .decrypt(encrypted_value, purpose: setting.purpose)
40
+ end
41
+ end
42
+
43
+ def define_attribute_accessors(attribute_name, options = {})
44
+ define_attribute_encryption_setting(attribute_name, options)
45
+ define_attribute_encryptor(attribute_name)
46
+ define_attribute_setter(attribute_name)
47
+ define_attribute_getter(attribute_name)
48
+ end
49
+
50
+ def define_attribute_encryption_setting(attribute_name, options = {})
51
+ define_method("#{attribute_name}_encryption_setting") do
52
+ instance_variable_name = "@#{attribute_name}_encryption_setting"
53
+ instance_variable = instance_variable_get(instance_variable_name)
54
+ return instance_variable if instance_variable
55
+
56
+ instance_variable_set(
57
+ instance_variable_name,
58
+ EncryptionSetting::Record.merge(self.class.encryption_setting,
59
+ options)
60
+ )
61
+ end
62
+ end
63
+
64
+ def define_attribute_encryptor(attribute_name)
65
+ define_method("#{attribute_name}_encryptor") do
66
+ instance_variable_name = "@#{attribute_name}_encryptor"
67
+ instance_variable_get(instance_variable_name) ||
68
+ instance_variable_set(
69
+ instance_variable_name,
70
+ Encryptor.new(
71
+ send("#{attribute_name}_encryption_setting")
72
+ )
73
+ )
74
+ end
75
+ end
76
+
77
+ def define_attribute_setter(attribute_name)
78
+ define_method("#{attribute_name}=") do |unencrypted_value|
79
+ # Save unencrypted value in instance variable to not have to
80
+ # decrypt a freshly encrypted value.
81
+ instance_variable_set("@#{attribute_name}", unencrypted_value)
82
+ unless unencrypted_value
83
+ return send("#{attribute_name}_encrypted=", nil)
84
+ end
85
+
86
+ encrypt(attribute_name, unencrypted_value)
87
+ unencrypted_value
88
+ end
89
+ end
90
+
91
+ def define_attribute_getter(attribute_name)
92
+ define_method(attribute_name) do
93
+ # Check if an instance variable with the decrypted value already
94
+ # exist to save decryption time. Otherwise, call the generic
95
+ # #decrypt method.
96
+ instance_variable = instance_variable_get("@#{attribute_name}")
97
+ return instance_variable if instance_variable
98
+
99
+ decrypted_value = decrypt(attribute_name)
100
+ # Save the result to not have to decrypt it again.
101
+ instance_variable_set("@#{attribute_name}", decrypted_value)
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/key_generator'
4
+ require 'active_support/message_encryptor'
5
+
6
+ module ActiveEncryption
7
+ module EncryptionSetting
8
+ # The ActiveEncryption::EncryptionSetting::Key class wraps around
9
+ # ActiveSupport::KeyGenerator
10
+ class Key
11
+ DEFAULT_SALT = 'ActiveEncryption default key salt'
12
+
13
+ attr_reader :salt, :iterations
14
+
15
+ def initialize(secret, salt: nil, cipher: nil, iterations: nil)
16
+ salt ||= DEFAULT_SALT
17
+ @salt = salt
18
+ @cipher = cipher
19
+ @iterations = iterations
20
+ @generator = ActiveSupport::KeyGenerator.new(
21
+ secret,
22
+ iterations: iterations
23
+ )
24
+ end
25
+
26
+ def value
27
+ @generator.generate_key(salt, length)
28
+ end
29
+
30
+ def cipher
31
+ @cipher ||= ActiveSupport::MessageEncryptor.default_cipher
32
+ end
33
+
34
+ def length
35
+ ActiveSupport::MessageEncryptor.key_len(cipher)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_encryption/encryption_setting/key'
4
+
5
+ module ActiveEncryption
6
+ module EncryptionSetting
7
+ # The ActiveEncryption::EncryptionSetting::Record contains the required
8
+ # settings for encrypting and decrypting content.
9
+ class Record
10
+ ATTRIBUTES = %i[cipher digest id key purpose secret
11
+ secret_iterations secret_salt serializer].freeze
12
+
13
+ attr_reader(*ATTRIBUTES)
14
+
15
+ def self.to_h(record)
16
+ if record.is_a?(Hash)
17
+ record.slice(*ATTRIBUTES)
18
+ else
19
+ ATTRIBUTES.each_with_object({}) do |name, attributes|
20
+ attributes[name] = record.public_send(name)
21
+ end
22
+ end
23
+ end
24
+
25
+ def self.merge(base_record, higher_priority_record)
26
+ new(
27
+ to_h(base_record)
28
+ .merge(key: nil) # reset the computed key
29
+ .merge(
30
+ to_h(higher_priority_record)
31
+ )
32
+ )
33
+ end
34
+
35
+ def initialize(attributes)
36
+ ATTRIBUTES.each do |name|
37
+ instance_variable_set("@#{name}", attributes[name])
38
+ end
39
+
40
+ @serializer = Object.const_get(@serializer) if @serializer.is_a?(String)
41
+ end
42
+
43
+ def key
44
+ @key ||= Key.new(
45
+ secret,
46
+ cipher: cipher,
47
+ salt: secret_salt,
48
+ iterations: secret_iterations
49
+ ).value
50
+ end
51
+
52
+ def to_h
53
+ self.class.to_h(self)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
4
+ require 'yaml'
5
+ require 'active_encryption/encryption_setting/record'
6
+ require 'active_support/core_ext/hash'
7
+
8
+ module ActiveEncryption
9
+ module EncryptionSetting
10
+ # The ActiveEncryption::EncryptionSetting::YamlStore class retrieve
11
+ # ActiveEncryption::EncryptionSetting::Record from a YAML file.
12
+ class YamlStore
13
+ attr_reader :file_path
14
+
15
+ def initialize(file_path)
16
+ @file_path = file_path
17
+ end
18
+
19
+ def find(id)
20
+ id = id.to_sym
21
+ attributes = content[id]
22
+ return nil unless attributes
23
+
24
+ attributes[:id] = id
25
+ Record.new(attributes)
26
+ end
27
+
28
+ def content
29
+ @content ||= parse_file.deep_symbolize_keys
30
+ end
31
+
32
+ private
33
+
34
+ def parse_file
35
+ YAML.safe_load(ERB.new(File.read(file_path)).result)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/message_encryptor'
4
+
5
+ module ActiveEncryption
6
+ # The ActiveEncryption::Encryptor is an abstraction class around
7
+ # ActiveSupport::MessageEncryptor
8
+ #
9
+ # Usage:
10
+ #
11
+ # encryptor = ActiveEncryption::Encryptor.new(encryption_setting)
12
+ # encrypted_data = encryptor.encrypt(data)
13
+ # data = encryptor.decrypt(encrypted_data)
14
+ #
15
+ class Encryptor
16
+ attr_reader :encryption_setting
17
+
18
+ def initialize(encryption_setting, service = nil)
19
+ @encryption_setting = encryption_setting
20
+ @service = service
21
+ end
22
+
23
+ # :reek:LongParameterList is required to map to encrypt_and_sign
24
+ def encrypt(data, expires_at: nil, expires_in: nil, purpose: nil)
25
+ return nil unless data
26
+
27
+ service.encrypt_and_sign(
28
+ data,
29
+ expires_at: expires_at,
30
+ expires_in: expires_in,
31
+ purpose: purpose
32
+ )
33
+ end
34
+
35
+ def decrypt(data, purpose: nil)
36
+ return nil unless data
37
+
38
+ service.decrypt_and_verify(
39
+ data,
40
+ purpose: purpose
41
+ )
42
+ end
43
+
44
+ private
45
+
46
+ def service
47
+ @service ||= ActiveSupport::MessageEncryptor.new(
48
+ encryption_setting.key,
49
+ cipher: encryption_setting.cipher,
50
+ digest: encryption_setting.digest,
51
+ serializer: encryption_setting.serializer
52
+ )
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveEncryption
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators/base'
4
+
5
+ module ActiveEncryption
6
+ module Generators
7
+ # Generator to install ActiveEncryption in a Rails application.
8
+ #
9
+ # Usage:
10
+ #
11
+ # ``rails generate active_encryption:install``
12
+ #
13
+ class InstallGenerator < Rails::Generators::Base
14
+ source_root File.expand_path('../templates', __dir__)
15
+
16
+ desc <<~DESCRIPTION
17
+ Creates a ActiveEncryption initializer and copy\
18
+ encryption_settings.yml file to your application.
19
+ DESCRIPTION
20
+
21
+ def copy_initializer
22
+ copy_file(
23
+ 'active_encryption.rb',
24
+ Rails.root.join('config', 'initializers', 'active_encryption.rb')
25
+ )
26
+ end
27
+
28
+ def copy_encryption_settings
29
+ file_path = Rails.root.join('config', 'encryption_settings.yml')
30
+ copy_file 'encryption_settings.yml', file_path
31
+ gsub_file file_path,
32
+ '*RANDOM_SALT*',
33
+ SecureRandom.urlsafe_base64(4)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Be sure to restart your server when you modify this file.
4
+
5
+ ActiveEncryption.configure do |config|
6
+ # Store containing the encryption settings
7
+ # Use "config/encryption_settings.yml" to store the settings:
8
+ config.encryption_setting_store =
9
+ ActiveEncryption::EncryptionSetting::YamlStore.new(
10
+ Rails.root.join('config', 'encryption_settings.yml')
11
+ )
12
+
13
+ # ID of the encryption setting to use by default:
14
+ # config.default_encryption_setting_id = :default
15
+ end
@@ -0,0 +1,34 @@
1
+ # WARNING: Changing these encryption settings prevents the decryption
2
+ # of already encrypted data.
3
+
4
+ # Default encryption setting
5
+ default:
6
+ # secret: must be a cryptographically random string.
7
+ # The secret is hashed with PBKDF2 to generate the encryption key.
8
+ #
9
+ # You can generate one with:
10
+ # - "rails secret"
11
+ # - SecureRandom.hex(64)
12
+ # - or, SecureRandom.urlsafe_base64(64)
13
+ #
14
+ ## WARNING ##
15
+ # The secret value should NOT be stored in this file directly.
16
+ # You should instead refer to where the secret value is stored
17
+ # e.g. refer to Rails credentials/secrets, an environment variable or
18
+ # a KMS/HSM, etc.
19
+ secret: <%= Rails.application.credentials.secret_key_base %>
20
+ # Salt used to generate the encryption key based on the secret
21
+ secret_salt: 'ActiveEncryption salt: *RANDOM_SALT*'
22
+ # Number of iterations for PBKDF2 on the secret.
23
+ secret_iterations: <%= Rails.env.test? ? 1 : 2**16 %>
24
+ # Cipher to use. Can be any cipher returned by OpenSSL::Cipher.ciphers.
25
+ cipher: aes-256-gcm
26
+ # Digest to use to sign. Default is SHA1. Recommended is SHA256.
27
+ # Ignored when using an AEAD cipher like 'aes-256-gcm'.
28
+ # digest: SHA256
29
+
30
+ # my_other_setting:
31
+ # secret: <%= Rails.application.credentials.active_encryption_key1 %>
32
+ # secret_salt: 'ActiveEncryption salt: *RANDOM_SALT*'
33
+ # secret_iterations: <%= Rails.env.test? ? 1 : 2**16 %>
34
+ # cipher: aes-128-gcm
metadata ADDED
@@ -0,0 +1,242 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_encryption
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Arnaud Germis
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIEODCCAqCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhhcm5h
14
+ dWQvREM9emlyY29kZS9EQz1jb20wHhcNMTkwNzE4MTQ0OTE4WhcNMjAwNzE3MTQ0
15
+ OTE4WjAjMSEwHwYDVQQDDBhhcm5hdWQvREM9emlyY29kZS9EQz1jb20wggGiMA0G
16
+ CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDltdBv6MnjmokVZEkhubGk0NfEiU4C
17
+ WZZLNgN+FpyK5VNDvGvs8+OTusYCw07HFkhKVF2T+3A1XlYZKOXozCFBoQtL5ted
18
+ Nxy8yo874kcF5M6EV22np8/SefOJrpk4Wgvz4xdwT24LjZpmLHWFPXuVuqI4LZ7Q
19
+ Eh6sjVfG1h0SBSF8RjCCmEXONsz+ceDWvBKdBUSYfVt0HGmDSXYJByF4I8onkeUc
20
+ xxmLCu8VxZvnHrEw94BRPiEI1oUJ+3etNu2MYcK3pnLc+p9zYQ/NjS0Bsa423fmZ
21
+ 5K0Z4qiN550vccPZxRoMk9eiZHL8dN+ZgxG4+2o+ouCYRkLnkCyDR4rr7zLIcojo
22
+ 53iJqFF8cJtkectMOhNOO9jh/FMsJZnKWBzJ4/J3xHSLz4gD4/47WSwjAJ4tLHGC
23
+ 4VpzfD53vdr3i5RvB7bv3QiePUR2vV5AUap2S7TKJ+ojQVoh7TfJP3N5nwVspQkh
24
+ C3goXVkz5Op9TkLN3oUGqnveL9nC4y6e180CAwEAAaN3MHUwCQYDVR0TBAIwADAL
25
+ BgNVHQ8EBAMCBLAwHQYDVR0OBBYEFBNAzBaMirBd5+1xszQeddjvuLdCMB0GA1Ud
26
+ EQQWMBSBEmFybmF1ZEB6aXJjb2RlLmNvbTAdBgNVHRIEFjAUgRJhcm5hdWRAemly
27
+ Y29kZS5jb20wDQYJKoZIhvcNAQELBQADggGBAGvmnHTVKwGAlqB93/QZ19MBUrFm
28
+ vIxkoWYi/GlZnJGsApFwZtOsNaAFxYIVfAR7fZjQtCB7B6ZyERZF+m8J3tC23eTG
29
+ PadrSjz3SPbFJlCIqJ0NllSvx5E+98b9pq9tIyaeFbYnII1qoy+SIiWOurVS4dWr
30
+ dkmUsJvxyNJ+3yoVt568UFSf/YZ88GaabEAL5JFwXIpv/cxaej9M2bALPkP7HUm/
31
+ rgSmTctYicJomzzQ5LSLhdVSV+z5w2L5roIu5bPEQJyWIj6pZCthACPMR/emsLQ2
32
+ T9JFyENPrM2CUtwBaLQacRInp5zRWueDKIf0I+vNjRKu5PwEeePVn2VlkcQTuhUT
33
+ Vgg0CeGsGrJdcSohxH13t3gx4QXH0SA+4HPW7uqEeIQLwmBA56nCi6jAgTGAZhjX
34
+ UsJ7gUgNcBEuCAwgXmVzhEQ50pTMVRAL2cQKqnFkqehpRJ+78n+psW480iLqmjq3
35
+ GzWvrPCkKt17EBe3MSjjMsq80n5C1eaKRQA9Vw==
36
+ -----END CERTIFICATE-----
37
+ date: 2019-07-19 00:00:00.000000000 Z
38
+ dependencies:
39
+ - !ruby/object:Gem::Dependency
40
+ name: activesupport
41
+ requirement: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: 5.0.0
46
+ - - "<="
47
+ - !ruby/object:Gem::Version
48
+ version: '6.1'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: 5.0.0
56
+ - - "<="
57
+ - !ruby/object:Gem::Version
58
+ version: '6.1'
59
+ - !ruby/object:Gem::Dependency
60
+ name: railties
61
+ requirement: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: 5.0.0
66
+ - - "<="
67
+ - !ruby/object:Gem::Version
68
+ version: '6.1'
69
+ type: :runtime
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 5.0.0
76
+ - - "<="
77
+ - !ruby/object:Gem::Version
78
+ version: '6.1'
79
+ - !ruby/object:Gem::Dependency
80
+ name: bundler
81
+ requirement: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - "~>"
84
+ - !ruby/object:Gem::Version
85
+ version: '2.0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - "~>"
91
+ - !ruby/object:Gem::Version
92
+ version: '2.0'
93
+ - !ruby/object:Gem::Dependency
94
+ name: rake
95
+ requirement: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '10.0'
100
+ type: :development
101
+ prerelease: false
102
+ version_requirements: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - "~>"
105
+ - !ruby/object:Gem::Version
106
+ version: '10.0'
107
+ - !ruby/object:Gem::Dependency
108
+ name: reek
109
+ requirement: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - "~>"
112
+ - !ruby/object:Gem::Version
113
+ version: 5.4.0
114
+ type: :development
115
+ prerelease: false
116
+ version_requirements: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - "~>"
119
+ - !ruby/object:Gem::Version
120
+ version: 5.4.0
121
+ - !ruby/object:Gem::Dependency
122
+ name: rspec
123
+ requirement: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - "~>"
126
+ - !ruby/object:Gem::Version
127
+ version: '3.0'
128
+ type: :development
129
+ prerelease: false
130
+ version_requirements: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - "~>"
133
+ - !ruby/object:Gem::Version
134
+ version: '3.0'
135
+ - !ruby/object:Gem::Dependency
136
+ name: rubocop
137
+ requirement: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - "~>"
140
+ - !ruby/object:Gem::Version
141
+ version: 0.72.0
142
+ type: :development
143
+ prerelease: false
144
+ version_requirements: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - "~>"
147
+ - !ruby/object:Gem::Version
148
+ version: 0.72.0
149
+ - !ruby/object:Gem::Dependency
150
+ name: rubocop-rspec
151
+ requirement: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - "~>"
154
+ - !ruby/object:Gem::Version
155
+ version: 1.33.0
156
+ type: :development
157
+ prerelease: false
158
+ version_requirements: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - "~>"
161
+ - !ruby/object:Gem::Version
162
+ version: 1.33.0
163
+ - !ruby/object:Gem::Dependency
164
+ name: simplecov
165
+ requirement: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - "~>"
168
+ - !ruby/object:Gem::Version
169
+ version: 0.17.0
170
+ type: :development
171
+ prerelease: false
172
+ version_requirements: !ruby/object:Gem::Requirement
173
+ requirements:
174
+ - - "~>"
175
+ - !ruby/object:Gem::Version
176
+ version: 0.17.0
177
+ description:
178
+ email:
179
+ - hello@zircode.com
180
+ - arnaud@zircode.com
181
+ executables: []
182
+ extensions: []
183
+ extra_rdoc_files: []
184
+ files:
185
+ - ".editorconfig"
186
+ - ".gitignore"
187
+ - ".rspec"
188
+ - ".rubocop.yml"
189
+ - ".travis.yml"
190
+ - CHANGELOG.md
191
+ - CODE_OF_CONDUCT.md
192
+ - Gemfile
193
+ - LICENSE.txt
194
+ - README.md
195
+ - Rakefile
196
+ - active_encryption.gemspec
197
+ - bin/console
198
+ - bin/setup
199
+ - certs/garnu.pem
200
+ - lib/active_encryption.rb
201
+ - lib/active_encryption/adapters.rb
202
+ - lib/active_encryption/adapters/active_record.rb
203
+ - lib/active_encryption/configuration.rb
204
+ - lib/active_encryption/configuration/store.rb
205
+ - lib/active_encryption/encryptable.rb
206
+ - lib/active_encryption/encryptable/instance_methods_on_activation.rb
207
+ - lib/active_encryption/encryption_setting/key.rb
208
+ - lib/active_encryption/encryption_setting/record.rb
209
+ - lib/active_encryption/encryption_setting/yaml_store.rb
210
+ - lib/active_encryption/encryptor.rb
211
+ - lib/active_encryption/version.rb
212
+ - lib/generators/active_encryption/install_generator.rb
213
+ - lib/generators/templates/active_encryption.rb
214
+ - lib/generators/templates/encryption_settings.yml
215
+ homepage: https://github.com/Zircode/active_encryption
216
+ licenses:
217
+ - MIT
218
+ metadata:
219
+ homepage_uri: https://github.com/Zircode/active_encryption
220
+ source_code_uri: https://github.com/Zircode/active_encryption
221
+ changelog_uri: https://github.com/Zircode/active_encryption/CHANGELOG.md
222
+ bug_tracker_uri: https://github.com/Zircode/active_encryption/issues
223
+ post_install_message:
224
+ rdoc_options: []
225
+ require_paths:
226
+ - lib
227
+ required_ruby_version: !ruby/object:Gem::Requirement
228
+ requirements:
229
+ - - ">="
230
+ - !ruby/object:Gem::Version
231
+ version: '2.3'
232
+ required_rubygems_version: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - ">="
235
+ - !ruby/object:Gem::Version
236
+ version: '0'
237
+ requirements: []
238
+ rubygems_version: 3.0.3
239
+ signing_key:
240
+ specification_version: 4
241
+ summary: ActiveEncryption transparently encrypt (and decrypt!) attributes with ActiveSupport::MessageEncryptor
242
+ test_files: []
Binary file