Kushal Das

FOSS and life. Kushal Das talks here.

kushal76uaid62oup5774umh654scnu5dwzh4u2534qxhcbi4wbab3ad.onion

Johnnycanencrypt 0.11.0 released

A couple of days ago I released Johnnycanencrypt v0.11.0. It is a Python module for OpenPGP written in Rust.

The most interesting update is for Linux users, now we have pre-built wheels for Python 3.8, 3.9, 3.10 & 3.11. You can just install that via python3 -m pip install johnnycanencrypt. You can also do the same on Intel Macs (for Python 3.10 and 3.11). But, I failed to build for Apple Silicon systems. I will work on it in the coming weeks.

To know the Yubikey card version we can call get_card_version function written in Rust.

>>> rjce.get_card_version()
(4, 3, 1)

Or directly use the function get_card_touch_policies to get a list of policies for the current Yubikey.

>>> import johnnycanencrypt as jce
>>> jce.get_card_touch_policies()
[TouchMode.On, TouchMode.Off, TouchMode.Fixed]

Then we now can also set the touch policies for a given Yubikey. For example:

rjce.set_keyslot_touch_policy(
    b"12345678", rjce.KeySlot.Authentication, rjce.TouchMode.On
)

It will be nice to see what people will build on top this. I also missed to blog about the v0.10.0 release. You should that changelog too.

Johnnycanencrypt 0.9.0 release

3 days ago I released Johnnycanencrypt 0.9.0. Here is the changelog:

- Adds `setuptools-rust` as build system.
- Key.uids now contains the certification details of each user id.
- `merge_keys` in rjce now takes a force boolean argument.
- `certify_key` can sign/certify another key by both card and on disk primary key.

The first biggest change is related to build system, now we are using setuptools-rust to build. This change happened as dkg is working towards packaging the module for Debian.

The other big change is about certifying someone's key. We can use the primary key (either on disk or on Yubikey) to do the signing.

k = ks.certify_key(
    my_key,
    k,
    ["Kushal Das <kushaldas@gmail.com>", "Kushal Das <kushal@fedoraproject.org>"],
    jce.SignatureType.PositiveCertification,
    password=password,
)

In the above example I am signing two user ids of the key k using my_key with a PositiveCertification.

johnnycanencrypt 0.7.0 released

Today I released Johnnycanencrypt 0.7.0. It has breaking change of some function names.

  • create_newkey renamed to create_key
  • import_cert renamed to import_key

But, the major work done are in few different places:

  • Handling errors better, no more normal Rust panics, instead providing better Python exceptions as CryptoError.
  • We can now sign bytes/files in both detached & in normal compressed binary form.
  • Signature can be done via smartcards, and verification works as usual.

In the Github release page you can find an OpenPGP signature, which you can use to verify the release. You can also verify via sigstore.

SIGSTORE_LOGLEVEL=debug python -m sigstore verify --cert-email mail@kushaldas.in --cert-oidc-issuer https://github.com/login/oauth johnnycanencrypt-0.7.0.tar.gz
DEBUG:sigstore._cli:parsed arguments Namespace(subcommand='verify', certificate=None, signature=None, cert_email='mail@kushaldas.in', cert_oidc_issuer='https://github.com/login/oauth', rekor_url='https://rekor.sigstore.dev', staging=False, files=[PosixPath('johnnycanencrypt-0.7.0.tar.gz')])
DEBUG:sigstore._cli:Using certificate from: johnnycanencrypt-0.7.0.tar.gz.crt
DEBUG:sigstore._cli:Using signature from: johnnycanencrypt-0.7.0.tar.gz.sig
DEBUG:sigstore._cli:Verifying contents from: johnnycanencrypt-0.7.0.tar.gz
DEBUG:sigstore._verify:Successfully verified signing certificate validity...
DEBUG:sigstore._verify:Successfully verified signature...
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): rekor.sigstore.dev:443
DEBUG:urllib3.connectionpool:https://rekor.sigstore.dev:443 "POST /api/v1/index/retrieve/ HTTP/1.1" 200 85
DEBUG:urllib3.connectionpool:https://rekor.sigstore.dev:443 "GET /api/v1/log/entries/362f8ecba72f4326972bc321d658ba3c9197b29bb8015967e755a97e1fa4758c13222bc07f26d27c HTTP/1.1" 200 None
DEBUG:sigstore._verify:Successfully verified Rekor entry...
OK: johnnycanencrypt-0.7.0.tar.gz

