dev-rewards icon indicating copy to clipboard operation
dev-rewards copied to clipboard

Accept GPG-based ssh keys

Open DamienCassou opened this issue 11 months ago ā€¢ 42 comments

Hi,

the SSH key associated to my GitHub account is handled by GnuPG's enable-ssh-support feature. As a result, I don't have any ssh key file to look for and scripts in this project fail.

DamienCassou avatar Mar 07 '24 12:03 DamienCassou

It's also impossible to use this when a key is on a yubikey. Handshake solved this by also supporting GPG keys associated with a user. They can be found in the github API. For example for me: https://api.github.com/users/yorickvp/gpg_keys

yorickvP avatar Mar 07 '24 14:03 yorickvP

Hi,

the SSH key associated to my GitHub account is handled by GnuPG's enable-ssh-support feature. As a result, I don't have any ssh key file to look for and scripts in this project fail.

to do that, you usually use gpg-agent which means: gpg --list-secret-keys .... and gpg --export-secret-keys ... should get you where need to be quite easily ... assuming you went that route to set things up.

boneyard93501 avatar Mar 08 '24 09:03 boneyard93501

@boneyard93501 this gives me a secret key in openpgp format, which can't be read by age or openssh. I tried monkeysphere's openpgp2ssh, but it only supports rsa keys and not the ed25519 format I used.

yorickvP avatar Mar 08 '24 10:03 yorickvP

this gives me a secret key in openpgp format, which can't be read by age or openssh

indeed

DamienCassou avatar Mar 08 '24 11:03 DamienCassou

you'll have to fiddle a little. i'd look at python's cryptography lib or similar. also, have you looked at https://musigma.blog/2021/05/09/gpg-ssh-ed25519.html or https://security.stackexchange.com/questions/267711/how-can-i-convert-an-ed25519-key-in-pkcs8-to-openssh-private-key-format ?

boneyard93501 avatar Mar 08 '24 11:03 boneyard93501

I can confirm that gpg --export-secret-key keyid | openpgp2ssh keyid resulted in a key that I could use with age to follow the steps of the proof.sh script. openpgp2ssh is from the monkeysphere package and only works with non-password-protected gpg keys. I recommend doing that on an airgapped machine.

A bit of a pain, but doable.

phryneas avatar Mar 10 '24 16:03 phryneas

openpgp2ssh only works for rsa . Still need another solution for GPG keys in ed25519 algo.

nykma avatar Mar 10 '24 17:03 nykma

I also have my private key on a hardware device which I use as a GnuPG smart card. What should I do?

weilbith avatar Mar 11 '24 19:03 weilbith

I also have my private key on a hardware device which I use as a GnuPG smart card. What should I do?

This is also what I do but I have an offline backup in case the smart card crashes. Don't you?

DamienCassou avatar Mar 11 '24 20:03 DamienCassou

This is also what I do but I have an offline backup in case the smart card crashes. Don't you?

Nope. If I lose the smart card I'd create a new auth subkey on a new smart key (and revoke the old one); and upload the new ssh pubkey to my github profile.

daurnimator avatar Mar 12 '24 01:03 daurnimator

@DamienCassou I have my master key in a non-digital form to renew the sub-keys. But would that help here? šŸ¤”

I saw there is this age plugin- for yubikeys. Could such a mechanism work to write my own script to generate the proof? I just looks roughly at the Python code to get a feeling what it does. Not sure about the details.

Wondering if it is worth the hassle...

weilbith avatar Mar 12 '24 09:03 weilbith

@weilbith make sure to read over this first: https://github.com/str4d/age-plugin-yubikey/issues/39

boneyard93501 avatar Mar 12 '24 13:03 boneyard93501

@boneyard93501 thanks for sharing. Seems pretty hopeless. šŸ˜‘ Not the best user (developer?) experience. Sad. šŸ˜•

weilbith avatar Mar 12 '24 13:03 weilbith

I am getting this when trying to do gpg --export-secret-key <keyid> | openpgp2ssh

