sops icon indicating copy to clipboard operation
sops copied to clipboard

unable to force specific gpg subkey

Open mammothbane opened this issue 1 year ago • 2 comments

situation

I use sops to manage secrets for my projects, all using GPG for encryption.

I have a GPG master key with several encryption subkeys:

  • One on my YubiKey (oldest)
  • One on my desktop at home
  • One on my desktop at work (newest)

I just recently added the desktop and work subkeys, and am hoping to be able to configure sops to encrypt my secrets with all of these subkeys so that I can recover in the eventuality that I lose the YubiKey.

state of the world

As far as I understand:

  • sops shells out to gpg to encrypt/decrypt
  • When given a master key fingerprint to use for encryption, gpg will always use the newest encryption subkey
  • By default, any subkey fingerprint passed to gpg will cause it to lookup the master key first, then select an encryption subkey (which will always be the newest one per above)
  • It is possible to override this behavior by passing a specific subkey fingerprint followed by an exclamation mark (disables master key lookup and forces the use of the specified fingerprint)
  • sops truncates key fingerprints to 16 characters during encryption for compatibility reasons

As a result, it isn't possible to tell sops to use a specific key fingerprint, since for a keyid like 0123456789ABCDEF!, sops will produce 123456789ABCDEF! , which is rejected by gpg as malformed.

In my case, this means that everything sops encrypts that points at my gpg key can be encrypted only with my work encryption key, as it's the newest.

proof of concept

The following patch solves this problem for me and lets me specify an exclamation-mark fingerprint to sops:

diff --git a/pgp/keysource.go b/pgp/keysource.go
--- pgp/keysource.go
+++ pgp/keysource.go
@@ -625,9 +625,6 @@
 // shortenFingerprint returns the short ID of the given fingerprint.
 // This is mostly used for compatibility reasons, as older versions of GnuPG
 // do not always like long IDs.
 func shortenFingerprint(fingerprint string) string {
-	if offset := len(fingerprint) - 16; offset > 0 {
-		fingerprint = fingerprint[offset:]
-	}
 	return fingerprint
 }

proposed upstream

In shortenFingerprint, special-case strings with terminal !, chopping the string to 17 characters rather than 16, retaining the full key and the !. If amenable, I could PR this.

related

#808

mammothbane avatar Dec 05 '23 13:12 mammothbane

I ran into this specific issue yesterday! I have multiple subkeys for different devices so need a way to specify them. It seems to me like the behavior should be to try the long key first and fall back to shortening (or even just have users in those environments manually specify short ids). @hiddeco do you have more detail on which versions of gpg would barf on long fingerprints?

jflanglois avatar Dec 15 '23 19:12 jflanglois

I also ran into this problem. I'm working around it with the above patch. Thanks @mammothbane!

Luflosi avatar Mar 10 '24 11:03 Luflosi