Highlighted
Moderator
Moderator
  • 457 Views

Securely Managing Software using GPG

Why don’t you install software from outside of your device’s App Store? It’s a security risk obviously. But how and why?

Software acquired from your device’s App Store has been tested, validated to be free of malware, and has the backing of your device’s vendor.

It’s about trust.

You trust that your App Store wants what’s best for you.

Why should your computer be any different? Why should your servers be any different?

How do you know that the game you illegally acquired by your favorite torrent site, does not have malware which calls home? How do you know that a particular software package which you downloaded from some random site is not going to setup a backdoor in your server?

The answer is to implement a trust relationship with software vendors so that any software which is not trusted, does not get installed.

So how do we identify who we trust? The answer is with GPG keys. Your software vendors are expected to digitally sign their software packages with their private key (which is private and only held by the vendor). They make the public key portion of the GPG available on the Internet for their customers to acquire, and to use the public key to validate that the software package does:

1) indeed come from the vendor
2) has not been tampered with since leaving the vendor

This is exactly the relationship that exists between your smart device and your device’s App Store.

Lets check to see if we do GPG signature validation by default on my server:

demo@example:$ grep gpgcheck /etc/yum* -R

You want to see that gpgcheck has the value of 1 or true. If not, edit the repository definitions to enable these checks on .a per repo basis, or edit /etc/yum.conf to enable it for all repositories:

grep gpgcheck /etc/yum.conf

Next step is to see which GPG public keys you’ve imported as this indicates which vendors you trust.

demo@example:$ rpm -qa gpg-pubkey

To get more information about who owns the key use:

demo@example:$ rpm -qi ${name of gpg pubkey}

In my scenario, I don’t have any GPG public keys installed

I’m going to create my own GPG public and private keypair to sign the package nmap.

As it stands, I cannot validate the integrity of the nmap RPM as I do not have the public key imported into my RPM database, for the private key which was used to sign the RPM.

