Skip to content

Meeco/cryppo

Repository files navigation

Cryppo

Cryppo is a cryptographic library that enables you to encrypt and decrypt data.

Pick an encryption strategy and encrypt away!

Installation

Add this line to your application's Gemfile:

gem 'cryppo'

And then execute:

$ bundle

Or install it yourself as:

$ gem install cryppo

Usage

Encrypt and decrypt data using a derived key

Encryption

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)

Persisting Encrypted 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!!

Decryption

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)

Encrypt and decrypt data using a generated cryptographic key

If you need, you can also encrypt using your own generated key using the generate_encryption_key and the encrypt functions:

Encryption

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)

Persisting Encrypted 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!!

Decryption

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)

Available strategies

You can list all available encryption strategies with Cryppo.encryption_strategies, and all key derivation strategies with Cryppo.derivation_strategies.

Signing and verification

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.

Serialization Format

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

Encrypted data encrypted without a derived key

A string containing 3 parts concatenated with a ..

  1. Encryption Strategy Name: The stategy name as defined by EncryptionStrategy#strategy_name
  2. Encoded Encrypted Data: Encrypted Data is encoded with Base64.urlsafe_encode64
  3. Encoded Encryption Artefacts: Encryption Artefacts are serialized into a hash by EncryptionStrategy#serialize_artefact, converted to YAML, then encoded with Base64.urlsafe_encode64

Encrypted data encrypted with a derived key

A string containing 5 parts concatenated with a .. The first 3 parts are the same as above.

  1. Key Derivation Strategy Name: The stategy name as defined by EncryptionStrategy#strategy_name
  2. Encoded Key Derivation Artefacts: Encryption Artefacts are serialized into a hash by EncryptionStrategy#serialize_artefact, converted to YAML, then encoded with Base64.urlsafe_encode64

Serialization of encryption artefacts and key derivation artefacts

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.

Encryption Strategies

The current strategies are wrappers around ruby's OpenSSL library.

Aes256Ofb

Aes256Ofb was chosen because if the incorrect salt is used during decryption, the encrypted data will remain entirely encrypted.

Aes256Gcm

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.

Key Derivation Strategies

The current key derivation strategies are wrappers around ruby's OpenSSL library.

Pbkdf2Hmac

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.

Wishlist

  • 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.

Development

Setup

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.

Testing

Run rake spec.

Releasing a new version

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.

Contributing

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.

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.

About

An encryption library

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages