Introduction to johnnycanencrypt ================================ Johnnycanencrypt provides only a few selected operations from the OpenPGP spec. If you need more and better granular access to the operations, this may not be the module for you. The module has 2 parts, one high level API, which can be directly accessed via importing the module. There is another internal module with the same name (which is native in Rust), and has all the low level functions and classes. We will import the module as jce. :: >>> import johnnycanencrypt as jce The KeyStore ------------- The module interacts over a `KeyStore` object, which points to a directory path on the system. Inside of the directory, it will create a `jce.db` sqlite3 database if missing. Below is an example where we are creating a keystore in an empty directory at "/var/lib/myapplication/keys", and then we will import a few keys in there. For our example, we will use the keys from our tests directory. :: >>> ks = jce.KeyStore("/var/lib/myapplication/keys") >>> ks.import_key("tests/files/store/secret.asc") >>> ks.import_key("tests/files/store/pgp_keys.asc") >>> ks.import_key("tests/files/store/public.asc") Now, if we check the directory from the shell, we will find the keys imported there. :: ❯ ls -l /var/lib/myapplication/keys .rw-rw-r--@ 9.5k user 6 Oct 18:48 jce.db .. note:: This keystore directory is very much application specific. As a developer you should choose which directory on the system you will use as the key store. `SecureDrop `_ uses **/var/lib/securedrop/store** as their key storage (via gpg's python binding). .. warning:: This module does not handle keys still using `sha1` or `md5` for hash algorithms. If you are using any such old key, please generate new key and use them along wtih the module. `This function `_ explains in some details why. KeyStore path for the applicaitons which can run per user ---------------------------------------------------------- If you are writing a desktop application or any other tool which can have per user configuration, you should look into the `base dir spec `_. If your application name is **myapplication**, then the store path can be like: **$XDG_DATA_HOME/myapplication**. Encrypting and decrypting some bytes for a given fingerprint ------------------------------------------------------------- :: >>> ks = jce.KeyStore("tests/files/store") >>> key = ks.get_key("F4F388BBB194925AE301F844C52B42177857DD79") >>> enc = ks.encrypt(key, "Sequoia is amazing.") >>> print(enc[:27]) b'-----BEGIN PGP MESSAGE-----' >>> text = ks.decrypt(key, enc, "redhat") >>> print(text) b'Sequoia is amazing.' Verify Tor Browser download using the signature and public key --------------------------------------------------------------- In this example we will download the Tor Browser 10.0, and the signature and the public key using **wget**, and then verify via our module. :: curl -s -O https://dist.torproject.org/torbrowser/12.0.5/tor-browser-linux64-12.0.5_ALL.tar.xz curl -s -O https://dist.torproject.org/torbrowser/12.0.5/tor-browser-linux64-12.0.5_ALL.tar.xz.asc KEYURL=https://openpgpkey.torproject.org/.well-known/openpgpkey/torproject.org/hu/kounek7zrdx745qydx6p59t9mqjpuhdf curl -s -o kounek7zrdx745qydx6p59t9mqjpuhdf.pub $KEYURL Now let us import the key and verify. :: import tempfile import johnnycanencrypt as jce filename = "tor-browser-linux64-12.0.5_ALL.tar.xz" signame = "tor-browser-linux64-12.0.5_ALL.tar.xz.asc" with tempfile.TemporaryDirectory() as tmpdir: ks = jce.KeyStore(tmpdir) torkey = ks.import_key("kounek7zrdx745qydx6p59t9mqjpuhdf.pub") if ks.verify_file_detached(torkey, filename, signame): print("Verified.") else: print("Verification failed.")