README.md in lockbox-0.4.6 vs README.md in lockbox-0.4.7

- old
+ new

@@ -188,10 +188,12 @@ end ``` ## Action Text +**Note:** Action Text uses direct uploads for files, which cannot be encrypted with application-level encryption like Lockbox. This only encrypts the database field. + Create a migration with: ```ruby class AddBodyCiphertextToRichTexts < ActiveRecord::Migration[6.0] def change @@ -262,12 +264,13 @@ end ``` There are a few limitations to be aware of: -- Metadata like image width and height are not extracted when encrypted -- Direct uploads cannot be encrypted +- Variants and previews aren’t supported when encrypted +- Metadata like image width and height aren’t extracted when encrypted +- Direct uploads can’t be encrypted with application-level encryption like Lockbox, but can use server-side encryption To serve encrypted files, use a controller action. ```ruby def license @@ -506,10 +509,28 @@ Lockbox.rotate(User, attributes: [:email]) ``` Once all records are rotated, you can remove `previous_versions` from the model. +### Action Text + +Update your initializer: + +```ruby +Lockbox.encrypts_action_text_body(previous_versions: [{key: previous_key}]) +``` + +Use `master_key` instead of `key` if passing the master key. + +To rotate existing records, use: + +```ruby +Lockbox.rotate(ActionText::RichText, attributes: [:body]) +``` + +Once all records are rotated, you can remove `previous_versions` from the initializer. + ### Active Storage Update your model: ```ruby @@ -548,10 +569,18 @@ User.find_each do |user| user.license.rotate_encryption! end ``` +For multiple files, use: + +```ruby +User.find_each do |user| + user.licenses.map(&:rotate_encryption!) +end +``` + Once all files are rotated, you can remove `previous_versions` from the model. ### Local Files & Strings For local files and strings, use: @@ -732,16 +761,36 @@ ## Key Management You can use a key management service to manage your keys with [KMS Encrypted](https://github.com/ankane/kms_encrypted). +For Active Record and Mongoid, use: + ```ruby class User < ApplicationRecord encrypts :email, key: :kms_key end ``` +For Action Text, use: + +```ruby +ActiveSupport.on_load(:action_text_rich_text) do + ActionText::RichText.has_kms_key +end + +Lockbox.encrypts_action_text_body(key: :kms_key) +``` + +For Active Storage, use: + +```ruby +class User < ApplicationRecord + encrypts_attached :license, key: :kms_key +end +``` + For CarrierWave, use: ```ruby class LicenseUploader < CarrierWave::Uploader::Base encrypt key: -> { model.kms_key } @@ -770,11 +819,11 @@ lockbox.encrypt("fail").bytesize # 44 lockbox.encrypt("clear").bytesize # 44 lockbox.encrypt("consider").bytesize # 44 ``` -The block size for padding is 16 bytes by default. If we have a status larger than 15 bytes, it will have a different length than the others. +The block size for padding is 16 bytes by default. Lockbox uses [ISO/IEC 7816-4](https://en.wikipedia.org/wiki/Padding_(cryptography)#ISO/IEC_7816-4) padding, which uses at least one byte, so if we have a status larger than 15 bytes, it will have a different length than the others. ```ruby box.encrypt("length15status!").bytesize # 44 box.encrypt("length16status!!").bytesize # 60 ``` @@ -783,22 +832,38 @@ ```ruby Lockbox.new(padding: 32) # bytes ``` +## Associated Data + +You can pass extra context during encryption to make sure encrypted data isn’t moved to a different context. + +```ruby +lockbox = Lockbox.new(key: key) +ciphertext = lockbox.encrypt(message, associated_data: "somecontext") +``` + +Without the same context, decryption will fail. + +```ruby +lockbox.decrypt(ciphertext, associated_data: "somecontext") # success +lockbox.decrypt(ciphertext, associated_data: "othercontext") # fails +``` + ## Binary Columns -You can use `binary` columns for the ciphertext instead of `text` columns to save space. +You can use `binary` columns for the ciphertext instead of `text` columns. ```ruby class AddEmailCiphertextToUsers < ActiveRecord::Migration[6.0] def change add_column :users, :email_ciphertext, :binary end end ``` -You should disable Base64 encoding if you do this. +Disable Base64 encoding to save space. ```ruby class User < ApplicationRecord encrypts :email, encode: false end