demo@example:$ rpm -K nmap-6.40-7.el7.x86_64.rpm
nmap-6.40-7.el7.x86_64.rpm: RSA sha1 ((MD5) PGP) md5 NOT OK (MISSING KEYS: (MD5) PGP#fd431d51) 

Now, let’s create our own public and private key pair:

demo@example:$ gpg --gen-key
gpg (GnuPG) 2.0.22; Copyright (C) 2013 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.

gpg: keyring `/home/student/.gnupg/secring.gpg' created
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 
Requested keysize is 2048 bits
Please specify how long the key should be valid.
0 = key does not expire
= key expires in n days
w = key expires in n weeks
m = key expires in n months
y = key expires in n years
Key is valid for? (0) 5y
Key expires at Wed 04 Aug 2021 08:01:37 AM EDT
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: Example Corp Package Manager
Email address: packman@example.com
Comment: 
You selected this USER-ID:
"Example Corp Package Manager <packman@example.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
You need a Passphrase to protect your secret key.

We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

gpg: key CED68B91 marked as ultimately trusted
public and secret key created and signed.

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2021-08-04
pub 2048R/CED68B91 2016-08-05 [expires: 2021-08-04]
Key fingerprint = 6757 6075 1C2D 8016 A234 D54A 5B92 FF35 CED6 8B91
uid Example Corp Package Manager <packman@example.com>
sub 2048R/C0A79171 2016-08-05 [expires: 2021-08-04]

The key has been created using the algorithm RSA, 2048 bits in size, with the name CED68B91, expiring on 2021-08-04.

While we have the keypair, we have yet to identify that any software package which is signed with the private key portion, is trusted. To do this I need to export the armor of my public key and import it into YUM which handles package management on RHEL based systems.

Let’s see which GPG keys I have:

demo@example:$ gpg --list-keys
/home/student/.gnupg/pubring.gpg
--------------------------------
pub 2048R/CED68B91 2016-08-05 [expires: 2021-08-04]
uid Example Corp Package Manager <packman@example.com>
sub 2048R/C0A79171 2016-08-05 [expires: 2021-08-04]

Now, export the armor to a plain text file:

demo@example:$ gpg --armor --export CED68B91 > mykey.pub

Let’s look at the pre-import state of the public keys which YUM uses for trusts.

demo@example:$ rpm -qa gpg-pubkey

This is a null listing.

Now, import the public key for YUM to use.

demo@example:$ rpm -qa gpg-pubkey
[student@workstation ~]$ sudo rpm --import mykey.pub 
[sudo] password for student: 

Check the list of public keys installed on your system again:

demo@example:$ rpm -qa gpg-pubkey
gpg-pubkey-ced68b91-57a48044

We have a public key trusted by YUM called CED68b91 – does that name look familiar?

Let’s see who it belongs to:

demo@example:$ rpm -qi gpg-pubkey-ced68b91-57a48044
Name : gpg-pubkey
Version : ced68b91
Release : 57a48044
Architecture: (none)
Install Date: Fri 05 Aug 2016 08:09:14 AM EDT
Group : Public Keys
Size : 0
License : pubkey
Signature : (none)
Source RPM : (none)
Build Date : Fri 05 Aug 2016 08:02:12 AM EDT
Build Host : localhost
Relocations : (not relocatable)
Packager : Example Corp Package Manager <packman@example.com>
Summary : gpg(Example Corp Package Manager <packman@example.com>)
Description :
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: rpm-4.11.3 (NSS-3)

mQENBFekgEQBCAC/N9HCTNzng4+a0CT1QkrdEPCZCvnchuoNptA01FCO43765vzy
VUPUDxq3pofCAivLEbIj3SUUyk5YZvxdVkqlUXo8RQLhrvAAAXcIAvqwU10/GZOg
AW+48IKjMjBZXtw7JkOZIcprpf3kejAsIgqQf2OOvHZKv4iuDT7lxUB4sWXdU1hy
huffqMPp0oxC0XBPHke68Id4kz8PdQ+JQUoCNwZK4hOsf+FAtmDjrVojengGAo20
Ps3KgfhD9+x8DhLDOPRFe94ueak2EOg4ylqgRGgswO8863dTb8IC9ubkrx59lqAz
mNcY8TGmHI8PSOV9qGdc0nIlPrg9mQOyTvrhABEBAAG0LEFDTUUgQ29ycCBQYWNr
YWdlIE1hbmFnZXIgPHBhY2ttYW5AYWNtZS5jb20+iQE/BBMBAgApBQJXpIBEAhsD
BQkJZgGABwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQW5L/Nc7Wi5Hv7ggA
gY3PKc4UL/VFMrTsiDVz+va8y/H3tGF5Ai9bDutRA1FhORA1nXKdVvX4ekW6Q8qZ
LlqPQbtqVsxLbyICi38QdHDYMfHjEuh68f3WEF3MAGlZf6lLKXirdF34pf0v+P+b
73ObWpvTKMarOwmAE1gJbE/B/z7cbaLhi4nNwbYIKYuLTrTrfSTjUMl+jXIKUah6
giMZoGNeVYuLR83y5sKiNULYT7fz2t791ApXdFkh1rF6YyFkbZX1c59VAaFI8EMQ
NFIwQzgvAeYlgnIHhIPp2oPfFLbU1IBG02RB/zG6p9ug/nyUG8dJbwqsLmeaHsP/
sOafcKJ9RFy/wEfdqMH+FbkBDQRXpIBEAQgAwlgDTGf5vStO2L3NseXc+GZvnvPj
OV51mlFlDuB4PbuNI98TjDGvdbM8PZD1RgK6twqPOkOn40mMxzO/yhEtmlks57KJ
11peprLTvN/RHJfcbUpObQ33Rl+8rt/jYZtavCxN1Rwti3p0VuBL42VqSeXbj/lm
QVQYV3GxZ9ekHk/8FYBvtYaEWx0/3Katv+M79jBw+naqXHv2JXjnVC6yfSz0mXYl
Mw8moy61JwIgBuLRrgXi1CGIiU9z8os/kFzd1+DPdR01wbr1tjpb4o6FOCfxxMUk
IJIKZYmTDd42LmYq5cri6X64R2AdPPQXcscnoulLdVGQCH60uhtBjHE3gQARAQAB
iQElBBgBAgAPBQJXpIBEAhsMBQkJZgGAAAoJEFuS/zXO1ouRIjUIAKasbDGxT01z
dYUdL4rDghKhA6pz4cxwyt6G3RwJXsNDfbHrbUJ8vHo/V5Nyuy0EELLJXh3ReXHK
PVQCP8L3MOmlE6LBKNliVTMzIRVqF68ad+vtIYYLB13GoMuiUyKcPlpWLjBxhc8v
iFxzlWT1fUpNW+/v7mRlT/aYzsCcuUa2nf+lWR5h2PKyCJc99NaavhXvX3x6GWOo
5iF1g2KW+bfuHybhBvhnT5MA2Dla9RFd6uqOCIV6MhnJQO2txK4jmO8SGE5g8YZS
Qswsf/KbWIvdalcnB87ojdxdiFUX0i+wqiu5bYtP5i2eZDEHkeoTe81fv2CLoHWu
PD8pTtsx0ac=
=qS4M
-----END PGP PUBLIC KEY BLOCK-----

Any RPM packages which has been signed with the public key’s partner private key, will be trusted by YUM.

I’ve downloaded nmap from my repository to my home direcrory,  using yumdownloader as follows:

demo@example:$ yumdownloader nmap
Loaded plugins: langpacks

Let's have a look at the downloaded file: 
 
demo@example:$ ls -l nmap-6.40-7.el7.x86_64.rpm 
-rw-rw-r--. 1 student student 4139888 Aug 10 2015 nmap-6.40-7.el7.x86_64.rpm

But will nmap be installable on my system?

demo@example:$ rpm -K nmap-6.40-7.el7.x86_64.rpm 
nmap-6.40-7.el7.x86_64.rpm: RSA sha1 ((MD5) PGP) md5 NOT OK (MISSING KEYS: (MD5) PGP#fd431d51) 

NO!

As root, do the following to create your own repository

 
demo@example:$ mkdir /local-repo
demo@example:$ cp /home/student/nmap-6.40-7.el7.x86_64.rpm /local-repo

Package the above directory in repository format by creating the YUM catalog which describes the repo’s content:

demo@example:$ createrepo /local-repo

Let’s create a repository definition for my local machine:

demo@example:$ cat > /etc/yum.repos.d/local.repo << EOF
[localrepo]
name=demo repo
gpgcheck=1
baseurl=file:///local-repo
EOF

Exit from your root session to be logged in as a local user and install nmap from your newly created and defined local repo:

demo@example:$ sudo yum -y --disablerepo=* --enablerepo=localrepo install nmap
Loaded plugins: langpacks, search-disabled-repos
Resolving Dependencies
--> Running transaction check
---> Package nmap.x86_64 2:6.40-7.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

===================================================================================================================================================================================
Package Arch Version Repository Size
===================================================================================================================================================================================
Installing:
nmap x86_64 2:6.40-7.el7 localrepo 3.9 M

Transaction Summary
===================================================================================================================================================================================
Install 1 Package

Total download size: 3.9 M
Installed size: 16 M
Downloading packages:
warning: /home/student/local-repo/nmap-6.40-7.el7.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID fd431d51: NOKEY
Public key for nmap-6.40-7.el7.x86_64.rpm is not installed


Public key for nmap-6.40-7.el7.x86_64.rpm is not installed

This makes sense because the nmap RPM has not been signed with the private key, of the public key which we trust. So lets sign the RPM with rpm-sign.

demo@example:$ sudo yum install -y rpm-sign

Now create ~/.rpmmacros which refers to the private key which you want to use to sign RPMs

demo@example:$ cat > ~/.rpmmacros << EOF
%_gpg_name CED68B91
EOF

Let’s do the signing with the CED68B91 private key.

demo@example:$ rpm --resign /local-repo/nmap-6.40-7.el7.x86_64.rpm 
Enter pass phrase: 
Pass phrase is good.

Now let’s see the key difference when we verify the signature:

demo@example:$ rpm -K local-repo/nmap-6.40-7.el7.x86_64.rpm 
local-repo/nmap-6.40-7.el7.x86_64.rpm: rsa sha1 (md5) pgp md5 OK

The signature on the RPM file (which was created by the private key) matches a public key which we have imported into YUM.

Now we should be able to install the RPM using YUM:

demo@example:$ sudo yum -y --disablerepo=* --enablerepo=localrepo install nmap
Loaded plugins: langpacks, search-disabled-repos
localrepo | 2.9 kB 00:00:00 
localrepo/primary_db | 2.9 kB 00:00:00 
Resolving Dependencies
--> Running transaction check
---> Package nmap.x86_64 2:6.40-7.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

===================================================================================================================================================================================
Package Arch Version Repository Size
===================================================================================================================================================================================
Installing:
nmap x86_64 2:6.40-7.el7 localrepo 3.9 M

Transaction Summary
===================================================================================================================================================================================
Install 1 Package

Total download size: 3.9 M
Installed size: 16 M
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Installing : 2:nmap-6.40-7.el7.x86_64 1/1 
Verifying : 2:nmap-6.40-7.el7.x86_64 1/1 

Installed:
nmap.x86_64 2:6.40-7.el7 

Complete!
Labels (4)
Join the discussion
You must log in to join this conversation.