Fix SOPS_AGE_SSH_PRIVATE_KEY_FILE for age recipients#2009
Fix SOPS_AGE_SSH_PRIVATE_KEY_FILE for age recipients#2009gokselk wants to merge 4 commits intogetsops:mainfrom
Conversation
a153789 to
b19cafa
Compare
b19cafa to
9833fcc
Compare
|
Thanks for your contribution. I don't see that this PR has a chance of getting merged in its current form though. It contains a lot of apparently vendored code from an unknown source (I don't see any links to the source) that we would now have to maintain. |
|
@felixfontein Thanks for taking a look! Yeah fair point, I should've added proper attribution. The bech32 code is from ssh-to-age which itself copies from age's internal package. The tricky part is age keeps their bech32 internal, so we can't just import it directly. A few options:
Let me know which direction you'd prefer and I'll update the PR. |
|
I'd probably import the code from ssh-to-age:
|
2c123f1 to
bf361ae
Compare
Done, switched to github.com/Mic92/ssh-to-age/bech32 and removed the vendored code. |
Enable SSH ed25519 keys to decrypt data encrypted to age recipients derived from the same key (via ssh-to-age or similar tools). Fixes getsops#1999 Signed-off-by: gokselk <gokselk.dev@gmail.com>
bf361ae to
0211dc6
Compare
|
Updated the PR description. The implementation has changed quite a bit. Also, the ssh-to-age tags don't follow Go module version numbering conventions, so I've opened an issue to address this: Mic92/ssh-to-age#190 |
|
CC @Mic92 - do you think using ssh-to-age in here like this makes sense? |
Signed-off-by: gokselk <gokselk.dev@gmail.com>
Signed-off-by: gokselk <gokselk.dev@gmail.com>
Signed-off-by: gokselk <gokselk.dev@gmail.com>
|
Ping @Mic92 |
|
Please note that there's now a conflict since #2070 got merged. Also I'm still waiting for feedback from other maintainers (ping @getsops/maintainers) on whether adding the new dependency is OK. |
Does age/sops with age not support ssh key directly (https://pkg.go.dev/filippo.io/age/agessh)? Afaik this was mostly needed when this wasn't the case. But I haven't read through the whole thread yet. |
<- This seems like a weird use case. You can use both consistently use the ssh key format to encrypt/decrypt or you convert your ssh key to age, both public/private key and than use the age format. But what this PR is proposing is to mix these two. |
|
@Mic92 thanks a lot for weighting in! I spent some time today thinking about this, and I'm currently tending to agree. I guess this feature would mainly be useful for users who manually converted SSH keys to Age identities with your tool in the past, and used the converted keys to encrypt SOPS files, and now want to decode without having to keep the converted keys. While I can understand that this is useful, I don't like the increase of complexity this apparent convenience feature brings to the codebase. @getsops/maintainers more opinions? |
Fixes #1999
Problem
Users who convert their SSH public keys to age recipients using
ssh-to-agecannot decrypt withSOPS_AGE_SSH_PRIVATE_KEY_FILE. This is a common workflow for reusing existing SSH keys with SOPS.Example workflow that fails:
Root Cause
SOPS only creates an SSH identity from the key file. SSH identities can decrypt data encrypted to SSH recipients, but NOT data encrypted to age X25519 recipients (even when derived from the same key).
Solution
For ed25519 SSH keys, now create both:
The conversion uses the
github.com/Mic92/ssh-to-agelibrary which implements the ed25519 -> curve25519 -> bech32-encoded age identity conversion.For encrypted (passphrase-protected) SSH keys, a
lazyEd25519AgeIdentitywrapper is used that:Non-ed25519 keys (RSA, ECDSA) are unchanged - they only get an SSH identity. age uses X25519 which is based on Curve25519, the same curve as ed25519, making conversion possible only for ed25519 keys.
Changes
age/ssh_parse.golazyEd25519AgeIdentityfor lazy passphrase prompting,recipientMatcherinterface, usessh-to-agelibrary for key conversionage/keysource.goage/keysource_test.gogo.modgithub.com/Mic92/ssh-to-agedependencyTest Plan