You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Try to parse an exported GnuPG secret cryptoblob, with a subkey that does not have private key material (such as a hardware token, or a subkey that isn't present on that machine)
What did you expect to see?
A wonderful cryptoblob that I can use to post screeds to my local mailing lists.
What did you see instead?
openpgp: unsupported feature: hash for S2K function: 0
More details
When GnuPG exports the secret chunks of a key, it will also export the subkey private material. This will come as wholly uninteresting to everyone involved, I'm sure.
However, the interesting part is when that subkey does not have a private component associated with it (e.g. a hardware token, or subkey that has a key on another machine), it is marked "offline".
From the GPG manpage:
-K List the specified secret keys. If no keys are specified, then
all known secret keys are listed. A # after the initial tags
sec or ssb means that the secret key or subkey is currently not
usable. We also say that this key has been taken offline (for
example, a primary key can be taken offline by exported the key
using the command --export-secret-subkeys). A > after these
tags indicate that the key is stored on a smartcard. See also
--list-keys.
So, I made a key, and added a subkey with the golang.org/x/crypto/openpgp library, and discarded the subkey privatekey material (since gpg can't know if that's stored somewhere real or not), and imported that into the keyring.
I then added a new key and let it keep the key material.
[other packets that aren't germane to my point]
:secret sub key packet:
version 4, algo 1, created 1513992502, expires 0
pkey[0]: [2048 bits]
pkey[1]: [17 bits]
gnu-dummy S2K, algo: 0, simple checksum, hash: 0
protect IV:
keyid: C3A17CA0B9DFF1E5
[other packets that aren't germane to my point]
:secret sub key packet:
version 4, algo 1, created 1513993077, expires 0
pkey[0]: [2048 bits]
pkey[1]: [17 bits]
iter+salt S2K, algo: 7, SHA1 protection, hash: 2, salt: 87557FFC8163000E
protect count: 65011712 (255)
protect IV: 8e db a3 af 4e 71 11 5a e5 d7 48 97 40 e3 a6 c9
skey[2]: [v4 protected]
keyid: 26E9A61F6F84F502
Now, on the real subkey packet, it has an S2K packet that looks legit, and the "offline" key has a "gnu-dummy" subkey on it. Neat!
Seems like it's exporting shim (and empty) secret packets for the keys it doesn't have the private half to, which would explain why it's coming up with anyone doing stuff with Yubikeys.
This is a really wackado thing for GnuPG to do, and I'm kinda creeped out that it does this rather than just outputting the public key packet. I'm sure there's a totally plausible and mature reason to do this rather than it being easier to make a custom secret packet type.
I guess the behavior of /x/crypto/openpgp ought to be ignoring the gnu-dummy packets, pull the public key material out of it, and go on about your day, but it's apparently trying to validate what seems to this one humble engineer as a batshit value.
If it didn't crash there, it would for sure blow up when it tried to read the actual private key material, so maybe this is better? Who can know.
Here's another bug report that I think is related, and I posted there, until I thought to file it here, too.
The following workaround can be used to work around parts of this being a problem for very specific use-cases:
Since the problem is the subkey, let's export the secret key for the root, but not any of the subkeys. Or you can use the --export-secret-subkes flag to get those. That's done by adding a ! after the Key ID.
$ gpg --export-secret-keys KEYID!
That will export the secret key as something x/crypto/openpgp can grok again, but it will not have any subkeys on it. Depending on your use-case this may not be OK, but if you can read from this keyring for signing key use, and a pubkeyring (using boring --export), you can put it back together, to some degree.
Per the accepted #44226 proposal and due to lack of maintenance, the golang.org/x/crypto/openpgp package is now frozen and deprecated. No new changes will be accepted except for security fixes. The package will not be removed.
If this is a security issue, please email [email protected] and we will assess it and provide a fix.
If you're looking for alternatives, consider the crypto/ed25519 package for simple signatures, golang.org/x/mod/sumdb/note for inline signatures, or filippo.io/age for encryption. You can read a summary of OpenPGP issues and alternatives here.
If you are required to interoperate with OpenPGP systems and need a maintained package, we suggest considering one of multiple community forks of golang.org/x/crypto/openpgp. We don't endorse any specific one.
Please answer these questions before submitting your issue. Thanks!
What version of Go are you using (
go version
)?go version go1.9.2 linux/amd64
Does this issue reproduce with the latest release?
Yes, including a fresh git clone of
x/crypto
.What operating system and processor architecture are you using (
go env
)?Nothing but the finest Debian GNU/Linux has to offer
What did you do?
Try to parse an exported GnuPG secret cryptoblob, with a subkey that does not have private key material (such as a hardware token, or a subkey that isn't present on that machine)
What did you expect to see?
A wonderful cryptoblob that I can use to post screeds to my local mailing lists.
What did you see instead?
openpgp: unsupported feature: hash for S2K function: 0
More details
When GnuPG exports the secret chunks of a key, it will also export the subkey private material. This will come as wholly uninteresting to everyone involved, I'm sure.
However, the interesting part is when that subkey does not have a private component associated with it (e.g. a hardware token, or subkey that has a key on another machine), it is marked "offline".
From the GPG manpage:
So, I made a key, and added a subkey with the
golang.org/x/crypto/openpgp
library, and discarded the subkey privatekey material (since gpg can't know if that's stored somewhere real or not), and imported that into the keyring.I then added a new key and let it keep the key material.
And, now the interesting part of
--list-packets
:Now, on the real subkey packet, it has an S2K packet that looks legit, and the "offline" key has a "gnu-dummy" subkey on it. Neat!
Seems like it's exporting shim (and empty) secret packets for the keys it doesn't have the private half to, which would explain why it's coming up with anyone doing stuff with Yubikeys.
This is a really wackado thing for GnuPG to do, and I'm kinda creeped out that it does this rather than just outputting the public key packet. I'm sure there's a totally plausible and mature reason to do this rather than it being easier to make a custom secret packet type.
I guess the behavior of
/x/crypto/openpgp
ought to be ignoring thegnu-dummy
packets, pull the public key material out of it, and go on about your day, but it's apparently trying to validate what seems to this one humble engineer as a batshit value.If it didn't crash there, it would for sure blow up when it tried to read the actual private key material, so maybe this is better? Who can know.
Here's another bug report that I think is related, and I posted there, until I thought to file it here, too.
keybase/keybase-issues#1885 (comment)
The text was updated successfully, but these errors were encountered: