Page MenuHome GnuPG

gpg chokes on empty UserId
Closed, WontfixPublic

Description

hey there,

bug as is says on the tin. examples:

gpg --list-packets /tmp/nouid.sec.asc

# off=0 ctb=95 tag=5 hlen=3 plen=966
:secret key packet:
	version 4, algo 1, created 1497283586, expires 0
	pkey[0]: [2048 bits]
	pkey[1]: [17 bits]
	iter+salt S2K, algo: 9, SHA1 protection, hash: 10, salt: 384F0480B89CE5CB
	protect count: 524288 (144)
	protect IV:  10 5c be b7 83 e5 a5 fd df 16 17 c8 90 3b 7f a0
	skey[2]: [v4 protected]
	keyid: 1316CE9CF807975D
# off=969 ctb=b4 tag=13 hlen=2 plen=0
:user ID packet: ""
# off=971 ctb=89 tag=2 hlen=3 plen=304
:signature packet: algo 1, keyid 1316CE9CF807975D
	version 4, created 1497283586, md5len 0, sigclass 0x13
	digest algo 10, begin of digest 94 04
	hashed subpkt 11 len 3 (pref-sym-algos: 9 8 7)
	hashed subpkt 21 len 1 (pref-hash-algos: 10)
	hashed subpkt 22 len 1 (pref-zip-algos: 1)
	hashed subpkt 25 len 1 (primary user ID)
	critical hashed subpkt 2 len 4 (sig created 2017-06-12)
	critical hashed subpkt 30 len 1 (features: 01)
	critical hashed subpkt 27 len 1 (key flags: 03)
	subpkt 16 len 8 (issuer key ID 1316CE9CF807975D)
	data: [2047 bits]
# off=1278 ctb=9d tag=7 hlen=3 plen=966
:secret sub key packet:
	version 4, algo 1, created 1497283586, expires 0
	pkey[0]: [2048 bits]
	pkey[1]: [17 bits]
	iter+salt S2K, algo: 9, SHA1 protection, hash: 10, salt: 603D070159508257
	protect count: 524288 (144)
	protect IV:  64 00 dd dd fb 1b 83 e4 8e b3 e0 ea ba 08 8b b4
	skey[2]: [v4 protected]
	keyid: 36FD61CA22B8B20D
# off=2247 ctb=89 tag=2 hlen=3 plen=287
:signature packet: algo 1, keyid 1316CE9CF807975D
	version 4, created 1497283586, md5len 0, sigclass 0x18
	digest algo 10, begin of digest 82 d1
	critical hashed subpkt 2 len 4 (sig created 2017-06-12)
	critical hashed subpkt 27 len 1 (key flags: 04)
	subpkt 16 len 8 (issuer key ID 1316CE9CF807975D)
	data: [2047 bits]
gpg --no-default-keyring --keyring=/tmp/tmp.AY9CZfDrkq --import /tmp/nouid.sec.asc

gpg: [don't know]: indeterminate length for invalid packet type 13
gpg: keyring_get_keyblock: read error: Invalid packet
gpg: keydb_get_keyblock failed: Invalid keyring
gpg: keydb_search failed: Invalid keyring
gpg: key 0x1316CE9CF807975D: public key "[User ID not found]" imported
gpg: [don't know]: indeterminate length for invalid packet type 13
gpg: keyring_get_keyblock: read error: Invalid packet
gpg: keydb_get_keyblock failed: Invalid keyring
gpg: keydb_search failed: Invalid keyring
gpg: key 0x1316CE9CF807975D: failed to re-lookup public key
gpg: Total number processed: 1
gpg:               imported: 1
gpg:       secret keys read: 1

the key is apparently imported, and will keep causing errors while listing keys. I was unable to delete it with --delete-keys, too.

Details

Version
2.1.18

Event Timeline

cat /tmp/nouid.sec.asc

-----BEGIN PGP PRIVATE KEY BLOCK-----

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
=PH8Z
-----END PGP PRIVATE KEY BLOCK-----
justus triaged this task as Normal priority.Jun 13 2017, 10:37 AM
justus added a project: gnupg (gpg22).
justus added a subscriber: justus.

Out of curiosity, how did you create the key? What is the use case?

Also, the example key seems to be protected by a passphrase. What is it?

The key was created programmatically by my standard approach, which is bastardizing openkeychain unit tests. good question about the passphrase - I don't remember exactly, but I'm guessing it's either empty or "x". doesn't really matter in the context of this particular bug I guess :)

the use case is having keys with no user ids, i.e. "anonymous" keys. sadly, openpgp doesn't allow keys that simply don't have a user id.

I'd suggest to skip such user id. Actually I had in mind that we did that in the past - but I may be wrong.

user ids with length 0 do conform with rfc4880, though

The key was created programmatically by my standard approach, which is bastardizing openkeychain unit tests. good question about the passphrase - I don't remember exactly, but I'm guessing it's either empty or "x". doesn't really matter in the context of this particular bug I guess :)

