fluencelabs / dev-rewards

Apache License 2.0
570 stars 374 forks source link

Accept GPG-based ssh keys #48

Open DamienCassou opened 6 months ago

DamienCassou commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago

@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 commented 6 months ago

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

indeed

boneyard93501 commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago

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

weilbith commented 6 months ago

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

DamienCassou commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago

@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 commented 6 months ago

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

weilbith commented 6 months ago

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

lana-shanghai commented 6 months ago

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

We cannot handle encrypted secret keys. Skipping! :(

phryneas commented 6 months ago

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

mateo-moon commented 6 months ago

@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 commented 6 months ago

@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 commented 6 months ago

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 commented 6 months ago

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

boneyard93501 commented 6 months ago

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.

mateo-moon commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago

@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 commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago
āÆ 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 commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago

@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: https://github.com/pinpox/gpg2age/pull/1

felschr commented 6 months ago

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: 0xde031f16976AFcaC613087B6213Eb521F63d3A49 felschr: 0xD66753D737603E18018281E298Df86DE402d313E

dvdplm commented 6 months ago

So to recap the current status here:

Did I get that right?

acatangiu commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago

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 commented 5 months ago

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

savely-krasovsky commented 5 months ago

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.

corpix commented 4 months ago

My key is on Yubikey, so I can't claim. But thanks, now I know I forgot backup subkeys huh

DamienCassou commented 4 months ago

@felschr, @pinpox: I just sent you 200FLT each. Thank you very much for your hard work.