I took 8 months for this release, now time to write some tools to use it in more places :)

Trouble with signing and notarization on macOS for Tumpa

This week I released the first version of Tumpa on Mac. Though the actual changes required for building the Mac app and dmg file were small, but I had to reap apart those few remaining hairs on my head to get it working on any other Mac (than the building box). It was the classic case of Works on my laptop.

The issue

Tumpa is a Python application which uses PySide2 and also Johnnycanencrypt which is written in Rust.

I tried both briefcase tool and manual calling to codesign and create-dmg tools to create the tumpa.app and the tumpa-0.1.3.dmg.

After creating the dmg file, I had to submit it for notarisation to Apple, following:

xcrun /Applications/Xcode.app/Contents/Developer/usr/bin/altool --notarize-app --primary-bundle-id "in.kushaldas.Tumpa" -u "kushaldas@gmail.com" -p "@keychain:MYNOTARIZATION" -f macOS/tumpa-0.1.3.dmg

This worked successfully, after a few minutes I can see that the job passed. So, I can then staple the ticket on the dmg file.

xcrun stapler staple macOS/tumpa-0.1.3.dmg

I can install from the file, and run the application, sounds great.

But, whenever someone else tried to run the application after installing from dmg, it showed the following.

mac failure screenshot

Solution

It took me over 4 hours to keep trying all possible combinations, and finally I had to pass --options=runtime,library to the codesign tool, and that did the trick. Not being able to figure out how to get more logs on Mac was making my life difficult.

I had to patch briefcase to make sure I can keep using it (also created the upstream issue).

--- .venv/lib/python3.9/site-packages/briefcase/platforms/macOS/__init__.py	2022-01-07 08:48:12.000000000 +0100
+++ /tmp/__init__.py	2022-01-07 08:47:54.000000000 +0100
@@ -117,7 +117,7 @@
                     '--deep', str(path),
                     '--force',
                     '--timestamp',
-                    '--options', 'runtime',
+                    '--options', 'runtime,library',
                 ],
                 check=True,
             )

You can see my build script, which is based on input from Micah.

I want to thank all of my new friends inside of SUNET who were excellent helping hands to test the multiple builds of Tumpa. Later many folks from IRC also jumped in to help to test the tool.

Releasing Tumpa for Mac

I am happy to announce the release of Tumpa (The Usability Minded PGP Application) for Mac. This release contains the old UI (and the UI bugs), but creates RSA4096 keys by default. Right now Tumpa will allow the following:

  • Create new RSA4096 OpenPGP key. Remember to click on the “Authentication” subkey checkbox if you want to use the key for ssh.
  • Export the public key.
  • You can reset the Yubikey from the smartcard menu.
  • Allows to upload the subkeys to Yubikey (4 or 5).
  • Change the user pin/admin pin of the Yubikey.
  • Change the name and public key URL of the Yubikey.

The keys are stored at ~/.tumpa/ directory, you can back it up in an encrypted USB drive.

You can download the dmg file from my website.

$ wget https://kushaldas.in/tumpa-0.1.3.dmg
$ sha256sum ./tumpa-0.1.3.dmg 
6204cf3253fbe41ada91429684fccc0df87257f85345976d9468c8adf131c591  ./tumpa-0.1.3.dmg

Download & install from the dmg in the standard drag & drop style. If you are using one of the new M1 box, remember to click on “Open in Rosetta” for the application.

Tumpa opening on Mac

Click on “Open”.

Here is a GIF recorded on Linux, the functions are same in Mac.

Tumpa gif

Saptak (my amazing comaintainer) is working on a new website. He is also leading the development of the future UI, based on usability reports. We already saw a few UI issues on Mac (specially while generating a new key), those will be fixed in a future release.

Feel free to open issues as you find, find us in #tumpa channel on Libera.chat IRC network.

Johnnycanencrypt 0.6.0 released

A few days ago I released 0.6.0 of Johnnycanencrypt. It is a Python module written in Rust for OpenPGP using the amazing sequoia-pgp library. It allows you to access/use Yubikeys (without gpg-agent) directly from your code.

This release took almost an year. Though most of the work was done before, but I was not in a state to do a release.

Major changes

  • We can now sign and decrypt using both Curve25519 and RSA keys on the smartcard (we support only Yubikeys)
  • Changing of the password of the secret keys
  • Updating expiry date of the subkeys
  • Adding new user ID(s)
  • Revoking user ID(s)

I also released a new version of Tumpa which uses this. An updated package for Debian 11.

Using your OpenPGP key on Yubikey for ssh

Last week I wrote about how you can generate ssh keys on your Yubikeys and use them. There is another way of keeping your ssh keys secure, that is using your already existing OpenPGP key (along with authentication subkey) on a Yubikey and use it for ssh.

In this post I am not going to explain the steps on how to move your key to a Yubikey, but only the steps required to start using it for ssh access. Feel free to have a look at Tumpa if you want an easy way to upload keys to your card.

Enabling gpg-agent for ssh

First we have to add gpg-agent.conf file with correct configuration. Remember to use a different pinentry program if you are on Mac or KDE.

❯ echo "enable-ssh-support" >> ~/.gnupg/gpg-agent.conf
❯ echo "pinentry-program $(which pinentry-gnome)" >> ~/.gnupg/gpg-agent.conf
❯ echo "export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)" >> ~/.bash_profile
❯ source ~/.bash_profile 
❯ gpg --export-ssh-key <KEYID> > ~/.ssh/id_rsa_yubikey.pub

At this moment your public key (for ssh usage) is at ~/.ssh/id_rsa_yubikey.pub file. You can use it in the ~/.ssh/authorized_keys file on the servers as required.

We can then restart the gpg-agent using the following command and then also verify that the card is attached and gpg-agent can find it.

❯ gpgconf --kill gpg-agent
❯ gpg --card-status

Enabling touch policy on the card

We should also enable touch policy on the card for authentication operation. This means every time you will try to ssh using the Yubikey, you will have to touch the interface (it will be flashing the light till you touch it).

❯ ykman openpgp keys set-touch aut On
Enter Admin PIN: 
Set touch policy of authentication key to on? [y/N]: y

If you still have servers where you have only the old key, ssh client will be smart enough to ask you the passphrase for those keys.

Introducing Tumpa, to make OpenPGP simple with smartcards

Generating OpenPGP keys in an offline air-gapped system and then moving them into a smart card is always a difficult task for me. To remember the steps and command-line options of gpg2 correctly and then following them in the same order is difficult, and I had trouble enough number of times in doing so when I think about someone who is not into the command line that much, how difficult these steps are for them.

While having a chat with Saptak a few weeks ago, we came up with the idea of writing a small desktop tool to help. I started adding more features into my Johnnycanencrypt for the same. The OpenPGP operations are possible due to the amazing Sequoia project.

Introducing Tumpa

The work on the main application started during the holiday break, and today I am happy to release 0.1.0 version of Tumpa to make specific OpenPGP operations simple to use. It uses Johnnycanencrypt inside, and does not depend on the gpg.

Here is a small demo of the application running in a Tails (VM) environment. I am creating a new OpenPGP key with encryption and signing subkeys, and then putting them into a Yubikey. We are also setting the card holder's name via our tool.