'x' is not working, and GnuPG does not accept empty passphrases. Well, it matters in so far that I cannot import the key with GnuPG master. Would you be so kind to generate a new key with these properties?

here's a public key version of the same key. it was available easier and should reproduce the bug just as well

-----BEGIN PGP PUBLIC KEY BLOCK-----

mQENBFk+vAIBCACsbLY+5iWXqLCkweBd32MuCchiY7ZRk3vjKa7m9btVlXlzyLDg
NEv6jmCHNfGCRNCSKxFjZxw1hi3wio3hMlBQGzAenm7mhnmMY+2CHQlvB7eIksgV
sj6ySyagvXp5wBd767Qg6mAYpqkYGGL7j9yRNm8xJPE6vf+akiEC/gSETZQj0xUH
2LYb5H0WgZM2nQ0RKP7HhOL7syx9O0vzcGZBmukEU0fpPs8x2jI3aKUhx4AxoklO
JgX8628tDO1SWcxgArZ0s+w22Iqb/L+BXPeRRpa5fw/Q1j3nvaC7LTbH/7Fugb60
io7ixuP1y88opMldYm5Ob+va8TweBK0iEnrnABEBAAG0AIkBMAQTAQoAGgQLCQgH
AhUKAhYBAhkABYJZPrwCAp4BApsDAAoJEBMWzpz4B5ddlAQH/2dcmPXzjWCItvKh
u61k7uqGzLJ1JN1vr7mqCtXqE3Hm6pzVwXKfxQBpENrUEGVkX69TfY+7KwOTGH7p
HQql5i8jQ9N7KLBUnP7ekd1R29FXnRmGUN6ttGxtBo6RFmpJCHY5GYURlkB7xorW
dsgI7ZWDCQ/P2pWNjQ5fxWNqUkEzdGxRMeD9f2uBJvrFJOr4C8+R10DVYZSGJsQW
XGHgSA1nRZ6/hqelKx4sEwo+aHhVxofexpYZ8Rw7Zzilk25Ccdov7y9cl1rZ+4Vs
hDy0YE8Dk1QzlgUvnxBQlXutEvRsDRABdM8t9RYL1+p4f4Wl5Xg/IL/VYL3NWKS6
BaLFkou5AQ0EWT68AgEIALx6qFvhsll3DyBMM0faARBoFqQ5SwlVGfXdD5V4Eh0e
1GPN77NIt85G2nfuwPA1/IKgX/+YYh5t5KLGpWeQZfQ6l5IFq74PpovOtEaUS/4I
ts7kklC9fbtVm3wDqC8/3ZBIkoni+PfiOU6NiyYrtlhGd21J+nSXY1BVQvgF0UqH
gtOZAW7j3A6CpgvioXDYZOVV5nj4n3SnEjQdicUsCx/pLT2wWb1Fguoq/wokvGkH
D7g+dcR2qtBJCg87RL7HIOq30BnDRU8rxm/47fdvr2UiZmAR87FRD78N+ZglLtMc
HdKmNMzm7q4Qog1EwlmffffpAA3BmXrS+LsyUPU9TqEAEQEAAYkBHwQYAQoACQWC
WT68AgKbBAAKCRATFs6c+AeXXYLRB/9kpRoqEZvA4D5qUNcrhNa14VPDDg/7vheW
h1Sn0NDiFuwuKAX4doVTWKH+z5+4o6v2HeNFlJ6qKayMie+jJ4vnLgY5WdSFHOnA
kW58jqXMt7dI/q065DxOBTf5OwklraggXZN5Vk/+T+dndBmoPcq7sRKf8XQj/x3x
k0qzIhfMURSD/a6gi9BE2X1I4IOuQreOtcXgecIgOcmLlINQWx6ttcbqpuXINjTd
KvO1C5rQdH4nUbL4wjXmC+uaCP+OI8Dr4Ey9F76W8BnfR7HT3zzNvFAgxV4fPrW8
A55Pw6HVnVRJ4p7Wb8GeqwLLWiDhM/M2nreOOcgm4NfXkJs62FtY
=fyqD
-----END PGP PUBLIC KEY BLOCK-----

I'm not sure I understand the problem. Importing that key seems to work just fine. Listing as well.

