README.md in crypt_keeper-1.1.1 vs README.md in crypt_keeper-2.0.0.rc1
- old
+ new
@@ -13,11 +13,11 @@
3. Provides a `decrypt` method that returns the plaintext
Note: Any options defined using `crypt_keeper` will be passed to `new` as a
hash.
-You can see an AES example [here](https://github.com/jmazzi/crypt_keeper/blob/master/lib/crypt_keeper/provider/aes_new.rb).
+You can see an example [here](https://github.com/jmazzi/crypt_keeper/blob/master/lib/crypt_keeper/provider/active_support.rb).
## Why?
The options available were either too complicated under the hood or had weird
edge cases that made the library hard to use. I wanted to write something
@@ -25,11 +25,11 @@
## Usage
```ruby
class MyModel < ActiveRecord::Base
- crypt_keeper :field, :other_field, :encryptor => :aes_new, :key => 'super_good_password', salt: 'salt'
+ crypt_keeper :field, :other_field, encryptor: :active_support, key: 'super_good_password', salt: 'salt'
end
model = MyModel.new(field: 'sometext')
model.save! #=> Your data is now encrypted
model.field #=> 'sometext'
@@ -51,11 +51,11 @@
You can force an encoding on the plaintext before encryption and after decryption by using the `encoding` option. This is useful when dealing with multibyte strings:
```ruby
class MyModel < ActiveRecord::Base
- crypt_keeper :field, :other_field, :encryptor => :aes_new, :key => 'super_good_password', salt: 'salt', :encoding => 'UTF-8'
+ crypt_keeper :field, :other_field, encryptor: :active_support, key: 'super_good_password', salt: 'salt', encoding: 'UTF-8'
end
model = MyModel.new(field: 'Tromsø')
model.save! #=> Your data is now encrypted
model.field #=> 'Tromsø'
@@ -66,24 +66,24 @@
If you are working with an existing table you would like to encrypt, you must use the `MyExistingModel.encrypt_table!` class method.
```ruby
class MyExistingModel < ActiveRecord::Base
- crypt_keeper :field, :other_field, :encryptor => :aes_new, :key => 'super_good_password', salt: 'salt'
+ crypt_keeper :field, :other_field, encryptor: :active_support, key: 'super_good_password', salt: 'salt'
end
MyExistingModel.encrypt_table!
```
Running `encrypt_table!` will encrypt all rows in the database using the encryption method specificed by the `crypt_keeper` line in your model.
## Supported Available Encryptors
-There are four supported encryptors: `aes_new`, `mysql_aes_new`, `postgres_pgp`, `postgres_pgp_public_key`.
+There are four supported encryptors: `active_support`, `mysql_aes_new`, `postgres_pgp`, `postgres_pgp_public_key`.
-* [AES New](https://github.com/jmazzi/crypt_keeper/blob/master/lib/crypt_keeper/provider/aes_new.rb)
- * Encryption is peformed using AES-256 via OpenSSL.
+* [ActiveSupport](https://github.com/jmazzi/crypt_keeper/blob/master/lib/crypt_keeper/provider/active_support.rb)
+ * Encryption is performed using [ActiveSupport::MessageEncryptor](http://api.rubyonrails.org/classes/ActiveSupport/MessageEncryptor.html)
* Passphrases are derived using [PBKDF2](http://en.wikipedia.org/wiki/PBKDF2)
* [MySQL AES New](https://github.com/jmazzi/crypt_keeper/blob/master/lib/crypt_keeper/provider/mysql_aes_new.rb)
* Encryption is peformed MySQL's native AES functions.
* ActiveRecord logs are [automatically](https://github.com/jmazzi/crypt_keeper/blob/master/lib/crypt_keeper/log_subscriber/mysql_aes.rb)
@@ -109,12 +109,12 @@
* Passphrases are hashed by PostgresSQL itself using a [String2Key (S2K)](http://www.postgresql.org/docs/9.2/static/pgcrypto.html) algorithm. This is rather similar to crypt() algorithms — purposefully slow and with random salt — but it produces a full-length binary key.
## Searching
Searching ciphertext is a complex problem that varies depending on the encryption algorithm you choose. All of the bundled providers include search support, but they have some caveats.
-* AES
- * The Ruby implementation of AES uses a random initialization vector. The same plaintext encrypted multiple times will have different output each time for the ciphertext. Since this is the case, it is not possible to search leveraging the database. Database rows will need to be filtered in memory. It is suggested that you use a scope or ActiveRecord batches to narrow the results before seaching them.
+* ActiveSupport::MessageEncryptor
+ * ActiveSupport's MessageEncryptor uses a random initialization vector when generating keys. The same plaintext encrypted multiple times will have different output each time for the ciphertext. Since this is the case, it is not possible to search leveraging the database. Database rows will need to be filtered in memory. It is suggested that you use a scope or ActiveRecord batches to narrow the results before seaching them.
* Mysql AES
* Surprisingly, MySQL's implementation of AES does not use a random initialization vector. The column containing the ciphertext can be indexed and searched quickly.
* PostgresSQL PGP
@@ -155,12 +155,37 @@
Just require your code and setup your model to use it. Just pass the class name
as a string or an underscored symbol
```ruby
class MyModel < ActiveRecord::Base
- crypt_keeper :field, :other_field, :encryptor => :my_encryptor, :key => 'super_good_password'
+ crypt_keeper :field, :other_field, encryptor: :my_encryptor, key: 'super_good_password'
end
```
+
+## Migrating from CryptKeeper 1.x to 2.0
+
+CryptKeeper 2.0 removes the AES encryptor due to security issues in the
+underlying AES gem. If you were previously using the `aes_new` encryptor, you
+will need to follow these instructions to reencrypt your data.
+
+The general migration path is as follows:
+
+1. Enable maintenance mode in any live apps
+2. Backup database
+3. Decrypt tables: TableName.decrypt_table!
+4. Update to 2.0.0.rc1 in your app. Update the encryptor to use :active_support
+5. Encrypt tables: `TableName.encrypt_table!`
+6. Verify data can be decrypted: `TableName.first`
+7. Disable maintenance mode if necessary
+
+In case you experience problems, the rollback procedure is as follows:
+
+1. Enable maintenance mode
+2. Backup database again
+3. Restore first database dump, from before CryptKeeper 2.0.0.rc1
+4. Verify data can be decrypted
+5. Disable maintenance mode
+6. Let us know what happened :(
## Requirements
CryptKeeper has been tested against ActiveRecord 4.2 and 5.0 using Ruby
2.1.10, 2.2.5 and 2.3.1.