PGP Key Security generating and using SubKeys.

Loosing the private key it’s bad, but if someone steals the private key, it’s a disaster.
Thieves can not only decrypt personal data, they can also impersonate the owner by signing messages with his private key.
Yes, it is possible to revoke the stolen key, but that would mean probably loose years of signatures and basically creating a massive inconvenience to redistribute a new public key to the world. SubKeys can help to prevent this disaster.

Having separate SubKeys makes key management easier and protects you in certain occasions, for example it is possible to create a new SubKey when a previous one gets stolen, without losing previous signatures.

SubKeys can’t prevent a thief from decrypting messages intended for a private key, but they can help to have a minor damage to identities when a key is lost or stolen.
By using SubKeys, it is not possible to sign other people’s keys. To accomplish that, the “Master Secret Key” is needed. This is a small side-effect that does not impact in everyday use of PGP/GPG usually.

To generate and use a PGP (GPG) KeyRing using SubKeys, some steps are needed:

  • Generate an RSA Sign-Only key with high encryption level.
    This Key will be the “Master Secret Key” and has to be stored in a protected place and it is suggested to have it also printed in paper (as shown in another post).
  • Add additional SubKeys to the KeyPair, with Encryption, Signing (and maybe Authentication, if needed) capabilities (assign each capability to a specific SubKey is suggested).
  • Generate a revocation certificate file to be stored in a safe place. If the “Master Secret Key” gets lost or stolen this certificate is the only way to revoke the key.
  • Remove the “Master Secret Key” (the one that needs to be secretly stored) keeping only Secret SubKeys.
  • Use SubKeys for their specific capabilities also in portable devices, for example to sign eMail messages or crypt data.
  • Use the “Master Secret Key” only to sign other keys, keeping it in a safe place and not in KeyRings used for daily purposes.

Let’s view the procedure in CLI (using gpg).

Very Important Notes:

  • It is suggested to create a working path dedicated to this activities, for example consider to create and a directory called TMP_GPG where temporarily save your data like dumps, certificates, etc.. The best and definitive location will be found later according to personal storage policies and options.
  • In these examples some keys will be generated and some commands will be executed ‘calling’ the KeyID (Ex.: 5F15E945 for the “Master Secret Key”). Obviously it is needed to change it, by using the personal and right KeyID.
  • Before doing anything make sure a backup of your current GPG configuration and environment (including actual Keys, if installed) has been done!

Generate an RSA Sign-Only key with high encryption level

$ gpg2 --gen-key

Select option 4 for “RSA (sign only)” and a long keysize (at least 4096 bits), set the key to not expire.
Construct a user ID to identify the key, by filling fields with real data.
Enter a long and stong Passphrase to protect the secret key. Please remember that we are creating the “Master Secret Key” at this stage, so keep Security in mind!

The Master Secret Key will be created and shown as follows:

pub   4096R/5F15E945 2014-09-12
      Key fingerprint = 3282 C9F4 9B7B 289D 8DEC  2682 C152 AEA5 5F15 E945
uid                  IntSec.NET NOC <noc@intsec.net>

Harden some encryption preferences:

$ gpg2 --edit-key 5F15E945

set inside gpg CLI:

setpref SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed

Add additional SubKeys to the KeyPair

We will use ‘expert’ editing mode in gpg since we will generate a SubKey with Authentication Capability, the expert mode is not needed if this SubKey has not to be generated.
We will generate three keys, one with Signing, one with Encryption and one with Authentication capability.

$ gpg2 --expert --edit-key 5F15E945

For the first SubKey, let’s execute the command ‘addkey’ and then select option 4 (RSA sign only), select a long keysize (4096 bits is suggested) and specify how long the key should be valid according to personal policies.
For the second SubKey, let’s execute again the command ‘addkey’ and then select option 6 (RSA encrypt only), select a long keysize (4096 bits is suggested) and specify how long the key should be valid according to personal policies.
For the third SubKey, let’s execute again the command ‘addkey’ and then select option 8 (RSA set your own capabilities), toggle Sign and Encrypt capability OFF and Authenticate capability ON, then select a long keysize (4096 bits is suggested) and specify how long the key should be valid according to personal policies.

Check the result with ‘list’ command, the output should appear like this:

pub  4096R/5F15E945  created: 2014-09-12  expires: never       usage: SC  
                     trust: ultimate      validity: ultimate
sub  4096R/65989256  created: 2014-09-12  expires: never       usage: S   
sub  4096R/5FA88CA4  created: 2014-09-12  expires: never       usage: E   
sub  4096R/43F35C05  created: 2014-09-12  expires: never       usage: A   
[ultimate] (1). IntSec.NET NOC <noc@intsec.net>

If everything is correct, save and exit with ‘save’ GPG command.


Generate a revocation certificate file

$ gpg2 --output 5F15E945_revocation_certificate.asc \
--gen-revoke 5F15E945

Confirm you are requesting a revocation certificate, select the reason for the revocation and (optionally) insert a note. A file called 5F15E945_revocation_certificate.asc containing the certificate will be created in your current working directory.

Important Notes: This certificate will be used only to revoke the “Master Secret Key”, in case access to it will be lost.
Revoking SubKeys will be done using the “Master Secret Key” and not this revocation certificate!


Save (dump) the “Master Secret Key” and remove it from the KeyRing keeping in it only Secret SubKeys
GnuPG is not able to remove the “Master Secret Key” while keeping its SubKeys, for this reason it is needed to:

Export in different files secret key and secret subkeys

$ gpg2 --armor --export-secret-keys 5F15E945 \
> 5F15E945_secret.asc
$ gpg2 --armor --export-secret-subkeys 5F15E945 \
> 5F15E945_subkeys.asc

Delete the complete secret keys

$ gpg2 --delete-secret-key 5F15E945

import-back only the SubKeys

$ gpg2 --import 5F15E945_subkeys.asc

To check if everything is ok, ask gpg to list secret keys for your KeyID:

$ gpg2 --list-secret-keys 5F15E945

The output should be something similar to this:

sec#  4096R/5F15E945 2014-09-12
uid                  IntSec.NET NOC <noc@intsec.net>
ssb   4096R/65989256 2014-09-12
ssb   4096R/5FA88CA4 2014-09-12
ssb   4096R/43F35C05 2014-09-12

The pound (#) in the “sec” line means that the “Master Secret Key” is missing, as expected.


It is now possible to use the keys loaded into the KeyRing to encrypt, decrypt, and sign files and messages.
To sign someone other keys or to create or revoke a SubKey, the “Master Secret Key” will be needed, for this reason it is suggested to use a temporary KeyRing, in a safe environment.

It’s time now to distribute the Public Key to a KeyServer:

$ gpg2 --keyserver keys.gnupg.net --send-key 5F15E945

Very Important Notes:

Private Secret Keys has to be stored in safe places (at least two copies, in different kind of media) and removed securely from the temporary place where Key Creation and Dumps have been performed!
It is mandatory to remove any temporary files in the safest way from the media where all operation are made, for this reason it is suggested to use shred to overwrite the file multiple times using patterns chosen to maximize destruction of the residual data, after saving all the necessary to removable devices.

$ shred -vfzu -n 10 <FILENAME>

where FILENAME, in the case of this example, is (at least) 5F15E945_secret.asc and 5F15E945_revocation_certificate.asc or in other words files containing “Master Secret Key” and “Master Secret Key Revocation Certificate”


If the SubKeys will be compromised will be time to revoke them, to do this, simply get the “Master Secret Key” and import it into a temporary (secondary) keyring:

$ gpg2 --no-default-keyring \
--keyring ./tmp-public-kr.gpg \
--secret-keyring ./tmp-private-kr.gpg \
--trustdb-name ./tmp-trustdb.gpg \
--import ../5F15E945_secret.asc

Time to edit interactively the Key and generate the revocation certificate:

$ gpg2 --no-default-keyring \
--keyring ./tmp-public-kr.gpg \
--secret-keyring ./tmp-private-kr.gpg \
--trustdb-name ./tmp-trustdb.gpg \
--expert --edit-key 5F15E945

At the gpg prompt, list the keys issuing the list command, select the one to be revoked issuing the key command followed by sequential number of the SubKey, double-check you have selected the right SubKey (check that the key has been marked as selected with ‘*’) and generate the revocation certificate with the revkey command, then save.

Now send back the modified key to the KeyServer, containing the revocation request:

$ gpg2 --no-default-keyring \
--keyring ./tmp-public-kr.gpg \
--secret-keyring ./tmp-private-kr.gpg \
--trustdb-name ./tmp-trustdb.gpg \
--send-key --keyserver keys.gnupg.net 5F15E945

Very Important Notes: These operations should be done in a safe environment (a live Linux Distro is suggested). In any case, if temporary wallet is written in a non-volatile filesystem it is mandatory to remove temporary files in the safest way from the media where all these operation are made, for this reason it is suggested to use shred to overwrite the file multiple times using patterns chosen to maximize destruction of the residual data.

$ shred -vfzu -n 10 ./tmp*

A similar procedure could be done to sign someone other’s Key, by using a Temporary KeyRing.
As the previous example, get the “Master Secret Key” and import it into a temporary (secondary) keyring:

$ gpg2 --no-default-keyring \
--keyring ./tmp-public-kr.gpg \
--secret-keyring ./tmp-private-kr.gpg \
--trustdb-name ./tmp-trustdb.gpg \
--import ../5F15E945_secret.asc

Retrieve the key that needs to be signed:

$ gpg2 --no-default-keyring \
--keyring ./tmp-public-kr.gpg \
--secret-keyring ./tmp-private-kr.gpg \
--trustdb-name ./tmp-trustdb.gpg \
--keyserver x-hkp://pgp.mit.edu --recv-keys 8ED2364E

Check if the key has been correctly imported:

$ gpg2 --no-default-keyring \
--keyring ./tmp-public-kr.gpg \
--secret-keyring ./tmp-private-kr.gpg \
--trustdb-name ./tmp-trustdb.gpg \
--list-keys 8ED2364E

Sign the Key:

$ gpg2 --no-default-keyring \
--keyring ./tmp-public-kr.gpg \
--secret-keyring ./tmp-private-kr.gpg \
--trustdb-name ./tmp-trustdb.gpg \
--sign-key --ask-cert-level 8ED2364E

Upload back the key to the keyserver:

$ gpg2 --no-default-keyring \
--keyring ./tmp-public-kr.gpg \
--secret-keyring ./tmp-private-kr.gpg \
--trustdb-name ./tmp-trustdb.gpg \
--keyserver keys.gnupg.net --send-key 8ED2364E

Very Important Notes:

These operations should be done in a safe environment (a live Linux Distro is suggested). In any case, if temporary wallet is written in a non-volatile filesystem it is mandatory to remove temporary files in the safest way from the media where all these operation are made, for this reason it is suggested to use shred to overwrite the file multiple times using patterns chosen to maximize destruction of the residual data.

$ shred -vfzu -n 10 ./tmp*

Comments are closed.