trustcrypto / OnlyKey-App

The OnlyKey App is used for the initial setup and configuration of OnlyKey. Supported on Windows, macOS, Linux, and Chromebook (with Chrome App).
https://docs.crp.to/app.html
Other
105 stars 25 forks source link

Add support for GPG keys with multiple subkeys #166

Open LRitzdorf opened 3 years ago

LRitzdorf commented 3 years ago

While the OnlyKey documentation specifically mentions the case of OpenPGP keys with multiple subkeys (i.e. the primary signing key, the encryption subkey, and a secondary signing key), the app does not seem to support this case.

I tested this by generating a new Ed25519 keypair, which loaded onto the OnlyKey successfully. This process included a dialog that asked me to choose between loading the primary key and the first subkey (for signing and decryption, respectively). However, after adding a secondary signing subkey to this same original keypair (using gpg --expert --edit-key MY-KEYGRIP-HERE), the loading process failed.

I attempted to load the full keypair, as given by gpg --armor --export-secret-key MY-KEYGRIP-HERE, which gave a TypeError: Cannot read property 'data' of undefined in the app. I also tried the encryption subkey on its own, as given by gpg --armor --export-secret-subkey MY-KEYGRIP-HERE, but this gave an Error parsing PGP key: Invalid enum value.

Ideally, when reading in a key with multiple subkeys, we would simply add options to the subkey selection dialog mentioned above. At the moment, however, it appears that the app doesn't even parse the input correctly, so that's probably the first piece to fix.

onlykey commented 3 years ago

We currently use OpenPGP.js to parse keys, GPG supports things that OpenPGP.js does not so keep that in mind. The mention of multiple subkeys was for RSA where a primary 4096 key is used and two 2048 subkeys, we currently don't have support for multiple ECC subkeys we may be able to add this in future app release. There is also the option of manually loading the raw ECC keys (private is 32 bytes) on the advanced tab.

LRitzdorf commented 3 years ago

Ah, good to know. Thanks!

I realize this isn't directly on topic, but could someone point me toward an article or docs page that outlines how to get the raw ECC key? I'd seen that section of the app, but I'm unclear on how to extract the "raw" key from the key file. (Maybe worth adding a section on this to the OnlyKey docs?)

onlykey commented 3 years ago

I will have to look into how to do this with GPG keys. Here is how to do it with OpenSSL keys:

Generate ECC prime256v1 Private Key $ openssl ecparam -genkey -name prime256v1 -out prime256v1.key Generate ECC secp256k1 Private Key $ openssl ecparam -genkey -name secp256k1 -out secp256k1.key Generate ECC Curve25519 Private Key $ openssl genpkey -algorithm X25519 -out X25519.key View prime256v1 Private Key $ openssl ec -in prime256v1.key -noout -text 2>/dev/null | sed -n '/priv:/,/pub:/p' | grep -o '[0-9a-f]{2}' | tr -d ' \n' View secp256k1 Private Key $ openssl ec -in secp256k1.key -noout -text 2>/dev/null | sed -n '/priv:/,/pub:/p' | grep -o '[0-9a-f]{2}' | tr -d ' \n' View Curve25519 Private Key $ openssl pkey -in X25519.key -noout -text 2>/dev/null | sed -n '/priv:/,/pub:/p' | grep -o '[0-9a-f]{2}' | tr -d ' \n'

altsalt commented 3 years ago

I am also having this problem (potentially among others) and described at least one step towards resolution in this closed issue. That said, I wanted to add commands to export the individual subkeys with gnupg.

To list the info needed to extract subkeys: gpg --list-keys --with-subkey-fingerprints

To export one subkey, with the keychain to the master: gpg --export-secret-subkeys --armor '0000000000000000000000000000000000000000' > subkey.asc

To export JUST the subkey: gpg --export-secret-subkeys --armor '0000000000000000000000000000000000000000!' > subkey_only.asc

onlykey commented 3 years ago

I have created a python script that is able to extract raw key values for a PGP primary key and this should work for unlimited number of subkeys. @altsalt You mentioned looking for a method to load keys for more complicated GPG keys with multiple subkeys this should do that. Keep in mind that this script extracts raw key material and displays it so this should only be run on a trusted computer. Here is how to use this script:

image

altsalt commented 3 years ago

Thank you very much for the script @onlykey ! It did not work at first for my rootless subkeys, but I figured out the work-around. Both the issue and fix were left as replies to https://github.com/SecurityInnovation/PGPy/issues/77

The extracted subkey is able to be loaded as you indicated. Excited to do a bit more testing before loading on my real key. Unfortunately, the snag mentioned in #170 is still in play, I will post screenshots in reply to that particular issue.

LRitzdorf commented 3 years ago

Great to see this working! I'd hesitate to truly close the issue at this point, since there isn't native support for subkeys yet, but it's definitely a step that makes subkeys a workable option!

For any other users here looking for a solution, see the above comments for code that works with both OpenSSL and GPG keys.

onlykey commented 3 years ago

@altsalt Great to hear its working. So next step is to test with various key types to see if this covers most use cases. Then we can add in the ability to display and select a subkey to load, then we could have this load to OnlyKey from the script using onlykey-cli.

altsalt commented 3 years ago

Working on that step with my trifurcated key sometime this week and will send along results.

svareille commented 2 years ago

Hi ! I tested the script with an gpg-generated key which features :

The current script doesn't allow for different algorithms for primary and sub keys. Plus, I don't really like having to put my passphrase along with my private key directly in the script and thus plain text on my disk.

Therefore I reworked the script to :

It currently doesn't extract DSA and ElGamal private keys (not sure if OnlyKey support theses).

The script can be found at https://gist.github.com/SimonVareille/fda49baf5f3e15b5c88e25560aeb2822 The key used is the john_do.asc key whose passphrase is the single letter a : https://gist.github.com/SimonVareille/1e15779ac524eb868600af53ac8a3dca

Do you think it's worth adding in the official repo ? In any case, any comment would be appreciated !

onlykey commented 2 years ago

@SimonVareille Very nice! We can add this to the official repo. DSA and ElGamal private keys are not supported only RSA (2048bit or 4096bit) ECC (nist256p1, cv25519, ed25519)

garrickwelsh commented 2 years ago

@onlykey I had implemented multiple key and subkey support in libagent for onlykey now. I have a PR to your libagent repository onlykey/lib-agent PR8. I hope this is the correct way as I hoped to let you review changes and push from your repository upstream. I have modified @SimonVareille's script to create a proof of concept that automatically load keys to the onlykey in a format that can later be read off them using onlykey-gpg-agent. onlykey-cli-gpg-add-keys.py The short coming I have at the moment is that I still require the master key to be installed on the key, I can't just have subkeys installed. I'd like to workaround this as ideally I'd prefer to only load subkeys onto my key. Additional changes pushed to PR so master key is not required on onlykey to support subkeys.

Technetium1 commented 3 months ago

@onlykey There is now OpenPGP.js 5.x, and a beta for 6.x. Have you considered testing the new releases? https://github.com/openpgpjs/openpgpjs/releases