Skip to content

matthiashuschle/cryp-to-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cryp-to-go

What is it?

  • 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

Usage

CLI

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

example

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.

Core

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 uses nacl.pwhash.argon2i, but you will likely either use create_default (always), or create_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 a CryptoHandler with derived encyption keys with the generate_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 and decrypt_stream are generators that iterate over a stream and yield the encrypted/decrypted content. They work in encryption chunks and use the encrypt_chunk and decrypt_chunk methods. They are at the core of most encryption operations and suitable to process large data.
  • encrypt_snippet and decrypt_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 key key_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 the create_signature context manager. It can be accessed afterwards as the signature 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 the verify_signature context manager. It ignores None signatures, so you don't need to worry about missing isgnatures.

Interface

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.