Tumpa demo

We can also reset any Yubikey with just a click.

Reset Yubikey

You can download the Debian Buster package for Tails from the release page from Github. You can run from the source in Mac or Fedora too. But, if you are doing any real key generation, then you should try to do it in an air-gapped system.

You can install the package as dpkg -i ./tumpa_0.1.0+buster+nmu1_all.deb inside of Tails.

What are the current available features?

  • We can create a new OpenPGP key along with selected subkeys using Curve25519. By default, the tool will add three years for the expiration of the subkeys.
  • We can move the subkeys to a smart card. We tested only against Yubikeys as that is what we have.
  • We can set the name and public key URL on the card.
  • We can set the user pin and the admin pin of the smart card
  • We can reset a Yubikey.
  • We can export the public key for a selected key.

What is next?

A lot of work :) This is just the beginning. There are a ton of features we planned, and we will slowly add those. The UI also requires a lot of work and touch from a real UX person.

The default application will be very simple to use, and we will also have many advanced features, say changing subkey expiration dates, creating new subkeys, etc. for the advanced users.

We are also conducting user interviews (which takes around 20 minutes of time). If you have some time to spare to talk to us and provide feedback, please feel free to ping us via Twitter/mastodon/IRC.

We are available on #tumpa channel on Freenode. Come over and say hi :)

There are a lot of people I should thank for this release. Here is a quick list at random. Maybe I miss many names here, but you know that we could not do this without your help and guidance.

  • Sequoia team for all the guidance on OpenPGP.
  • Milosch Meriac for providing the guidance (and a ton of hardware).
  • Vincent Breitmoser, for keep explaining OpenKeyChain codebase to me to understand smart card operations
  • Anwesha Das for fixing the CI failures for Johnnycanencrypt, and documentation PRs.
  • Harlo and Micah, for all the amazing input for months.
  • Saptak Sengupta for being the amazing co-maintainer.

Johnnycanencrypt 0.4.0 released

Last night I released 0.4.0 of johnnycanencrypt module for OpenPGP in Python. This release has one update in the creating new key API. Now, we can pass one single UID as a string, or multiple in a list, or even pass None to the key creation method. This means we can have User ID-less certificates, which sequoia-pgp allows.

I also managed to fix the bug so that users can use pip to install the latest release from https://pypi.org.

You will need the rust toolchain, I generally install from https://rustup.rs.

For Fedora

sudo dnf install nettle clang clang-devel nettle-devel python3-devel

For Debian/Ubuntu

sudo apt install -y python3-dev libnettle6 nettle-dev libhogweed4 python3-pip python3-venv clang

Remember to upgrade your pip version inside of the virtual environment if you are in Buster.

For macOS

Install nettle via brew.

Installing the package

❯ python3 -m pip install johnnycanencrypt
Collecting johnnycanencrypt
  Downloading https://files.pythonhosted.org/packages/50/98/53ae56eb208ebcc6288397a66cf8ac9af5de53b8bbae5fd27be7cd8bb9d7/johnnycanencrypt-0.4.0.tar.gz (128kB)
     |████████████████████████████████| 133kB 6.4MB/s
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
    Preparing wheel metadata ... done
Building wheels for collected packages: johnnycanencrypt
  Building wheel for johnnycanencrypt (PEP 517) ... done
  Created wheel for johnnycanencrypt: filename=johnnycanencrypt-0.4.0-cp37-cp37m-macosx_10_7_x86_64.whl size=1586569 sha256=41ab04d3758479a063a6c42d07a15684beb21b1f305d2f8b02e820cb15853ae1
  Stored in directory: /Users/kdas/Library/Caches/pip/wheels/3f/63/03/8afa8176c89b9afefc11f48c3b3867cd6dcc82e865c310c90d
Successfully built johnnycanencrypt
Installing collected packages: johnnycanencrypt
Successfully installed johnnycanencrypt-0.4.0
WARNING: You are using pip version 19.2.3, however version 20.2.4 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

