encrypt-vigen 0.0.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +21 -0
- data/README.md +722 -0
- data/lib/encryptvigen.rb +18 -0
- data/lib/{encryptv.rb → encryptvigen/encryptv.rb} +4 -7
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a79e3a2431131f82dbe4cded80e7d2820624c4a383a156bc288223e2cc7f8ed
|
4
|
+
data.tar.gz: fc0600144fe29897435c7b2443de5270aaa6d142cf5970cefc662b24a1224ab3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bef727c2e845bbc04de14067b519b6fc8924708015fefd574572fd379f6a27baaeb2b620dfd7107a56c740ba3833d38ba5a595ade5d4f51420bfdf0e5b86a5bf
|
7
|
+
data.tar.gz: dc22242080fc899c866b98e6c262f10853b37f0058e3599e1ede3c0627c8098cffa22521eb836390ce885a0875f822835fbb3f3b2ac58083d753b622eb15785b
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2016 Roberto Decurnex
|
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 all
|
13
|
+
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 THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,722 @@
|
|
1
|
+
# Nav
|
2
|
+
|
3
|
+
:package: Modern encryption for Rails
|
4
|
+
|
5
|
+
- Uses state-of-the-art algorithms
|
6
|
+
- Works with database fields, files, and strings
|
7
|
+
- Stores encrypted data in a single field
|
8
|
+
- Requires you to only manage a single encryption key (with the option to have more)
|
9
|
+
- Makes migrating existing data and key rotation easy
|
10
|
+
|
11
|
+
Learn [the principles behind it](https://ankane.org/modern-encryption-rails), [how to secure emails](https://ankane.org/securing-user-emails-lockbox), and [how to secure sensitive data in Rails](https://ankane.org/sensitive-data-rails)
|
12
|
+
|
13
|
+
[](https://travis-ci.org/ankane/lockbox)
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
Add this line to your application’s Gemfile:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
gem 'lockbox'
|
21
|
+
```
|
22
|
+
|
23
|
+
## Key Generation
|
24
|
+
|
25
|
+
Generate an encryption key
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
Lockbox.generate_key
|
29
|
+
```
|
30
|
+
|
31
|
+
Store the key with your other secrets. This is typically Rails credentials or an environment variable ([dotenv](https://github.com/bkeepers/dotenv) is great for this). Be sure to use different keys in development and production. Keys don’t need to be hex-encoded, but it’s often easier to store them this way.
|
32
|
+
|
33
|
+
Set the following environment variable with your key (you can use this one in development)
|
34
|
+
|
35
|
+
```sh
|
36
|
+
LOCKBOX_MASTER_KEY=0000000000000000000000000000000000000000000000000000000000000000
|
37
|
+
```
|
38
|
+
|
39
|
+
or create `config/initializers/lockbox.rb` with something like
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
Lockbox.master_key = Rails.application.credentials.lockbox_master_key
|
43
|
+
```
|
44
|
+
|
45
|
+
Alternatively, you can use a [key management service](#key-management) to manage your keys.
|
46
|
+
|
47
|
+
## Instructions
|
48
|
+
|
49
|
+
Database fields
|
50
|
+
|
51
|
+
- [Active Record](#active-record)
|
52
|
+
- [Mongoid](#mongoid)
|
53
|
+
|
54
|
+
Files
|
55
|
+
|
56
|
+
- [Active Storage](#active-storage)
|
57
|
+
- [CarrierWave](#carrierwave)
|
58
|
+
- [Shrine](#shrine)
|
59
|
+
- [Local Files](#local-files)
|
60
|
+
|
61
|
+
Other
|
62
|
+
|
63
|
+
- [Strings](#strings)
|
64
|
+
|
65
|
+
## Database Fields
|
66
|
+
|
67
|
+
### Active Record
|
68
|
+
|
69
|
+
Create a migration with:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
class AddEmailCiphertextToUsers < ActiveRecord::Migration[6.0]
|
73
|
+
def change
|
74
|
+
add_column :users, :email_ciphertext, :text
|
75
|
+
end
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
Add to your model:
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
class User < ApplicationRecord
|
83
|
+
encrypts :email
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
87
|
+
You can use `email` just like any other attribute.
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
User.create!(email: "hi@example.org")
|
91
|
+
```
|
92
|
+
|
93
|
+
If you need to query encrypted fields, check out [Blind Index](https://github.com/ankane/blind_index).
|
94
|
+
|
95
|
+
#### Types
|
96
|
+
|
97
|
+
Specify the type of a field with:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
class User < ApplicationRecord
|
101
|
+
encrypts :born_on, type: :date
|
102
|
+
encrypts :signed_at, type: :datetime
|
103
|
+
encrypts :opens_at, type: :time
|
104
|
+
encrypts :active, type: :boolean
|
105
|
+
encrypts :salary, type: :integer
|
106
|
+
encrypts :latitude, type: :float
|
107
|
+
encrypts :video, type: :binary
|
108
|
+
encrypts :properties, type: :json
|
109
|
+
encrypts :settings, type: :hash
|
110
|
+
end
|
111
|
+
```
|
112
|
+
|
113
|
+
**Note:** Always use a `text` or `binary` column for the ciphertext in migrations, regardless of the type
|
114
|
+
|
115
|
+
Lockbox automatically works with serialized fields for maximum compatibility with existing code and libraries.
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
class User < ApplicationRecord
|
119
|
+
serialize :properties, JSON
|
120
|
+
store :settings, accessors: [:color, :homepage]
|
121
|
+
attribute :configuration, CustomType.new
|
122
|
+
|
123
|
+
encrypts :properties, :settings, :configuration
|
124
|
+
end
|
125
|
+
```
|
126
|
+
|
127
|
+
For [StoreModel](https://github.com/DmitryTsepelev/store_model), use:
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
class User < ApplicationRecord
|
131
|
+
encrypts :configuration, type: Configuration.to_type
|
132
|
+
|
133
|
+
after_initialize do
|
134
|
+
self.configuration ||= {}
|
135
|
+
end
|
136
|
+
end
|
137
|
+
```
|
138
|
+
|
139
|
+
#### Validations
|
140
|
+
|
141
|
+
Validations work as expected with the exception of uniqueness. Uniqueness validations require a [blind index](https://github.com/ankane/blind_index).
|
142
|
+
|
143
|
+
### Mongoid
|
144
|
+
|
145
|
+
Add to your model:
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
class User
|
149
|
+
field :email_ciphertext, type: String
|
150
|
+
|
151
|
+
encrypts :email
|
152
|
+
end
|
153
|
+
```
|
154
|
+
|
155
|
+
You can use `email` just like any other attribute.
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
User.create!(email: "hi@example.org")
|
159
|
+
```
|
160
|
+
|
161
|
+
If you need to query encrypted fields, check out [Blind Index](https://github.com/ankane/blind_index).
|
162
|
+
|
163
|
+
## Files
|
164
|
+
|
165
|
+
### Active Storage
|
166
|
+
|
167
|
+
Add to your model:
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
class User < ApplicationRecord
|
171
|
+
has_one_attached :license
|
172
|
+
encrypts_attached :license
|
173
|
+
end
|
174
|
+
```
|
175
|
+
|
176
|
+
Works with multiple attachments as well.
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
class User < ApplicationRecord
|
180
|
+
has_many_attached :documents
|
181
|
+
encrypts_attached :documents
|
182
|
+
end
|
183
|
+
```
|
184
|
+
|
185
|
+
There are a few limitations to be aware of:
|
186
|
+
|
187
|
+
- Metadata like image width and height are not extracted when encrypted
|
188
|
+
- Direct uploads cannot be encrypted
|
189
|
+
|
190
|
+
To serve encrypted files, use a controller action.
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
def license
|
194
|
+
send_data @user.license.download, type: @user.license.content_type
|
195
|
+
end
|
196
|
+
```
|
197
|
+
|
198
|
+
### CarrierWave
|
199
|
+
|
200
|
+
Add to your uploader:
|
201
|
+
|
202
|
+
```ruby
|
203
|
+
class LicenseUploader < CarrierWave::Uploader::Base
|
204
|
+
encrypt
|
205
|
+
end
|
206
|
+
```
|
207
|
+
|
208
|
+
Encryption is applied to all versions after processing.
|
209
|
+
|
210
|
+
To serve encrypted files, use a controller action.
|
211
|
+
|
212
|
+
```ruby
|
213
|
+
def license
|
214
|
+
send_data @user.license.read, type: @user.license.content_type
|
215
|
+
end
|
216
|
+
```
|
217
|
+
|
218
|
+
### Shrine
|
219
|
+
|
220
|
+
Create a box
|
221
|
+
|
222
|
+
```ruby
|
223
|
+
box = Lockbox.new(key: key)
|
224
|
+
```
|
225
|
+
|
226
|
+
Encrypt files before passing them to Shrine
|
227
|
+
|
228
|
+
```ruby
|
229
|
+
LicenseUploader.upload(box.encrypt_io(file), :store)
|
230
|
+
```
|
231
|
+
|
232
|
+
And decrypt them after reading
|
233
|
+
|
234
|
+
```ruby
|
235
|
+
box.decrypt(uploaded_file.read)
|
236
|
+
```
|
237
|
+
|
238
|
+
For models, encrypt with:
|
239
|
+
|
240
|
+
```ruby
|
241
|
+
license = params.require(:user).fetch(:license)
|
242
|
+
@user.license = box.encrypt_io(license)
|
243
|
+
```
|
244
|
+
|
245
|
+
To serve encrypted files, use a controller action.
|
246
|
+
|
247
|
+
```ruby
|
248
|
+
def license
|
249
|
+
send_data box.decrypt(@user.license.read), type: @user.license.mime_type
|
250
|
+
end
|
251
|
+
```
|
252
|
+
|
253
|
+
### Local Files
|
254
|
+
|
255
|
+
Read the file as a binary string
|
256
|
+
|
257
|
+
```ruby
|
258
|
+
message = File.binread("file.txt")
|
259
|
+
```
|
260
|
+
|
261
|
+
Then follow the instructions for encrypting a string below.
|
262
|
+
|
263
|
+
## Strings
|
264
|
+
|
265
|
+
Create a box
|
266
|
+
|
267
|
+
```ruby
|
268
|
+
box = Lockbox.new(key: key)
|
269
|
+
```
|
270
|
+
|
271
|
+
Encrypt
|
272
|
+
|
273
|
+
```ruby
|
274
|
+
ciphertext = box.encrypt(message)
|
275
|
+
```
|
276
|
+
|
277
|
+
Decrypt
|
278
|
+
|
279
|
+
```ruby
|
280
|
+
box.decrypt(ciphertext)
|
281
|
+
```
|
282
|
+
|
283
|
+
Decrypt and return UTF-8 instead of binary
|
284
|
+
|
285
|
+
```ruby
|
286
|
+
box.decrypt_str(ciphertext)
|
287
|
+
```
|
288
|
+
|
289
|
+
## Migrating Existing Data
|
290
|
+
|
291
|
+
Lockbox makes it easy to encrypt an existing column. Add a new column for the ciphertext, then add to your model:
|
292
|
+
|
293
|
+
```ruby
|
294
|
+
class User < ApplicationRecord
|
295
|
+
encrypts :email, migrating: true
|
296
|
+
end
|
297
|
+
```
|
298
|
+
|
299
|
+
Backfill the data in the Rails console:
|
300
|
+
|
301
|
+
```ruby
|
302
|
+
Lockbox.migrate(User)
|
303
|
+
```
|
304
|
+
|
305
|
+
Then update the model to the desired state:
|
306
|
+
|
307
|
+
```ruby
|
308
|
+
class User < ApplicationRecord
|
309
|
+
encrypts :email
|
310
|
+
|
311
|
+
# remove this line after dropping email column
|
312
|
+
self.ignored_columns = ["email"]
|
313
|
+
end
|
314
|
+
```
|
315
|
+
|
316
|
+
Finally, drop the unencrypted column.
|
317
|
+
|
318
|
+
## Key Rotation
|
319
|
+
|
320
|
+
To make key rotation easy, you can pass previous versions of keys that can decrypt.
|
321
|
+
|
322
|
+
### Active Record
|
323
|
+
|
324
|
+
For Active Record, use:
|
325
|
+
|
326
|
+
```ruby
|
327
|
+
class User < ApplicationRecord
|
328
|
+
encrypts :email, previous_versions: [{key: previous_key}]
|
329
|
+
end
|
330
|
+
```
|
331
|
+
|
332
|
+
To rotate, use:
|
333
|
+
|
334
|
+
```ruby
|
335
|
+
user.update!(email: user.email)
|
336
|
+
```
|
337
|
+
|
338
|
+
### Mongoid
|
339
|
+
|
340
|
+
For Mongoid, use:
|
341
|
+
|
342
|
+
```ruby
|
343
|
+
class User
|
344
|
+
encrypts :email, previous_versions: [{key: previous_key}]
|
345
|
+
end
|
346
|
+
```
|
347
|
+
|
348
|
+
To rotate, use:
|
349
|
+
|
350
|
+
```ruby
|
351
|
+
user.update!(email: user.email)
|
352
|
+
```
|
353
|
+
|
354
|
+
### Active Storage
|
355
|
+
|
356
|
+
For Active Storage use:
|
357
|
+
|
358
|
+
```ruby
|
359
|
+
class User < ApplicationRecord
|
360
|
+
encrypts_attached :license, previous_versions: [{key: previous_key}]
|
361
|
+
end
|
362
|
+
```
|
363
|
+
|
364
|
+
To rotate existing files, use:
|
365
|
+
|
366
|
+
```ruby
|
367
|
+
user.license.rotate_encryption!
|
368
|
+
```
|
369
|
+
|
370
|
+
### CarrierWave
|
371
|
+
|
372
|
+
For CarrierWave, use:
|
373
|
+
|
374
|
+
```ruby
|
375
|
+
class LicenseUploader < CarrierWave::Uploader::Base
|
376
|
+
encrypt previous_versions: [{key: previous_key}]
|
377
|
+
end
|
378
|
+
```
|
379
|
+
|
380
|
+
To rotate existing files, use:
|
381
|
+
|
382
|
+
```ruby
|
383
|
+
user.license.rotate_encryption!
|
384
|
+
```
|
385
|
+
|
386
|
+
### Strings
|
387
|
+
|
388
|
+
For strings, use:
|
389
|
+
|
390
|
+
```ruby
|
391
|
+
Lockbox.new(key: key, previous_versions: [{key: previous_key}])
|
392
|
+
```
|
393
|
+
|
394
|
+
## Fixtures
|
395
|
+
|
396
|
+
You can use encrypted attributes in fixtures with:
|
397
|
+
|
398
|
+
```yml
|
399
|
+
test_user:
|
400
|
+
email_ciphertext: <%= User.generate_email_ciphertext("secret").inspect %>
|
401
|
+
```
|
402
|
+
|
403
|
+
Be sure to include the `inspect` at the end or it won’t be encoded properly in YAML.
|
404
|
+
|
405
|
+
## Algorithms
|
406
|
+
|
407
|
+
### AES-GCM
|
408
|
+
|
409
|
+
This is the default algorithm. Rotate the key every 2 billion encryptions to minimize the chance of a [nonce collision](https://www.cryptologie.net/article/402/is-symmetric-security-solved/), which will expose the key.
|
410
|
+
|
411
|
+
### XSalsa20
|
412
|
+
|
413
|
+
You can also use XSalsa20, which uses an extended nonce so you don’t have to worry about nonce collisions. First, [install Libsodium](https://github.com/crypto-rb/rbnacl/wiki/Installing-libsodium). For Homebrew, use:
|
414
|
+
|
415
|
+
```sh
|
416
|
+
brew install libsodium
|
417
|
+
```
|
418
|
+
|
419
|
+
And add to your Gemfile:
|
420
|
+
|
421
|
+
```ruby
|
422
|
+
gem 'rbnacl'
|
423
|
+
```
|
424
|
+
|
425
|
+
Then add to your model:
|
426
|
+
|
427
|
+
|
428
|
+
```ruby
|
429
|
+
class User < ApplicationRecord
|
430
|
+
encrypts :email, algorithm: "xsalsa20"
|
431
|
+
end
|
432
|
+
```
|
433
|
+
|
434
|
+
Make it the default with:
|
435
|
+
|
436
|
+
```ruby
|
437
|
+
Lockbox.default_options = {algorithm: "xsalsa20"}
|
438
|
+
```
|
439
|
+
|
440
|
+
You can also pass an algorithm to `previous_versions` for key rotation.
|
441
|
+
|
442
|
+
#### XSalsa20 Deployment
|
443
|
+
|
444
|
+
##### Heroku
|
445
|
+
|
446
|
+
Heroku [comes with libsodium](https://devcenter.heroku.com/articles/stack-packages) preinstalled.
|
447
|
+
|
448
|
+
##### Ubuntu
|
449
|
+
|
450
|
+
For Ubuntu 18.04, use:
|
451
|
+
|
452
|
+
```sh
|
453
|
+
sudo apt-get install libsodium23
|
454
|
+
```
|
455
|
+
|
456
|
+
For Ubuntu 16.04, use:
|
457
|
+
|
458
|
+
```sh
|
459
|
+
sudo apt-get install libsodium18
|
460
|
+
```
|
461
|
+
|
462
|
+
##### Travis CI
|
463
|
+
|
464
|
+
On Bionic, add to `.travis.yml`:
|
465
|
+
|
466
|
+
```yml
|
467
|
+
addons:
|
468
|
+
apt:
|
469
|
+
packages:
|
470
|
+
- libsodium23
|
471
|
+
```
|
472
|
+
|
473
|
+
On Xenial, add to `.travis.yml`:
|
474
|
+
|
475
|
+
```yml
|
476
|
+
addons:
|
477
|
+
apt:
|
478
|
+
packages:
|
479
|
+
- libsodium18
|
480
|
+
```
|
481
|
+
|
482
|
+
##### CircleCI
|
483
|
+
|
484
|
+
Add a step to `.circleci/config.yml`:
|
485
|
+
|
486
|
+
```yml
|
487
|
+
- run:
|
488
|
+
name: install Libsodium
|
489
|
+
command: |
|
490
|
+
sudo apt-get install -y libsodium18
|
491
|
+
```
|
492
|
+
|
493
|
+
## Hybrid Cryptography
|
494
|
+
|
495
|
+
[Hybrid cryptography](https://en.wikipedia.org/wiki/Hybrid_cryptosystem) allows servers to encrypt data without being able to decrypt it.
|
496
|
+
|
497
|
+
Follow the instructions above for installing Libsodium and including `rbnacl` in your Gemfile.
|
498
|
+
|
499
|
+
Generate a key pair with:
|
500
|
+
|
501
|
+
```ruby
|
502
|
+
Lockbox.generate_key_pair
|
503
|
+
```
|
504
|
+
|
505
|
+
Store the keys with your other secrets. Then use:
|
506
|
+
|
507
|
+
```ruby
|
508
|
+
class User < ApplicationRecord
|
509
|
+
encrypts :email, algorithm: "hybrid", encryption_key: encryption_key, decryption_key: decryption_key
|
510
|
+
end
|
511
|
+
```
|
512
|
+
|
513
|
+
Make sure `decryption_key` is `nil` on servers that shouldn’t decrypt.
|
514
|
+
|
515
|
+
This uses X25519 for key exchange and XSalsa20 for encryption.
|
516
|
+
|
517
|
+
## Key Separation
|
518
|
+
|
519
|
+
The master key is used to generate unique keys for each column. This technique comes from [CipherSweet](https://ciphersweet.paragonie.com/internals/key-hierarchy). The table name and column name are both used in this process. If you need to rename a table with encrypted columns, or an encrypted column itself, get the key:
|
520
|
+
|
521
|
+
```ruby
|
522
|
+
Lockbox.attribute_key(table: "users", attribute: "email_ciphertext")
|
523
|
+
```
|
524
|
+
|
525
|
+
And set it directly before renaming:
|
526
|
+
|
527
|
+
```ruby
|
528
|
+
class User < ApplicationRecord
|
529
|
+
encrypts :email, key: ENV["USER_EMAIL_ENCRYPTION_KEY"]
|
530
|
+
end
|
531
|
+
```
|
532
|
+
|
533
|
+
## Key Management
|
534
|
+
|
535
|
+
You can use a key management service to manage your keys with [KMS Encrypted](https://github.com/ankane/kms_encrypted).
|
536
|
+
|
537
|
+
```ruby
|
538
|
+
class User < ApplicationRecord
|
539
|
+
encrypts :email, key: :kms_key
|
540
|
+
end
|
541
|
+
```
|
542
|
+
|
543
|
+
For CarrierWave, use:
|
544
|
+
|
545
|
+
```ruby
|
546
|
+
class LicenseUploader < CarrierWave::Uploader::Base
|
547
|
+
encrypt key: -> { model.kms_key }
|
548
|
+
end
|
549
|
+
```
|
550
|
+
|
551
|
+
**Note:** KMS Encrypted’s key rotation does not know to rotate encrypted files, so avoid calling `record.rotate_kms_key!` on models with file uploads for now.
|
552
|
+
|
553
|
+
## Padding
|
554
|
+
|
555
|
+
Add padding to conceal the exact length of messages.
|
556
|
+
|
557
|
+
```ruby
|
558
|
+
Lockbox.new(padding: true)
|
559
|
+
```
|
560
|
+
|
561
|
+
The block size for padding is 16 bytes by default. Change this with:
|
562
|
+
|
563
|
+
```ruby
|
564
|
+
Lockbox.new(padding: 32) # bytes
|
565
|
+
```
|
566
|
+
|
567
|
+
## Reference
|
568
|
+
|
569
|
+
Set default options in an initializer with:
|
570
|
+
|
571
|
+
```ruby
|
572
|
+
Lockbox.default_options = {algorithm: "xsalsa20"}
|
573
|
+
```
|
574
|
+
|
575
|
+
For database fields, encrypted data is encoded in Base64. If you use `binary` columns instead of `text` columns, set:
|
576
|
+
|
577
|
+
```ruby
|
578
|
+
class User < ApplicationRecord
|
579
|
+
encrypts :email, encode: false
|
580
|
+
end
|
581
|
+
```
|
582
|
+
|
583
|
+
## Compatibility
|
584
|
+
|
585
|
+
It’s easy to read encrypted data in another language if needed.
|
586
|
+
|
587
|
+
For AES-GCM, the format is:
|
588
|
+
|
589
|
+
- nonce (IV) - 12 bytes
|
590
|
+
- ciphertext - variable length
|
591
|
+
- authentication tag - 16 bytes
|
592
|
+
|
593
|
+
Here are [some examples](docs/Compatibility.md).
|
594
|
+
|
595
|
+
For XSalsa20, use the appropriate [Libsodium library](https://libsodium.gitbook.io/doc/bindings_for_other_languages).
|
596
|
+
|
597
|
+
## Migrating from Another Library
|
598
|
+
|
599
|
+
Lockbox makes it easy to migrate from another library without downtime. The example below uses `attr_encrypted` but the same approach should work for any library.
|
600
|
+
|
601
|
+
Let’s suppose your model looks like this:
|
602
|
+
|
603
|
+
```ruby
|
604
|
+
class User < ApplicationRecord
|
605
|
+
attr_encrypted :name, key: key
|
606
|
+
attr_encrypted :email, key: key
|
607
|
+
end
|
608
|
+
```
|
609
|
+
|
610
|
+
Create a migration with:
|
611
|
+
|
612
|
+
```ruby
|
613
|
+
class MigrateToLockbox < ActiveRecord::Migration[6.0]
|
614
|
+
def change
|
615
|
+
add_column :users, :name_ciphertext, :text
|
616
|
+
add_column :users, :email_ciphertext, :text
|
617
|
+
end
|
618
|
+
end
|
619
|
+
```
|
620
|
+
|
621
|
+
And add `encrypts` to your model with the `migrating` option:
|
622
|
+
|
623
|
+
```ruby
|
624
|
+
class User < ApplicationRecord
|
625
|
+
encrypts :name, :email, migrating: true
|
626
|
+
end
|
627
|
+
```
|
628
|
+
|
629
|
+
Then run:
|
630
|
+
|
631
|
+
```ruby
|
632
|
+
Lockbox.migrate(User)
|
633
|
+
```
|
634
|
+
|
635
|
+
Once all records are migrated, remove the `migrating` option and the previous model code (the `attr_encrypted` methods in this example).
|
636
|
+
|
637
|
+
```ruby
|
638
|
+
class User < ApplicationRecord
|
639
|
+
encrypts :name, :email
|
640
|
+
end
|
641
|
+
```
|
642
|
+
|
643
|
+
Then remove the previous gem from your Gemfile and drop its columns.
|
644
|
+
|
645
|
+
```ruby
|
646
|
+
class RemovePreviousEncryptedColumns < ActiveRecord::Migration[6.0]
|
647
|
+
def change
|
648
|
+
remove_column :users, :encrypted_name, :text
|
649
|
+
remove_column :users, :encrypted_name_iv, :text
|
650
|
+
remove_column :users, :encrypted_email, :text
|
651
|
+
remove_column :users, :encrypted_email_iv, :text
|
652
|
+
end
|
653
|
+
end
|
654
|
+
```
|
655
|
+
|
656
|
+
## Upgrading
|
657
|
+
|
658
|
+
### 0.2.0
|
659
|
+
|
660
|
+
0.2.0 brings a number of improvements. Here are a few to be aware of:
|
661
|
+
|
662
|
+
- Added `encrypts` method for database fields
|
663
|
+
- Added support for XSalsa20
|
664
|
+
- `attached_encrypted` is deprecated in favor of `encrypts_attached`.
|
665
|
+
|
666
|
+
#### Optional
|
667
|
+
|
668
|
+
To switch to a master key, generate a key:
|
669
|
+
|
670
|
+
```ruby
|
671
|
+
Lockbox.generate_key
|
672
|
+
```
|
673
|
+
|
674
|
+
And set `ENV["LOCKBOX_MASTER_KEY"]` or `Lockbox.master_key`.
|
675
|
+
|
676
|
+
Update your model:
|
677
|
+
|
678
|
+
```ruby
|
679
|
+
class User < ApplicationRecord
|
680
|
+
encrypts_attached :license, previous_versions: [{key: key}]
|
681
|
+
end
|
682
|
+
```
|
683
|
+
|
684
|
+
New uploads will be encrypted with the new key.
|
685
|
+
|
686
|
+
You can rotate existing records with:
|
687
|
+
|
688
|
+
```ruby
|
689
|
+
User.unscoped.find_each do |user|
|
690
|
+
user.license.rotate_encryption!
|
691
|
+
end
|
692
|
+
```
|
693
|
+
|
694
|
+
Once that’s complete, update your model:
|
695
|
+
|
696
|
+
```ruby
|
697
|
+
class User < ApplicationRecord
|
698
|
+
encrypts_attached :license
|
699
|
+
end
|
700
|
+
```
|
701
|
+
|
702
|
+
## History
|
703
|
+
|
704
|
+
View the [changelog](https://github.com/ankane/lockbox/blob/master/CHANGELOG.md)
|
705
|
+
|
706
|
+
## Contributing
|
707
|
+
|
708
|
+
Everyone is encouraged to help improve this project. Here are a few ways you can help:
|
709
|
+
|
710
|
+
- [Report bugs](https://github.com/ankane/lockbox/issues)
|
711
|
+
- Fix bugs and [submit pull requests](https://github.com/ankane/lockbox/pulls)
|
712
|
+
- Write, clarify, or fix documentation
|
713
|
+
- Suggest or add new features
|
714
|
+
|
715
|
+
To get started with development and testing:
|
716
|
+
|
717
|
+
```sh
|
718
|
+
git clone https://github.com/ankane/lockbox.git
|
719
|
+
cd lockbox
|
720
|
+
bundle install
|
721
|
+
bundle exec rake test
|
722
|
+
```
|
data/lib/encryptvigen.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Archivo encrypt_v/lib/encryptvigen.rb
|
2
|
+
|
3
|
+
# Clases
|
4
|
+
require_relative "./encryptvigen/encryptv.rb"
|
5
|
+
|
6
|
+
# Modulo de uso
|
7
|
+
module EncryptVigen
|
8
|
+
|
9
|
+
# Metodo para encriptar mensaje
|
10
|
+
def self.encrypt(msg, key)
|
11
|
+
return EncryptV.new.encrypt(msg, key)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Metodo para desencriptar mensaje
|
15
|
+
def self.decrypt(encrypted_msg, key)
|
16
|
+
return EncryptV.new.decrypt(encrypted_msg, key)
|
17
|
+
end
|
18
|
+
end
|
@@ -1,14 +1,11 @@
|
|
1
|
-
# Archivo encrypt_v/lib/encryptv.rb
|
1
|
+
# Archivo encrypt_v/lib/encryptvigen/encryptv.rb
|
2
2
|
class EncryptV
|
3
|
-
# Variables privadas de la clase
|
4
|
-
# @available_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ".split("")
|
5
|
-
|
6
3
|
# Acceso publico
|
7
|
-
|
4
|
+
|
8
5
|
# Metodos publicos
|
9
6
|
def encrypt(msg, key)
|
10
7
|
# Metodo para encriptar un mensaje
|
11
|
-
|
8
|
+
algorithm_encrypt_v(msg,key)
|
12
9
|
end
|
13
10
|
|
14
11
|
def decrypt(encrypted_msg, key)
|
@@ -22,7 +19,7 @@ class EncryptV
|
|
22
19
|
# Metodos privados
|
23
20
|
|
24
21
|
def index(ch)
|
25
|
-
# Devuelve la
|
22
|
+
# Devuelve la posicion del caracter en el hash
|
26
23
|
available_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ".split("")
|
27
24
|
available_chars.each_with_index { |c,i|
|
28
25
|
if c.eql? ch
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: encrypt-vigen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Juan Rodriguez
|
@@ -17,10 +17,13 @@ executables: []
|
|
17
17
|
extensions: []
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
|
-
-
|
20
|
+
- LICENSE.txt
|
21
|
+
- README.md
|
22
|
+
- lib/encryptvigen.rb
|
23
|
+
- lib/encryptvigen/encryptv.rb
|
21
24
|
homepage: https://github.com/engineer-jrg/EncryptV.git
|
22
25
|
licenses:
|
23
|
-
-
|
26
|
+
- MIT
|
24
27
|
metadata: {}
|
25
28
|
post_install_message:
|
26
29
|
rdoc_options: []
|
@@ -30,7 +33,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
30
33
|
requirements:
|
31
34
|
- - ">="
|
32
35
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
36
|
+
version: '1.0'
|
34
37
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
35
38
|
requirements:
|
36
39
|
- - ">="
|