Cryppo is a cryptographic library that enables you to encrypt and decrypt data.
Pick an encryption strategy and encrypt away!
Add this line to your application's Gemfile:
gem 'cryppo'
And then execute:
$ bundle
Or install it yourself as:
$ gem install cryppo
When encrypting data with a user-generated passphrase or password, use the encrypt_with_derived_key
function.
The data will be encrypted with cryptographically secure key that is derived from the passphrase.
encryption_strategy = 'Aes256Gcm'
key_derivation_strategy = 'Pbkdf2Hmac'
user_passphrase = 'MyPassword!!'
data = 'some data to encrypt'
encrypted_data = Cryppo.encrypt_with_derived_key(encryption_strategy, key_derivation_strategy, user_passphrase, data)
The encryption process will return an EncryptedDataWithDerivedKey
object that contains all the encryption artifacts necessary to decrypt the encrypted data.
The data in this object can be serialized using the EncryptedDataWithDerivedKey#serialize
method.
The serialized payload can be stored directly in a database.
The serialized payload can later be loaded by using Cryppo.load(serialized_payload)
.
serialized_payload = encrypted_data.serialize
loaded_encrypted_data = Cryppo.load(serialized_payload)
Note: Never store the contents of objects of type Cryppo::EncryptionValues::EncryptionKey
. These objects contain keys used to encrypt the data. They should never be stored in the clear. They need to be kept safe and protected!!
To decrypt the encrypted data, we load the serialized encrypted data, and then decrypt with the users passphrase:
Following on from the encryption example:
user_passphrase = 'MyPassword!!'
encrypted_data = Cryppo.load(serialized_payload)
encrypted_data.decrypt(user_passphrase)
If you need, you can also encrypt using your own generated key using the generate_encryption_key
and the encrypt
functions:
encryption_strategy = 'Aes256Gcm'
key = Cryppo.generate_encryption_key(encryption_strategy) # this key needs to be kept safe
data = 'some data to encrypt'
encrypted_data = Cryppo.encrypt(encryption_strategy, key, data)
The encryption process will return an EncryptedData
object that contains all the encryption artefacts necessary to decrypt the encrypted data.
The data in this object can be serialized using the the EncryptedData#serialize
method.
The serialized payload can be stored directly in a database.
The serialized payload can later be loaded by using Cryppo.load(serialized_payload)
.
Note: Never store the contents of objects of type Cryppo::EncryptionValues::EncryptionKey
. These objects contain keys used to encrypt the data. They should never be stored in the clear. They need to be kept safe and protected!!
To decrypt the encrypted data, we load the serialized encrypted data, and then decrypt with the users passphrase:
Following on from the encryption example:
encrypted_data = Cryppo.load(serialized_payload)
encrypted_data.decrypt(key)
You can list all available encryption strategies with Cryppo.encryption_strategies
,
and all key derivation strategies with Cryppo.derivation_strategies
.
For authentication purposes, a sender can sign a message with their private key, and a recipient can verify this signature using the sender's public key.
# accepts the private key as a string, and the data to sign
serialized_signature = Cryppo.sign_with_private_key(private_key_string, data).serialize
# takes serialized signature and returns object of type Cryppo::EncryptionValues::RsaSignature
signature = Cryppo.load(serialized_signature)
# will return true if the private and public keys form a keypair
signature.verify(public_key_string)
The serialized signature contains the signing strategy, the encoded signature, and the data itself.
The serialization format of encrypted data is designed to be easy to parse and store.
There are two serialization formats:
- Encrypted data encrypted without a derived key
- Encrypted data encrypted with a derived key
A string containing 3 parts concatenated with a .
.
- Encryption Strategy Name: The stategy name as defined by EncryptionStrategy#strategy_name
- Encoded Encrypted Data: Encrypted Data is encoded with Base64.urlsafe_encode64
- Encoded Encryption Artefacts: Encryption Artefacts are serialized into a hash by EncryptionStrategy#serialize_artefact, converted to YAML, then encoded with Base64.urlsafe_encode64
A string containing 5 parts concatenated with a .
. The first 3 parts are the same as above.
- Key Derivation Strategy Name: The stategy name as defined by EncryptionStrategy#strategy_name
- Encoded Key Derivation Artefacts: Encryption Artefacts are serialized into a hash by EncryptionStrategy#serialize_artefact, converted to YAML, then encoded with Base64.urlsafe_encode64
Each strategy is responsible for serializing and deserializing any artefacts it produces. The goal is to produce a hash containing the artefacts required to decrypt the encrypted data. The keys should be stringified to enhance compatibility between different YAML implementations. The keys should optionally be abbreviated to reduce the serialized payload size.
The current strategies are wrappers around ruby's OpenSSL library.
Aes256Ofb was chosen because if the incorrect salt is used during decryption, the encrypted data will remain entirely encrypted.
Aes256Gcm was chosen because it provides authenticated encryption. An error will be raised if an incorrect value, such as the encryption key, were used during decryption. This means you can always be sure that the decrypted data is the same as the data that was originally encrypted.
The current key derivation strategies are wrappers around ruby's OpenSSL library.
Pbkdf2Hmac generates cryptographically secure keys from potentially insecure sources such as user-generated passwords.
The derived key is cryptographically secure such that brute force attacks directly on the encrypted data is infeasible. The amount of computational effort required to complete the operation can be tweaked. This ensures that brute force attacks on the password encrypted data.
- Provide a way for third parties to register additional encryption strategies and key derivation strategies
- Tag encryption strategies that can accept derived keys. Eg AES strategies can accept Pbkdf2 derived keys whereas Rsa4096 can only accept an OpenSSL::PKey::RSA as the encryption key.
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
.
Run rake spec
.
Use semantic versioning.
Update the version in following files:
- cryppo/lib/version.rb
- RELEASE.md - Don't remove
## Unreleased
. Instead, add the new version as a h2 heading underneath. - Gemfile.lock
Ensure the RELEASE.md has been updated with all the changes/fixes/additions. Ensure the README.md has been updated to reflect all the changes in this release. Ensure new specs have been added for new features. Ensure the specs pass. Commit the changes.
To release, run bundle exec rake release
. This will create a git tag for the version, and push git commits and tags.
Bug reports and pull requests are welcome on GitHub at https://github.com/Meeco/cryppo. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
Everyone interacting in the Cryppo project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.