Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accept GPG-based ssh keys #48

Open
DamienCassou opened this issue Mar 7, 2024 · 40 comments
Open

Accept GPG-based ssh keys #48

DamienCassou opened this issue Mar 7, 2024 · 40 comments

Comments

@DamienCassou
Copy link

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.

@yorickvP
Copy link

yorickvP commented Mar 7, 2024

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

@boneyard93501
Copy link

boneyard93501 commented Mar 8, 2024

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.

@yorickvP
Copy link

yorickvP commented Mar 8, 2024

@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.

@DamienCassou
Copy link
Author

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

indeed

@boneyard93501
Copy link

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 ?

@phryneas
Copy link
Contributor

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.

@nykma
Copy link

nykma commented Mar 10, 2024

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

@weilbith
Copy link

weilbith commented Mar 11, 2024

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

@DamienCassou
Copy link
Author

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?

@daurnimator
Copy link

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.

@weilbith
Copy link

@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...

@boneyard93501
Copy link

@weilbith make sure to read over this first: str4d/age-plugin-yubikey#39

@weilbith
Copy link

weilbith commented Mar 12, 2024

@boneyard93501 thanks for sharing. Seems pretty hopeless. 😑
Not the best user (developer?) experience. Sad. 😕

@lana-shanghai
Copy link

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

We cannot handle encrypted secret keys. Skipping! :(

@phryneas
Copy link
Contributor

@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.

@oleg-plakida
Copy link

oleg-plakida commented Mar 12, 2024

@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>

@lana-shanghai
Copy link

@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?

@phryneas
Copy link
Contributor

phryneas commented Mar 12, 2024

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.

@lana-shanghai
Copy link

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

@boneyard93501
Copy link

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.

@oleg-plakida
Copy link

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.

@DamienCassou
Copy link
Author

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.

@lana-shanghai
Copy link

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.

@MakarovSg
Copy link

MakarovSg commented Mar 14, 2024

@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.

@pinpox
Copy link

pinpox commented Mar 20, 2024

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) <other@XXXX.tld>
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.

@mawalu
Copy link

mawalu commented Mar 25, 2024

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

@pinpox
Copy link

pinpox commented Mar 25, 2024

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

@mawalu
Copy link

mawalu commented Mar 25, 2024

❯ 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?

@yangby-cryptape
Copy link

yangby-cryptape commented Mar 25, 2024

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.

@pinpox
Copy link

pinpox commented Mar 25, 2024

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?

@felschr
Copy link

felschr commented Mar 25, 2024

There is an open issue about finishing the implementation of --export-secret-ssh-key, but it hasn't seen much activity:
https://dev.gnupg.org/T6647

Generally the keygrip/userid needs to be prefixed by &:

> gpg2 --export-secret-ssh-key "&AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
gpg: export as ssh key failed: Invalid public key algorithm

This might even work for RSA keys already, but for Ed25519 it will give the above error.

@pinpox
Copy link

pinpox commented Mar 26, 2024

I've been trying to implement my own tool to do this for ed25519 but the decryption still fails. Any go+encryption wizards around that could take a look and help out?
https://github.com/pinpox/gpg2age/blob/main/main.go

EDIT: As said on the discord, I offer 10% of my FLT as reward for anyone who can help me get it to work and claim the tokens.

@felschr
Copy link

felschr commented Mar 26, 2024

@pinbox I've tried to extend your code, but I also haven't got it to work. Still, I made some improvements that might be helpful:
pinpox/pgp2ssh#1

@felschr
Copy link

felschr commented Mar 27, 2024

Guys, we did it! 🥳
pgp2ssh can successfully derive SSH private keys from PGP private keys keys using ed25519.

This was only possible due to the close collaboration between @pinpox & me.
If you need any help, feel free to contact us.

And f you want to thank us, you can send us any crypto or token to our Ethereum / Polygon wallets 😊:
pinpox: 0x3d479e19ae8d1a67becdaeaf8d2d37c8e425bd03
felschr: 0xD66753D737603E18018281E298Df86DE402d313E

@dvdplm
Copy link

dvdplm commented Mar 28, 2024

So to recap the current status here:

  • RSA keys can be exported and transformed into the right shape with openpgp2ssh
  • ed25519 keys can also be made to work (thanks to @felschr and @pinpox)
  • Yubikey users of either flavour of key are screwed if they generated their key on the Yubikey because:
    • openpgp2ssh can only deal with decrypted keys
    • for HSM-based keys there is no passphrase, so gpg --edit-key YOURKEYID + passwd can't work to remove the password
    • pgp2ssh also requires the key passphrase to work, so cannot work for Yubikey-based keys
  • The devs cannot fix this because the metadata.bin is committed to on-chain. They also don't think they did anything wrong because "users should generate their keys outside the Yubikey".

Did I get that right?

@acatangiu
Copy link

acatangiu commented Mar 29, 2024

IIUC the private key on the Yubikey cannot be exported, and the Yubikey hardware does not support chacha20poly1305 decryption.

Alas, I too am unable to claim because there is no way to prove GitHub ownership with Yubikey setup. 😢

@Nexus2k
Copy link

Nexus2k commented Apr 1, 2024

Crap :( my key also refers to one generated on Yubikey. Why can't we just sign some message with the yubikey generated key to proof ownership? Did the devs ditch the unencrypted blobs? How will they reduce the rewards if not in possession of the keys for the temporary eth account?

@lana-shanghai
Copy link

Crap :( my key also refers to one generated on Yubikey. Why can't we just sign some message with the yubikey generated key to proof ownership? Did the devs ditch the unencrypted blobs? How will they reduce the rewards if not in possession of the keys for the temporary eth account?

Yeah that would be great, we sign a freshly generated messag

@savely-krasovsky
Copy link

@dvdplm if the passphrase itself is problem, you can remove this requirement for sure.

@savely-krasovsky
Copy link

savely-krasovsky commented Apr 12, 2024

I didn't have this problem and claimed my tokens already, but could try to help with obtaining right proof from Yubikey, I have two. Can someone say me which software you are using to get Yubikey working with SSH through GPG?

Well, if the process of getting proof involves decryption, then yeah, sorry, but GPG is using various keys for authentication and encryption unfortunately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests