PSA: apt / gpg issue – The following signatures couldn’t be verified because the public key is not available

Not a key?!

Context

Bob from Root Access ran into this annoyance while installing pixiecore by Dave Anderson, a tool for making PXE (network) booting a cinch.

Problem

He grabbed the pubkey via curl -L https://packagecloud.io/danderson/pixiecore/gpgkey, saved the output to a file at /usr/share/keyrings/pixiecore-archive-keyring.gpg, and told apt about both the repo and the pubkey:

deb [signed-by=/usr/share/keyrings/pixiecore-archive-keyring.gpg] https://packagecloud.io/danderson/pixiecore/debian stretch main

However, apt complained that the signature from the repo couldn’t be verified due to “public key is not available”:

root@pixiecore:~# apt update
Hit:1 http://deb.debian.org/debian bullseye InRelease
Hit:2 http://security.debian.org bullseye-security InRelease
Get:3 https://packagecloud.io/danderson/pixiecore/debian stretch InRelease [23.2 kB]
Err:3 https://packagecloud.io/danderson/pixiecore/debian stretch InRelease
The following signatures couldn't be verified because the public key is not available: NO_PUBKEY C9F812E8C6C291D9
Reading package lists… Done
W: GPG error: https://packagecloud.io/danderson/pixiecore/debian stretch InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY C9F812E8C6C291D9
E: The repository 'https://packagecloud.io/danderson/pixiecore/debian stretch InRelease' is not signed.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details

And yet the pubkey file existed, and definitely was there:

root@pixiecore:~# file /usr/share/keyrings/pixiecore-archive-keyring.gpg
/usr/share/keyrings/pixiecore-archive-keyring.gpg: PGP public key block Public-Key (old)

gpg wasn’t terribly happy about it, however:

root@pixiecore:~# gpg --fingerprint /usr/share/keyrings/pixiecore-archive-keyring.gpg
gpg: error reading key: No public key

Background: apt-key deprecated

As this answer on AskUbuntu explains, the previous way of acquiring a pubkey — apt-key add <key> — was deprecated as it was considered insecure. I can see why people would say that- if third party repos tell users “if you see an error saying ‘unable to verify’ then paste this apt-key add command”, a malicious repo could do the same and replace official packages (as I understand it).

This is similar to the Windows Vista-era problem of ‘UAC fatigue’. If every time you want to do something a modal popup appears asking for permissions to be granted, you get used to just saying “yes, allow” every time, which defeats the security of asking “do you want to grant MaliciousProgram.exe read and write permissions for your entire local storage?”.

Solution: Import, then export the key

Apt was clearly unhappy about the key file.

bertieb: oh

bertieb: is the “(old)” throwing things off somehow?

bertieb: the AskUbuntu thing had a conversion step

bertieb: which for some reason imported into gpg then exported

bertieb: maybe apt doesn’t like old style ones

Indeed, file gives different output for each:

$ file pixiecore-archive-keyring.gpg pixiecore-archive-keyring.gpg: PGP public key block Public-Key (old)

exported:

$ file pixiecore-archive-keyring-exported.gpg pixiecore-archive-keyring-exported.gpg: OpenPGP Public Key Version 4, Created Tue Aug 30 08:57:22 2016, RSA (Encrypt or Sign, 4096 bits); User ID; Signature; OpenPGP Certificate

The solution was to import the pubkey with gpg to a temporary keyring, export it and tell apt to use the exported pubkey:

$ gpg --no-default-keyring --keyring ./temp-keyring.gpg --import pixiecore-archive-keyring.gpg&lt;/p>
$ gpg --no-default-keyring --keyring ./temp-keyring.gpg --export --output pixiecore-archive-keyring-exported.gpg
$ rm temp-keyring.gpg

Which made apt happy.

Bob pointed out that the Debian wiki page doesn’t mention doing an import/export dance (except for ascii-armoured keys), nor a post which says that apt-key is deprecated.

Postscript: the new format seems to have different packet headers (per RFC 4880 § 4.2). Interestingly, examining both the old-format key and the new-format key packets gives identical output:

# off=0 ctb=99 tag=6 hlen=3 plen=525
:public key packet:
        version 4, algo 1, created 1472547442, expires 0
        pkey[0]: [4096 bits]
        pkey[1]: [17 bits]
        keyid: C7EE612C49005B7B
# off=528 ctb=b4 tag=13 hlen=2 plen=112
:user ID packet: "https://packagecloud.io/danderson/pixiecore (https://packagecloud.io/docs#gpg_signing) <support@packagecloud.io>"
# off=642 ctb=89 tag=2 hlen=3 plen=568
:signature packet: algo 1, keyid C7EE612C49005B7B
        version 4, created 1472547442, md5len 0, sigclass 0x13
        digest algo 2, begin of digest 3d 74
        hashed subpkt 2 len 4 (sig created 2016-08-30)
        hashed subpkt 27 len 1 (key flags: 2F)
        hashed subpkt 11 len 5 (pref-sym-algos: 9 8 7 3 2)
        hashed subpkt 21 len 5 (pref-hash-algos: 8 2 9 10 11)
        hashed subpkt 22 len 3 (pref-zip-algos: 2 3 1)
        hashed subpkt 30 len 1 (features: 01)
        hashed subpkt 23 len 1 (keyserver preferences: 80)
        subpkt 16 len 8 (issuer key ID C7EE612C49005B7B)
        data: [4096 bits]
# off=1213 ctb=b9 tag=14 hlen=3 plen=525
:public sub key packet:
        version 4, algo 1, created 1472547442, expires 0
        pkey[0]: [4096 bits]
        pkey[1]: [17 bits]
        keyid: C9F812E8C6C291D9
# off=1741 ctb=89 tag=2 hlen=3 plen=1086
:signature packet: algo 1, keyid C7EE612C49005B7B
        version 4, created 1472547442, md5len 0, sigclass 0x18
        digest algo 2, begin of digest ac d3
        hashed subpkt 2 len 4 (sig created 2016-08-30)
        hashed subpkt 27 len 1 (key flags: 2E)
        subpkt 16 len 8 (issuer key ID C7EE612C49005B7B)
        subpkt 32 len 540 (signature: v4, class 0x19, algo 1, digest algo 2)
        data: [4095 bits]

output not repeated, they are identical:

$ md5sum packetsnew.txt packetsold.txt 
e2280a7eec8b5ff236187fede704d9c1  packetsnew.txt
e2280a7eec8b5ff236187fede704d9c1  packetsold.txt

Tell us what's on your mind