Now, you can import the module inside of your virtual environment :)

Note: In the future, I may change the name of the module to something more meaningful :)

Another try at a new Python module for OpenPGP aka johnnycanencrypt

Using OpenPGP from Python is a pain. There are various documentation/notes on the Internet explaining why, including the famous one from isis agora lovecraft where they explained why they changed the module name to pretty_bad_protocol.

sequoia-pgp is a Rust project to do OpenPGP from scratch in Rust, and as library first approach. You can see the status page to see how much work is already done.

Using this and Pyo3 project I started writing an experimental Python module for OpenPGP called Johnny Can Encrypt.

I just did an release of 0.1.0. Here is some example code.

>>> import johnnycanencrypt as jce
>>> j = jce.Johnny("secret.asc")
>>> data = j.encrypt_bytes("kushal 🐍".encode("utf-8"))
>>> print(data)
-----BEGIN PGP MESSAGE-----

wcFMAwhsWpR1vDokAQ//UQGjrmmPLP0Td8pELf8XZEPh6fY9Xad6XHH6vQjGwvjG
36kK8ejRqyLbZpwVOO1FUfiZt6AyaeIEeEagoolMxmFl67mWBHsw5Z2NUPhydAwJ
EX+VdFn6CtRzQ0xG3T7rOCrsR50COO13gc4fIAn7Rxj1DyjqlFvur10FNnxRm0iJ
jnOwPnWVWKwoROzevfQd1Oef0n4nbkDUuyrS9oHSRFhFF/9I9bGtJhho0VIIcmFG
YVkhR0+QROTZ4edKotUg0R3UUfHmfwT0XcybGWMG/8Nh3W8pYuxwDdtbSMNDZzxu
o9TdpLrgoRIkhyGmuYWrURrRN1hmce5B6XOagWu7aKL7pFhP7Vd6LLoliDwY4G6x
1yKHbSo/1FEof7WBDujCksuVedUO8Gs9giitR/p/U9PBadeyiW0CKTYiTURkkNiF
g79lVfbmM54eZ9zmU+PraVNpekYXvH3o+lvXd5T39mo4Y/dv2fDCjo2aiZ/bE56Q
yn/0Hhmj2ikrsUk3NcuhO4zxt+VLctJt+lfk+R2hal+6NTaRkREdprPp4ltAt/bm
8xwBmqp+FDdxGgY+ItJkG69vsIf4WpPsvBI37fVbeYqrPsaz9NGlz2QKdfQvaH7j
R7rgxf24H2FjbbyNuHF3tJJa4Kfpnhq4nkxA/EdRP9JcVm/X568jLayTLyJGmrbS
PAHlVMLSBXQDApkY+5Veu3teRR5M2BLPr7X/gfeNnTlbZ4kF5S+E+0bjTjrz+6oo
dcsnTYxmcAm9hdPjng==
=1IYb
-----END PGP MESSAGE-----

>>> result = j.decrypt_bytes(data.encode("utf-8"), "mysecretpassword")
>>> print(result.decode("utf-8"))
kushal 🐍

The readme of the project page has build instruction, and more details about available API calls. We can create new keypair (RSA4096). We can encrypt/decrypt bytes and files. We can also sign/verify bytes/files. The code does not have much checks for error handling, this is super early stage.

You will need nettle (on Fedora) and libnettle on Debian (and related development packages) to build it successfully.

I published wheels for Debian Buster (Python3.7), and Fedora 32 (Python3.8).

Issues in providing better wheels for pip install

The wheels are linked against system provided nettle library. And every distribution has a different version. Means even if I am building a python3.7 wheel on Debian, it will not work on Fedora. I wish to find a better solution to this in the coming days.

As I said earlier in this post, this is just starting of this project. It will take time to mature for production use. And because of Sequoia, we will have better defaults of cipher/hash options.