- easy to use high-level crypto library for encrypted data storage/exchange
- can use derived encryption keys from password + salt
- can generate random keys and encrypt them by SSL public key (one or multiple)
- can handle HMAC signatures of encrypted data
- store multiple files in SQLite (ORM via peewee)
- store all necessary information and data in a single SQLite file
- store encrypted key/value pairs in SQLite (for usage in other python programs)
- allow encryption/decryption of streams (for usage in python programs that handle large data)
- CLI for file -> SQLite encryption
- based on cryptography and pynacl libraries
The CLI provides one part of the functionailty: Store encrypted files in a SQLite database file. This is intended for quick file storage (key derivation) or file exchange over insecure channels (public/private key). Multiple files are stored inside the same database. They are identified by their relativ path (on encryption: relative to CWD), and all paths are stored encrypted. Asymmetric keys are never stored, and symmetric encryption keys:
- are stored asymmetrically encrypted.
- and/or derived from a key derivation setup, that is stored in the database and requires the correct password.
The command cryp-to-go
should be accessable from the command line.
- The parameter
-s
sets the file name to use for the database. It defaults tocryp-to-go-safe.sqlite
. - Always choose an action: encrypt files
--encrypt
/-e
, decrypt files--decrypt
/-d
, list files--list
/-l
. - You can provide asymmetric keys:
- public key via
--pubkey
or-p
as string or file path - private key via
--private_key
or-k
as path to a PEM file. A passphrase will be requested, when it is necessary.
- public key via
- Encryption keys can either be restored by public key, or by password for key derivation.
If a new database file is created, the encryption keys will be created randomly,
if a public key is provided, and the
--always_derive
derive flag is not set. Otherwise a key derivation setup will be created and a password requested. - The public key is used to encrypt symmetric encryption keys.
It needs to be provided on
--encrypt
operations. It is possible to encrypt symmetric keys with multiple public keys, so multiple recepients get access. This is done via the--append_key
parameter with any action. - The files to encrypt/decrypt are the trailing arguments. List operation does not use them.
- Only files below CWD are allowed. This does not apply to the database file.
cryp-to-go --encrypt -s /tmp/ctg_example.sqlite -p ~/.ssh/id_rsa.pub README.md setup.py
cryp-to-go --list -s /tmp/ctg_example.sqlite -k ~/.ssh/id_rsa
cd /tmp
cryp-to-go --decrypt -s ctg_Example.sqlite -k ~/.ssh/id_rsa README.md
- The first line encrypts two files into a new container in
/tmp
. A public key is provided, so the owner of the private key can access the container. As the--always_derive
flag is not set, the encryptions keys are not derivable. This saves time, but means that the private key is the only way to access the decrypted content. - The second line lists the files contained. The private key is necessary. It's passphrase will be requested.
- The third line switches to a different directory, as we don't want to overwrite files in the original folder. Decryption is written relative to CWD!
- The last line executes the decryption of only one of the files. Again, the private key is required.
The core
module provides the lowest level functions and is intended for usage inside
other python modules. Besides some auxiliary functions (hexlify
, unhexlify
),
there are two auxiliary classes that might become relevant:
KeyDerivationSetup
creates and stores the settings for key derivation including salt. It is fully configurable and usesnacl.pwhash.argon2i
, but you will likely either usecreate_default
(always), orcreate_minimal
(unit tests only!). The latter makes key derivation very cheap and is therefore not suitable for anything else than tests. It provides serialization methods to be jsonifiable, and creates aCryptoHandler
with derived encyption keys with thegenerate_keys
method.AsymKey
is a wrapper for asymmetric keys -- public or private -- that provides easy access to encryption and decryption of short data fragments (like symmetric encryption keys).
The central class is the CryptoHandler
. It holds symmetric encryption and signature keys
and provides methods to encrypt, decrypt, sign and verify. Also, the create_random
factory
creates a new instance with random keys.
encrypt_stream
anddecrypt_stream
are generators that iterate over a stream and yield the encrypted/decrypted content. They work in encryption chunks and use theencrypt_chunk
anddecrypt_chunk
methods. They are at the core of most encryption operations and suitable to process large data.encrypt_snippet
anddecrypt_snippet
do the same, but without the streaming. They are intended for small pieces of data, like paths or dataset keys.- if the
CryptoHandler
has a signing keykey_sign
(usually set on creation via argument in factory methods), a signature can be calculated for the encrypted data. This happens on the fly, as the stream is encrypted, and only requires wrapping it in thecreate_signature
context manager. It can be accessed afterwards as thesignature
property. The encryption method already provides signatures for all chunks, so a total signature ensures only correct order, which is in most cases not a necessary increase in security, but might help with data integrity. To verify encrypted data, just wrap the decryption in theverify_signature
context manager. It ignoresNone
signatures, so you don't need to worry about missing isgnatures.
The interface
module contains interface(s) that provide core functionality in an
extended context. Currently only SQLiteFileInterface
exists. If another one is
added, a base class will be extracted.
The SQLiteFileInterface
handles encryption/decryption in the context of a SQLite
database. It manages storage of the key derivation setup
(store_key_derivation_setup
with counterpart load_crypto_handler
),
of pubkey-encrypted keys (store_keys_asymmetric
with load_crypto_handler_async
),
encrypted files (store_files
and restore_files
), and -- as additional
feature for potential usage in
other projects -- encrypted key-value pairs (store_values
with restore_files
(shared with file storage)).
It is the backbone of the CLI.