We cannot handle encrypted secret keys. Skipping! :(

lana-shanghai avatar Mar 12 '24 13:03 lana-shanghai

@lana-shanghai you can use gpg --edit-key YOURKEYID followed by passwd to remove the password from your key, at which point you can use openpgp2ssh.

I'd recommend doing that on a Live USB stick without persistance or network access to make sure that the unencrypted key doesn't touch your harddrive or the internet.

phryneas avatar Mar 12 '24 22:03 phryneas

@lana-shanghai you can use gpg --edit-key YOURKEYID followed by passwd to remove the password from your key, at which point you can use openpgp2ssh.

I'd recommend doing that on a Live USB stick without persistance or network access to make sure that the unencrypted key doesn't touch your harddrive or the internet.

Here is what i got when i'm trying to change password. I think it doesn't work for hardware keys.

gpg> passwd
Key has only stub or on-card key items - no passphrase to change.

gpg>

mateo-moon avatar Mar 12 '24 23:03 mateo-moon

@phryneas - tried your suggestion, getting this message: Key has only stub or on-card key items - no passphrase to change. so it seems like I never set a passphrase. When I try to do the export with openpgp2ssh again, it throws the same error message, We cannot handle encrypted secret keys. Skipping!. Did you manage the conversion with a Yubikey?

lana-shanghai avatar Mar 12 '24 23:03 lana-shanghai

It only works with keys you have on disk, not with keys in your Yubikey.

If you don't have a backup, you're out of luck.

phryneas avatar Mar 12 '24 23:03 phryneas

@boneyard93501 please don't tell me that you excluded people who signed commits with Yubikey from the airdrop! Whyyy :'(

lana-shanghai avatar Mar 12 '24 23:03 lana-shanghai

the yubico device users we sampled, including myself, all follow the best practices suggested by yubico, https://support.yubico.com/hc/en-us/articles/360013790259-Using-Your-YubiKey-with-OpenPGP with respect to gpg. so no, we didn't exclude yubikey users.

boneyard93501 avatar Mar 13 '24 15:03 boneyard93501

the yubico device users we sampled, including myself, all follow the best practices suggested by yubico, https://support.yubico.com/hc/en-us/articles/360013790259-Using-Your-YubiKey-with-OpenPGP with respect to gpg. so no, we didn't exclude yubikey users.

Iā€™m sorry. But how does this link help to solve problem with exporting ssh secret key(and feeding secret key to age is the only way to decript message) from yubikey? There is no any steps for that in the info through the link.

mateo-moon avatar Mar 13 '24 15:03 mateo-moon

the yubico device users we sampled, including myself, all follow the best practices suggested by yubico, [...] with respect to gpg

why are you talking about gpg? Only SSH keys are stored in the metadata file and the SSH keys are required to decrypt the message.

Everything I've read so far indicates that people using a smartcard (yubico, nitrokey or any other) and enable-ssh-support from GPG are actually excluded. Same for people using ed25519 and enable-ssh-support from GPG.

I think the process would have been much simpler for everyone if GPG was used to encrypt the message instead (or alongside) of SSH.

DamienCassou avatar Mar 13 '24 16:03 DamienCassou

Yes, the SSH secret key is not available to decrypt the data that was encrypted with the public SSH key. I tried to export the GPG secret key to decrypt the message, and it didn't work. The Yubikey encrypts the SSH secret key afaiu, and it's not possible to export it at all. We can only prove that we own the SSH secret key by signing some other message, but we cannot decrypt anything.

lana-shanghai avatar Mar 13 '24 21:03 lana-shanghai

@boneyard93501 Some ChatGPT tl;dr of how Age handles ssh private keys: When using an Ed25519 SSH private key with age for decryption, the process involves several key steps:

Key Type Recognition: age detects that the provided key is an Ed25519 SSH private key.

Conversion for Compatibility: To work within age's cryptographic framework, which uses X25519 for encryption, the Ed25519 SSH private key undergoes a conversion process. This ensures the key can be used in age's encryption and decryption operations. The conversion exploits the mathematical relationship between Ed25519 and X25519, focusing on adapting the key for the necessary cryptographic tasks without compromising security.

Symmetric Decryption: With the private key ready, age decrypts the symmetric key that encrypted the file. This step is crucial, as age employs symmetric cryptography for the bulk encryption of data. The algorithm used for symmetric encryption and decryption is typically AES-256-GCM or ChaCha20-Poly1305, both of which are known for their security and efficiency. The specific algorithm chosen depends on the implementation details and optimizations for performance and security.

File Decryption: Finally, using the decrypted symmetric key, age decrypts the file's contents and outputs them to the user. So from this we can conclude that we need to have a plaintext key which will then be converted by age, used for decryption of symmetric key and then this symmetric key will be used for decryption of ciphertext.

Yubikey generates and stores gpg secret keys internally. Moreover, when you configure Yubikey to use with gpg, it generates 3 separate keys: ed25519 secret key used for signatures; cv25519 secret key used for encryption; ed25519 used for authentication. Here is part of my card status output to demonstrate:

Example:

$ gpg --card-status
...
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
...
Key attributes ...: ed25519 cv25519 ed25519
...
Signature key ....: 6EA6 57B7 BB25 67DC D692  12FC 2DA6 0BC8 065A D981
      created ....: 2022-12-12 04:29:29
Encryption key....: E4BB C29A F8B0 61B4 1498  E222 84E1 A619 D888 2C6D
      created ....: 2022-12-12 04:29:29
Authentication key: 7336 188C 3E77 D50D 7A0D  7147 936C 1CBE D40D 3BCB
      created ....: 2022-12-12 04:29:29
...

So there is no way we use our signature keys to decrypt your age-encrypted messages from metadata.json. Yubikey API only allows signing something with this key. Here is their documentation page which clearly states these two functions are separate and are using separate keys.

So yes, you did exclude yubikey users after all.

MakarovSg avatar Mar 14 '24 17:03 MakarovSg

Did anyone find out how to use GPG keys that are in ed25519 format? I have those as backup (normally use a yubi only), but openpgp2ssh only does RSA.

The output of gpg --list-secret-keys looks like this for me:

sec   ed25519 2022-11-14 [C] [expires: 2024-11-13]
      3D65XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
uid           [ unknown] Pablo Ovelleiro Corral <mail@XXXXXX>
uid           [ unknown] Pablo Ovelleiro Corral (git) <mail@YYYYYY>
uid           [ unknown] Pablo Ovelleiro Corral (other) <[email protected]>
uid           [ unknown] [jpeg image of size 5583]
ssb   ed25519 2022-11-14 [S] [expires: 2024-11-13]
ssb   cv25519 2022-11-14 [E] [expires: 2024-11-13]
ssb   ed25519 2022-11-14 [A] [expires: 2024-11-13]

I have found no way to access my tokens. Let me know how to proceed to access it.

pinpox avatar Mar 20 '24 14:03 pinpox

If you have your plain keyfile somewhere you should be able to export it using gpgs --export-secret-ssh-key without using openpgp2ssh. In theory that should work with ed25519 keys. Sadly I only have a backup of my masterkey and not the authentication subkey so I couldn't test.

+1 for also encrypting the secret with the users pgp keys like hs did

mawalu avatar Mar 25 '24 10:03 mawalu

If you have your plain keyfile somewhere you should be able to export it using gpgs --export-secret-ssh-key without using openpgp2ssh. In theory that should work with ed25519 keys. Sadly I only have a backup of my masterkey and not the authentication subkey so I couldn't test.

+1 for also encrypting the secret with the users pgp keys like hs did

I can export the secret subkey with gpg --export-secret-keys 0x29E9XXXXXXXXXX but it fails to export the key when using --export-secret-ssh-key:

āÆ gpg --export-secret-ssh-key 0x29E9XXXXXXXXXX
gpg: key "0x29E9XXXXXXXXXX" not found: Not a Keygrip

@mawalu Am I doing it wrong? any ideas? It seems this option was never implemented: https://dev.gnupg.org/rGafe5fcda52e88438c7a7278117b2e03f510a9c1c

pinpox avatar Mar 25 '24 11:03 pinpox

āÆ gpg --export-secret-ssh-key 0x29E9XXXXXXXXXX
gpg: key "0x29E9XXXXXXXXXX" not found: Not a Keygrip

@mawalu Am I doing it wrong? any ideas? It seems this option was never implemented: https://dev.gnupg.org/rGafe5fcda52e88438c7a7278117b2e03f510a9c1c

I came across this as well. There exists gpg --list-secret-keys --with-keygrip which gives you the keygrip for keys, which seems something different then the id or fingerprint. Maybe that works for you?

mawalu avatar Mar 25 '24 12:03 mawalu

There exists gpg --list-secret-keys --with-keygrip which gives you the keygrip for keys,

I tried this and got some keygrip and I tried them all, I only got:

gpg: key "xxxxxxxxxxxxxxxx" not found: Not a Keygrip

I used gpg (GnuPG) 2.4.4 in Gentoo and my key used the ed25519 algo.

chaoticlonghair avatar Mar 25 '24 12:03 chaoticlonghair

The feature seems to never have been merged, see the messages at https://dev.gnupg.org/rGafe5fcda52e88438c7a7278117b2e03f510a9c1c

I'm trying to build gnupg from source based on that commit, but havn't had any luck yet. Any C/C++ people here that could help?

pinpox avatar Mar 25 '24 12:03 pinpox