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

FR: Put the same age key on multiple Yubikeys #75

Open
orolhawion opened this issue Jun 14, 2022 · 17 comments
Open

FR: Put the same age key on multiple Yubikeys #75

orolhawion opened this issue Jun 14, 2022 · 17 comments
Labels
enhancement New feature or request

Comments

@orolhawion
Copy link

orolhawion commented Jun 14, 2022

For backup reasons I would like to be able to put an age private key on more than one Yubikey so in case one Yubikey breaks, gets lost, is unusable in some other way, I would have another key that could decrypt my files. I might have overlooked such a feature, if so, please let me know how to do it.

@mihaigalos
Copy link

This will list all identities for plugged in YubiKeys:

$ age-plugin-yubikey --identity > identities

You can then encrypt to multiple identities:

$ identities=$(cat identities | grep Recipient | sed -e "s/ //g" | cut -d':' -f2 | sed -e 's/^age\(.*\)/ -r age\1/g'  | tr -d '\n')
$ rage $identities -e input.file -o output.file.age

Then decrypt to a single identitiy (a single plugged in YubiKey):

$ age-plugin-yubikey --identity > identity 2>/dev/null
$ cat $secret_file | rage -d -i identity

Have a look at how I've done it in pass for more details.

@mihaigalos
Copy link

BTW: the actual keys stored on the Yubikeys are still different^.

@orolhawion
Copy link
Author

ok, so you mean private age keys should be different and I should encrypt to all of them, which in fact makes this topic closable. thanks for the heads up. :)

@Merovius
Copy link

I am interested in the same thing for the same reason. I'd prefer having the same secret key on all my YubiKeys, so that if I have to replace one, I don't have to go around re-encrypting everything.

I understand the tradeoffs involved and I understand why people prefer to have separate private keys per hardware token. But I'd like the option to use an offline generated key.

@mihaigalos
Copy link

My 2 cents: I understand your point. Not sure if it's technically possible.

I believe a Yubikey-unique part (possibly hardware-coded) is involved in the process of generating an identity.

It is therefore unique and if you lose the Yubikey, you are left with whatever others you used to encrypt.
You will need to decrypt and reeencrypt to the list of Yubis you still possess.

Would like it if somebody could confirm/refute this^.

@orolhawion
Copy link
Author

I usually put my gpg identity on two different yubikeys, as stated for backup reasons. So I thought this should be possible with age keys also.

@mihaigalos
Copy link

@str4d ?

@str4d str4d added the enhancement New feature or request label Dec 30, 2022
@kmille
Copy link

kmille commented Feb 5, 2023

Another way to achieve this would be by generating the private key on an "unsafe device" and then importing it to the YubiKey(s). Is there a way/tutorial how to import private keys to the Yubikey?

@Merovius
Copy link

Merovius commented Feb 5, 2023

@kmille It's easy to do that using ykman, but age-plugin-yubikey refuses to use keys which have not been generated on the Yubikey.

@pinpox
Copy link

pinpox commented Aug 8, 2023

@kmille It's easy to do that using ykman, but age-plugin-yubikey refuses to use keys which have not been generated on the Yubikey.

Is there a technical reason/limitation behind this or could that be changed on age-plugin-yubikey's side? I'm used to the workflow as decribed by @orolhawion and @Merovius from gpg. I have also generated my gpg keys on an airgapped laptop and copied the keys to multiple yubikeys and also printed them out on paper to be stored safely as last-resort backup.

I would love to move from gpg to age for all encrypting purpouses, is there any chance we could allow keys not generated on the yubikey itself and copied via ykman?

This would also solve #3
Also, if you don't want to use this approach or disallow them I guess it could just be configurable whether you want to allow it?

@pinpox
Copy link

pinpox commented Aug 12, 2023

@mihaigalos I have a key and can help test this but need some guidance. How do you generate a key in the correct format to be imported? @Merovius how did you generate your key?

@pinpox
Copy link

pinpox commented Aug 13, 2023

I'm not sure how to import that key. I generated one like shown in the screenshot and saved the two strings to files:

shell ❯ cat secret-key
0c 06 41 0d 17 db 68 5a 84 47 e7 e9 d7 a5 2f 2f

shell ❯ cat private-identity
22 f5 0a 2e 1a db

I then tried to import them into my testing yubikey:

shell ❯ ykman piv keys import 82 ./secret-key 
ERROR: Could not parse private key.

I suppose that is not the correct format that ykman exports for importing? Can you give me directions on how to test this?

I also have tried removing the spaces.

@pinpox
Copy link

pinpox commented Aug 13, 2023

I found some information regarding this. Citing from: https://smallstep.com/blog/access-your-homelab-anywhere/

It confirms that the private key is hardware-bound and non-exportable.

Crucially, the YubiKey will only attest a private key that's been generated directly on the YubiKey. If you try to attest an imported private key, it will fail:

Could this be the cause?

@orolhawion
Copy link
Author

I don't quite get how you get from
age keys to Yubico OTPs...

@Merovius
Copy link

You can generate a private key with a tool of your choice, for example:

openssl genpkey -algorithm EC -out private.key -pkeyopt ec_paramgen_curve:P-384 -pkeyopt ec_param_enc:named_curve

You can then import it into an arbitrary slot of your YubiKey using ykman. For example, to install it into the Key Management Slot (which is used to encrypt E-Mails, so it seems an appropriate slot to use for age):

$ ykman piv keys import 9d private.key
$ ykman piv keys info 9d
Key slot:               9D (KEY_MANAGEMENT)              
Algorithm:              ECCP384
Origin:                 IMPORTED
PIN required for use:   ONCE
Touch required for use: NEVER

Going from there to actually getting age-plugin-yubikey to use that key is the step I'm failing at - but in theory, all you should need to generate an age identity is the public key, which you can derive from the private key. And all you need to decrypt a message is to use PIV to get the YubiKey to decrypt it for you.

So I'd expect age-plugin-yubikey to be able to 1. output an identity for any private key stored in any key slot on the YubiKey and 2. if asked to decrypt a message for a given public key, iterate through the key slots and retrieve their public keys, to find the required one (for example using the Get metadata PIV command) and then 3. use that slot to decrypt the message.

The documentation implies that only the retired key slots are used. But even if I store a private key into slot 82 (using the above procedure) it is not listed by age-plugin-yubikey --list-all, which leads me to believe that age-plugin-yubikey simply does not support any of this.

@kagehisa
Copy link

The documentation implies that only the retired key slots are used. But even if I store a private key into slot 82 (using the above procedure) it is not listed by age-plugin-yubikey --list-all, which leads me to believe that age-plugin-yubikey simply does not support any of this.

My Rust skills are limited at best but as far as I can see, there is a certificate check whenever a key is read from a slot. So I guess (emphasis on GUESS) is that keys generated with age-plugin-yubikey are signed or identified with a certeain certificate, in order to make sure this is not a key used by any other PIV service.

@pinpox
Copy link

pinpox commented Apr 18, 2024

that keys generated with age-plugin-yubikey are signed or identified with a certeain certificate

@str4d Can you confirm this?

If true, would you be able to make that optional or disable it alltogether so we can use exteranally generated age keys?
This issue is truely the only thing keeping me with GPG, I would love to find a solution on how to use my own key (which I can have a backup of) on the yubikey for everything

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

No branches or pull requests

7 participants