$ g10/gpg --import ../zero-length-uid.asc
gpg: keybox '/tmp/tmp.X8RFioiqWd/pubring.kbx' created
gpg: /tmp/tmp.X8RFioiqWd/trustdb.gpg: trustdb created
gpg: key 1316CE9CF807975D: public key "" imported
gpg: Total number processed: 1
gpg:               imported: 1
$ g10/gpg --list-keys
/tmp/tmp.X8RFioiqWd/pubring.kbx
-------------------------------
pub   rsa2048 2017-06-12 [SC]
      93A05FE7A1D84CCEB46088F61316CE9CF807975D
uid           [ unknown] 
sub   rsa2048 2017-06-12 [E]

$ g10/gpg --edit-key 93A05FE7A1D84CCEB46088F61316CE9CF807975D
gpg (GnuPG) 2.1.22-beta17; Copyright (C) 2017 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

pub  rsa2048/1316CE9CF807975D
     created: 2017-06-12  expires: never       usage: SC  
     trust: unknown       validity: unknown
sub  rsa2048/36FD61CA22B8B20D
     created: 2017-06-12  expires: never       usage: E   
[ unknown] (1). 

gpg> q

Anyway we should not allow empty user ids.

seems this was fixed along the way, then. I only tested with 2.1.18.

the spec doesn't forbid empty user ids, but unfortunately it does forbid keys with no uids. I would say thatempty user ids are the best option for "anonymous keys", i.e. keys that aren't supposed to have identity information attached to them. Those are nicer compared to using a fixed string (e.g. "anonymous", or "redacted") because they allow implementations to recognize them as such, and offer better handling.

It's a shame that older gpg cripples its keyring when importing such keys. I now get a ton of warnings in unrelated operations, and wasn't able to delete that test key from my keyring.

User IDs of length zero do seem to be in compliance with RFC4880.

gpg imposes limits on the length of data items in OpenPGP messages. OpenPGP does not specify any requirements on the length of keys or other properties, thus implementations can use sensible limits.

Just noticed that we fixed something related to this in 1.4:
bb61191aad98c3dbb487c1f76dd1552d44a52fe3

I think "anonymous" user ids are a valid use case, since openpgp doesn't allow "no" user ids. Disallowing zero-length user ids will just cause implementations that intend to use anonymous user ids to use another type of "empty", like a single space character. And the effect of that will be that it's no longer trivially defined what an "anonymous" user id is for special handling, e.g. showing a localized "anonymous key" placeholder. Please don't restrict zero-length user ids.

So, just use "Anonymous"? This clearly identifies what this user id is
about and does not lead users to think, that something is wrong.

Salam-Shalom,

Werner

Isn't it much nicer if we semantically convey that a key doesn't have associated user id information, compared to just listing such keys between "Andre" and "Arnold"? I'd much rather special case the empty string in the key list than an arbitrary string that may or may not have a universally obvious meaning.

werner edited projects, added Feature Request; removed Bug Report.

I consider allowing empty user ids too dangerous.

Hm. Could you elaborate on that? Why do you think it's dangerous?

I'd like to hear a little more about the use cases we imagine for Anonymous OpenPGP certificates.

I assume that we don't want true anonymity (completely unlinked one-shot identity), because otherwise there's no purpose to having the public key wrapped in a certificate in the first place.

so that means what we're looking for some form of pseudonymity. right? (feel free to help me clarify the requirements)

So either there's a user-chosen pseudonym or there is an automated one. Given that a user-chosen pseudonym is likely to be something that reduces the size of the anonymity set for that user, we probably prefer something as automated as possible.

given that the OpenPGP certificate already exists, and that the certificate already has a well-known, expected-to-be-unique handle, i think the most natural automated pseudonym is just the hex representation of the fingerprint.

So while you *can* build an OpenPGP certificate without a User ID, it will violate RFC 4880's "transferable public key" format, which means other implementations probably won't be able to interpret it.

and while you *can* send an empty User ID format, it sounds like again, existing implementations might choke on it. (also, you don't save much space by simply using the empty User ID, since most signatures are larger than most User IDs in the first place). furthermore, if all pseudonymous certificates have the same User ID then they might be harder to address, to display, or to index for common existing implementations.

so why not, for pseudonymous certificates, use the "natural" automatic pseudonym of the cert as a whole? like this:

pub   rsa4096 2007-06-02 [SC] [expires: 2017-12-21]
      0EE5BE979282D80B9F7540F1CCD2ED94D21739E9
uid           [ultimate] 0EE5BE979282D80B9F7540F1CCD2ED94D21739E9
sub   rsa4096 2016-12-21 [E] [expires: 2017-12-21]