Monday, 22 February 2021

How to check file GPG signature on Linux

Retrieving and installation of Linux software can be done via package management systems (like apt) or manually downloading and running the executable. 

Public Key Cryptography is used on Linux to verify the identity of the file provider. A public and private key are created, file sender signs the file with private key and publishes public key. Receiver uses the public key to verify the signature. 

GNU Privacy Guard (GnuPG or GPG) is set of open-source tools for key exchange, signing, verification, encrypting and decrypting files.




I want to show here how to use gpg to verify a file downloaded from Internet on the example of Tor browser installer. It is not necessary to do this when using package managers to install some software as they use this automatically (see SecureApt - Debian Wiki).

From Tor's website we need to download:

1) an installation archive (https://www.torproject.org/dist/torbrowser/10.0.10/tor-browser-linux64-10.0.10_en-US.tar.xz) 

2) its PGP signature (https://dist.torproject.org/torbrowser/10.0.10/tor-browser-linux64-10.0.10_en-US.tar.xz.asc) which looks like this:

-----BEGIN PGP SIGNATURE-----

iQIcBAABCgAGBQJgG5QbAAoJEOt3RJHZ/wbinYQP/RVTZOY9YLe7y2azJs2K3IcF
Wr20e2zMGVGpvV2WZ3uYij7nMQGujPU4V8cJ/5vSb3ONKSwr/YXfqSGOC6gL8EAF
yvJsS5JjVdGYpBxg9ye1Cb3AFtKgQLBwFLvDWtWuLH1lk7VDLY5dDPbRpX6x3HKE
LbulR1IsUdQLdrbUfkoUpYBf1GTb+4+F4a//tLEnCwWojO72jL3UNzRmKPCOZ+KD
IxbGxHCtqAHMU8dBYZ5yQugW7mLnzmTAyFtfem9KuJXMFlpKICadOK6yZDYH2U3Y
SPGONS3vRZEhlfuDmyh0U18L7A3H25ELdbUTYhQLfZj0/OCy0cyqESzn65cpSPS8
/Fg2BdnmyzkWqo45KF5l4KCoT3+Jd2BHC6uZ8na/LpW6WncQ43+8obBbthgHODLA
rHGTTA7ccR+2aWFHjlZaGHErj7mjdRiNuOzlpWVpfMwcvMoCxN71DUxrVIdQchY4
j7K4fvt5ZpR3Ln0pFd9QgbwES6bqi2U0MZ872ChQ/LPoYhGxqrsEpJTJoZBnJ7Ik
IL4MiHLcN+9RKwamBhC9qjOp9V1IHVexxPvRxWc1Ix3Vwp5W7hFSZoM+pBruMjsF
9gc8pEL3RETBomr8zSGRPKDAvHv/V+r31pHTEr9pgEn3rN7wU7VCABVrK7pHJltl
03nm5LAu7HdLxFYysxur
=6o0j
-----END PGP SIGNATURE-----

Now we want to verify the authenticity of the downloaded file. The tool that we're going to use is gpg. gpg is included in Linux distributions (I am using Ubuntu).

$ gpg --help
gpg (GnuPG) 2.2.19
libgcrypt 1.8.5
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /home/bojan/.gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cypher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2

Syntax: gpg [options] [files]
Sign, check, encrypt or decrypt
Default operation depends on the input data

Commands:
 
 -s, --sign                  make a signature
     --clear-sign            make a clear text signature
 -b, --detach-sign           make a detached signature
 -e, --encrypt               encrypt data
 -c, --symmetric             encryption only with symmetric cypher
 -d, --decrypt               decrypt data (default)
     --verify                verify a signature
 -k, --list-keys             list keys
     --list-signatures       list keys and signatures
     --check-signatures      list and check key signatures
     --fingerprint           list keys and fingerprints
 -K, --list-secret-keys      list secret keys
     --generate-key          generate a new key pair
     --quick-generate-key    quickly generate a new key pair
     --quick-add-uid         quickly add a new user-id
     --quick-revoke-uid      quickly revoke a user-id
     --quick-set-expire      quickly set a new expiration date
     --full-generate-key     full featured key pair generation
     --generate-revocation   generate a revocation certificate
     --delete-keys           remove keys from the public keyring
     --delete-secret-keys    remove keys from the secret keyring
     --quick-sign-key        quickly sign a key
     --quick-lsign-key       quickly sign a key locally
     --sign-key              sign a key
     --lsign-key             sign a key locally
     --edit-key              sign or edit a key
     --change-passphrase     change a passphrase
     --export                export keys
     --send-keys             export keys to a keyserver
     --receive-keys          import keys from a keyserver
     --search-keys           search for keys on a keyserver
     --refresh-keys          update all keys from a keyserver
     --import                import/merge keys
     --card-status           print the card status
     --edit-card             change data on a card
     --change-pin            change a card's PIN
     --update-trustdb        update the trust database
     --print-md              print message digests
     --server                run in server mode
     --tofu-policy VALUE     set the TOFU policy for a key

Options:
 
 -a, --armor                 create ASCII armoured output
 -r, --recipient USER-ID     encrypt for USER-ID
 -u, --local-user USER-ID    use USER-ID to sign or decrypt
 -z N                        set compress level to N (0 disables)
     --textmode              use canonical text mode
 -o, --output FILE           write output to FILE
 -v, --verbose               verbose
 -n, --dry-run               do not make any changes
 -i, --interactive           prompt before overwriting
     --openpgp               use strict OpenPGP behaviour

(See the man page for a complete listing of all commands and options)

Examples:

 -se -r Bob [file]          sign and encrypt for user Bob
 --clear-sign [file]        make a clear text signature
 --detach-sign [file]       make a detached signature
 --list-keys [names]        show keys
 --fingerprint [names]      show fingerprints

Please report bugs to <https://bugs.gnupg.org>.


From Tor's website we can find that it is signed by Tor Browser Developers and that their signing key is 0xEF6E286DDA85EA2A4BA7DE684E2C6E8793298290. 

gpg can import the public key of the author from Web Key Directory it deducts from author's public email ID:

$ gpg --auto-key-locate nodefault,wkd --locate-keys torbrowser@torproject.org
gpg: key 4E2C6E8793298290: public key "Tor Browser Developers (signing key) <torbrowser@torproject.org>" imported
gpg: Total number processed: 1
gpg:               imported: 1
pub   rsa4096 2014-12-15 [C] [expires: 2025-07-21]
      EF6E286DDA85EA2A4BA7DE684E2C6E8793298290
uid           [ unknown] Tor Browser Developers (signing key) <torbrowser@torproject.org>
sub   rsa4096 2018-05-26 [S] [expires: 2021-06-12]

--auto-key-locate defines how will gpg locate keys:

--auto-key-locate mechanisms
--no-auto-key-locate
              GnuPG  can  automatically  locate  and  retrieve  keys  as  needed using this option.  This happens when encrypting to an email address (in the "user@example.com" form), and there are no "user@example.com" keys on the local keyring.  This option takes any number of the mechanisms listed below, in the order they are to be tried.  Instead of listing the mechanisms as comma delimited  arguments,  the  option  may also be given several times to add more mechanism.  The option --no-auto-key-locate or the mechanism "clear" resets the list.  The default is "local,wkd".

              cert   Locate a key using DNS CERT, as specified in RFC-4398.
              pka    Locate a key using DNS PKA.
              dane   Locate a key using DANE, as specified in draft-ietf-dane-openpgpkey-05.txt.
              wkd    Locate a key using the Web Key Directory protocol.
              ldap   Using DNS Service Discovery, check the domain in question for any LDAP keyservers to use.  If this fails, attempt to locate the key using the  PGP  Universal  method  of  checking ‘ldap://keys.(thedomain)’.
              keyserver Locate a key using a keyserver.
              keyserver-URL In addition, a keyserver URL as used in the dirmngr configuration may be used here to query that particular keyserver.
              local  Locate  the  key  using  the  local keyrings.  This mechanism allows the user to select the order a local key lookup is done.  Thus using ‘--auto-key-locate local’ is identical to --no-auto-key-locate.
              nodefault
                     This flag disables the standard local key lookup, done before any of the mechanisms defined by the --auto-key-locate are tried.  The position of this mechanism in  the  list  does not matter.  It is not required if local is also used.
              clear  Clear all defined mechanisms.  This is useful to override mechanisms given in a config file.  Note that a nodefault in mechanisms will also be cleared unless it is given after the clear.


Web Key Directories: 
  • provide an easy way to discover public keys through HTTPS
  • way to retrieve PGP keys without using a keyserver
  • keep email addresses private (as you need to know an address already to ask for a public key)
  • are authoritative source for a public key for its domain
Web Key Directory protocol:
  • The sender's mail client checks a "well known" URL on the domain of the recipient.
  • If a public key is available for that mail address, will be downloaded via HTTPS.
  • The downloaded pubkey can now be used without further user interaction.
How does gpg find the URL of the key? It uses the host name from the provided email address and constructs it. See here: Attacks on GnuPG's Web Key Directory (WKD) | SektionEins GmbH and here: draft-koch-openpgp-webkey-service-08 - OpenPGP Web Key Directory.

torbrowser@torproject.org =>
    username (local-part): torbrowser
    domain: torproject.org

$ echo -n "torbrowser" | sha1sum 
5426242bb720dfdd6dc01bfcddfe3f5b92d9f065 

I used Cryptii online tool which uses z-base-32 Encoder to encrypt the string (sha1 sum):

kounek7zrdx745qydx6p59t9mqjpuhdf

We now have zbase32 username.

Every domain can host host the WKD from a special openpgpkey subdomain: openpgpkey.

It should have a folder structure similar to this:

.well-known
.well-known/openpgpkey
.well-known/openpgpkey/example.com
.well-known/openpgpkey/example.com/policy
.well-known/openpgpkey/example.com/hu
.well-known/openpgpkey/example.com/hu/<zbase32_username>

In our case:

https://openpgpkey.torproject.org/.well-known/openpgpkey/torproject.org/hu/kounek7zrdx745qydx6p59t9mqjpuhdf

We can see that Tor Browser Developers (signing key) is at that URL (I'm printing here only first 4 lines of the output): 

$ curl https://openpgpkey.torproject.org/.well-known/openpgpkey/hu/kounek7zrdx745qydx6p59t9mqjpuhdf?l=torbrowser \
--output - \
| head -n4
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
T����2ϐ��,�c݉0�     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
� Jʸ�X�jV_���>�P�AD���2B�>[���Ԟrv�K
Ge�ӧGWo��31�S#�2�H�+Յ5�Y�8{�Պbq'M�����D\l}�~9�S!/�v(�w�(;���bX/���@Tor Browser Developers (signing key) <torbrowser@torproject.org>�Te%�G�'��`;��X�;D�5q_���¤�f=��N��)�>�'�n}��K��TGhi��7;����[�
>
 
  5025    0     0  14075      0 --:--:-- --:--:-- --:--:-- 14036
(23) Failed writing body

Let's save this key in tor.keyring file:

$ gpg --output ./tor.keyring --export 0xEF6E286DDA85EA2A4BA7DE684E2C6E8793298290


Verification of the signature is done via gpgv tool:

$ gpgv --help
gpgv (GnuPG) 2.2.19
libgcrypt 1.8.5
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Syntax: gpgv [options] [files]
Check signatures against known trusted keys


Options:
 
 -v, --verbose                verbose
 -q, --quiet                  be somewhat more quiet
     --keyring FILE           take the keys from the keyring FILE
 -o, --output FILE            write output to FILE
     --ignore-time-conflict   make timestamp conflicts only a warning
     --status-fd FD           write status info to this FD
     --weak-digest ALGO       reject signatures made with ALGO

Please report bugs to <https://bugs.gnupg.org>.


$ gpgv \
--keyring ./tor.keyring \
~/Downloads/tor-browser-linux64-10.0.10_en-US.tar.xz.asc \ ~/Downloads/tor-browser-linux64-10.0.10_en-US.tar.xz
gpgv: Signature made Thu 04 Feb 2021 06:28:43 GMT
gpgv:                using RSA key EB774491D9FF06E2
gpgv: Good signature from "Tor Browser Developers (signing key) <torbrowser@torproject.org>"

No comments: