Configuring GPG clients with per user Environments

This procedure provides an example for a GPG per-user configuration. In this procedure, you'll use the gpgconfig command line utility do the following:

  • Set the Trust Protection Platform authentication and virtual HSM URLs
  • Establish trust with the Trust Protection Platform server
  • Obtain a grant enabling client access to the virtual HSM
  • List Trust Protection Platform-protected code signing certificates that are available for you to use
  • Upload an existing user GPG key

Prerequisites

  • Trust Protection Platform is already installed and CodeSign Protect is licensed. You have the URL to your Trust Protection Platform server. The following service modules are enabled:

    • Certificate Lifecycle and Monitoring
    • Key Lifecycle and Monitoring
    • HSM Backend
    • Authentication Server
    • Web Console
    • Web SDK
  • A CodeSign Protect Project is configured with at least one per-user GPG Environment, and the person or group using the private keys have Key User permission.
  • The CodeSign Protect client is installed on the code signing workstation.

NOTE  All of the configuration commands apply to Windows, Linux, and macOS. However, storage of configuration data varies.

On Windows, the configuration is stored in the registry. For Linux and macOS, the configuration is stored in the file, and trust is stored in the ~/.libhsmtrust file.

The paths to the gpgconfig utility are:

  • Linux: /usr/local/bin
  • macOS: /usr/local/bin
  • Windows: c:\Program Files\Venafi CodeSign Protect

Steps

TIP  The next three examples (setting the URLs, establishing trust, and getting a grant) provide examples of several gpgconfig commands to help familiarize you with the usage. Each of the next three examples, however, can be completed using just the following command:

$ gpgconfig getgrant --authurl=https://TPP_SERVER_URL/vedauth --hsmurl=https://TPP_SERVER_URL/vedhsm \
--username=sample-user --password=Passw0rd --force

Set the authentication server and virtual HSM server URLs

$ gpgconfig seturl --authurl=https://TPP_SERVER_URL/vedauth --hsmurl=https://TPP_SERVER_URL/vedhsm
					
INFO: HSM Url:            https://TPP_SERVER_URL/vedhsm/  
INFO: Authentication Url: https://TPP_SERVER_URL/vedauth/

If you don't specify the URLs on the command line, you will be prompted for them.

You can verify the URLs using the following:

$ gpgconfig option --show
					
User configuration holds 2 values:
   HSM SERVER URL = https://TPP_SERVER_URL/vedhsm/
   AUTH SERVER URL = https://TPP_SERVER_URL/vedauth/

Establish trust with the Trust Protection Platform server

Establish trust by adding the server TLS certificate(s) to the local trust store. Having the certificates in the local trust store provides protection against man-in-the-middle attacks and ensures the library is only communicating with trusted backends.

$ gpgconfig trust --hsmurl=https://TPP_SERVER_URL/vedhsm
					
INFO: Requesting certificates from https://TPP_SERVER_URL/vedhsm.
 Server presented 2 certificates:
 Certificate 1:
   Subject: C=US, O=DigiCert Inc, CN=DigiCert SHA2 Secure Server CA
   Issuer : C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA
   Serial : 01:FD:A3:EB:6E:CA:75:C8:88:43:8B:72:4B:CF:BC:91
   Certificate has CA constraint

 Certificate 2:
   Subject: C=US, ST=Utah, L=Salt Lake City, O=Venafi, Inc., OU=Engineering, CN=CodeSignDev.vfidev.com
   Issuer : C=US, O=DigiCert Inc, CN=DigiCert SHA2 Secure Server CA
   Serial : 0D:49:B8:FB:FC:47:43:2D:F3:82:6C:47:EA:2A:9A:85

 Add these certificates to the user store? (y/N) :

The presented certificates will be displayed, and you will be prompted whether you want to add the certificates to the logged-in user's store. Answer y only after ensuring the certificates match the Trust Protection Platform backend certificates. The certificates are stored in ~/.libhsmtrust.

You can verify your trust settings using the gpgconfig trust -show command:

$ gpgconfig trust --show
				
User store certificates (/root/.libhsmtrust):
 Certificate 1:
   Subject: C=US, O=DigiCert Inc, CN=DigiCert SHA2 Secure Server CA
   Issuer : C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA
   Serial : 01:FD:A3:EB:6E:CA:75:C8:88:43:8B:72:4B:CF:BC:91
   Certificate has CA constraint

 Certificate 2:
   Subject: C=US, ST=Utah, L=Salt Lake City, O=Venafi, Inc., OU=Engineering, CN=CodeSignDev.vfidev.com
   Issuer : C=US, O=DigiCert Inc, CN=DigiCert SHA2 Secure Server CA
   Serial : 0D:49:B8:FB:FC:47:43:2D:F3:82:6C:47:EA:2A:9A:85

Get grant

$ gpgconfig getgrant --username=sample-user --password=Passw0rd

INFO: Requesting a new grant.
INFO: Valid grant and refresh token available. Grant expires Wed Feb 12 01:14:43 2020, 90 days from now
SUCCESS: Grant is valid.
SUCCESS: New grant obtained.

This command queries the authentication server, and if the user credentials are valid, returns a grant. If you don't enter the credentials in the command line, you will be prompted to enter them.

You can verify the validity of a grant using the checkgrant option:

$ gpgconfig checkgrant

INFO: Authentication Url: https://TPP_SERVER_URL/vedauth/
INFO: HSM Url:            https://TPP_SERVER_URL/vedhsm/
INFO: Valid grant and refresh token found. Grant expires Sun Feb  9 22:11:34 2020, 89 days from now
SUCCESS: Grant is valid.

List available objects

Listing the available Environments verifies that the Project Environments have been properly configured and are ready to use.

gpgconfig listobjects

Company Signer <company.signer@example.com> [GPG-RPM-Signing-RPM-Signing] [GPG]
  Label:       GPG-RPM-Signing-RPM-Signing
  GPG uid:     Company Signer <company.signer@example.com>
  Public Key:  RSA (4096 bits)  (Authentication)
  Public Key:  RSA (4096 bits)  (Encryption)
  Public Key:  RSA (4096 bits)  (Signing)

SUCCESS: 0 certificates, 3 public keys, 0 private keys, 0 secret keys

Sync GPG keys

To sync your GPG keys from Trust Protection Platform to your workstation, use the sync command:

gpgconfig sync
Loaded signing key for Company Signer <company.signer@example.com>
        KEYID: 509E4F122F7376F8
        FPR:   BB703F5F9722F18C4A7E11C1509E4F122F7376F8
        Grip:  B5C6675FF8CC4F39FC94844689DA14EB411004A4
Loaded encrypt key for Company Signer <company.signer@example.com>
        KEYID: C5336DDAF7EB2D3B
        FPR:   7C9DB0CD2E01597CECD2EF8CC5336DDAF7EB2D3B
        Grip:  051FA3D96E3AFE0D6D975AEFFFD40FE5A9997F17
Loaded authentication key for Company Signer <company.signer@example.com>
        KEYID: 4C1E903442B30735
        FPR:   86C2A2F36F4138701BE87C414C1E903442B30735
        Grip:  FFDDAC390C954EBF2881A270FC022429A0B049F8
VenafiSCD: INFO: Exported publickey for 'Company Signer <company.signer@example.com>'
SUCCESS: One key synchronized with the gpg keychain at '/root/.gnupg'

The gpgconfig sync command does the following:

  1. Configures GPG to use the CodeSign Protect executable for Smart Cards instead of the built-in GPG support.
  2. Exports the public keys from each available environment in the OpenPGP format complete with signed user IDs (UIDs) and signed subkeys.
  3. Imports the public keys into the GPG keychain.
  4. Configures GPG to link each of the public keys to the appropriate virtual Smart Card that holds the matching private key.
  5. Configures GPG to treat the keys as trusted.

Once the sync is complete, the GPG keys are ready to be used for signing.

Verify signature

After the keys have been synced, they are ready to be used for signing. To verify a key, use the following command. This example specifies jean as the default key.

$ echo foo | gpg --sign --armor --default-key company.signer@example.com | gpg --verify
gpg: using "company.signer@example.com" as default secret key for signing
gpg: Signature made Wed 16 Sep 2020 06:14:01 PM MDT
gpg:                using RSA key BB703F5F9722F18C4A7E11C1509E4F122F7376F8
gpg:                issuer "company.signer@example.com"
gpg: Good signature from "Company Signer <company.signer@example.com>" [ultimate]

Uploading a private GPG user key

NOTE  This option is available only for per-user GPG environments.

If you already have your own GPG key, you can upload your key to the Trust Protection Platform server. Uploading your private key replaces the key that was generated for when you listed the objects available to you above. After uploading, you can continue using your key as before, but your key will be stored and protected in the Trust Protection Platform Secret Store rather than stored on your local machine.

IMPORTANT  Since this process removes your private key from your machine, we recommend you backup your key before starting. Once the process is completed successfully, you no longer need the backup.

To complete these steps, you'll need your private key's UID and passphrase, and the label of the CodeSign Protect environment.

Get UID of existing key

$ gpg --list-secret-keys
sec   rsa3072 2020-09-17 [SC]
      F1C2CD549C3F4564D1825AC627A4902E2038B09F
uid           [ultimate] Real Name <real.email@example.com>
ssb   rsa3072 2020-09-17 [E]

You can use any part of the uid that uniquely identifies this key. In this example, we'll use the email address.

Get Label of the CodeSign Protect Environment

$ gpgconfig listobjects
Sample GPG PerUser <sample.peruser@example.com> [GPG-User-git-commit-signing] [GPG]
  Label:       GPG-User-git-commit-signing
  GPG uid:     Sample GPG PerUser <sample.peruser@example.com>
  Public Key:  RSA (4096 bits)  (Authentication)
  Public Key:  RSA (4096 bits)  (Encryption)
  Public Key:  RSA (4096 bits)  (Signing)

SUCCESS: 0 certificates, 3 public keys, 0 private keys, 0 secret keys

Use the value in the Label field.

Upload existing key

$ gpgconfig storekey -uid real.email@example.com -label GPG-User-git-commit-signing

gpg (GnuPG) 2.2.12; Copyright (C) 2018 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.

Secret key is available.

sec  rsa3072/27A4902E2038B09F
     created: 2020-09-17  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa3072/F29C535B092250FF
     created: 2020-09-17  expires: never       usage: E
[ultimate] (1). Real Name <real.email@example.com>

Really move the primary key? (y/N) y
Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 1

gpg: WARNING: such a key has already been stored on the card!

Replace existing key? (y/N) y

sec  rsa3072/27A4902E2038B09F
     created: 2020-09-17  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa3072/F29C535B092250FF
     created: 2020-09-17  expires: never       usage: E
[ultimate] (1). Real Name <real.email@example.com>

Loaded signing key for Sample GPG PerUser <sample.peruser@example.com>
        KEYID: 27A4902E2038B09F
        FPR:   F1C2CD549C3F4564D1825AC627A4902E2038B09F
        Grip:  EF5F479FD42CC52844772F2AEF9538BA0114B697
Loaded encrypt key for Sample GPG PerUser <sample.peruser@example.com>
        KEYID: 9649F32EB56274FC
        FPR:   270959F5DBBF511243AFFD3F9649F32EB56274FC
        Grip:  B28A1E762842D71028813034288A1570D6C91797
Loaded authentication key for Sample GPG PerUser <sample.peruser@example.com>
        KEYID: C0DE7AFFCF8BF041
        FPR:   23060EBF97DC86EEA258518FC0DE7AFFCF8BF041
        Grip:  D826F05AE653CF727FCE312B168914DD6C6D3827
VenafiSCD: INFO: Exported publickey for 'Sample GPG PerUser <sample.peruser@example.com>'
SUCCESS: One key synchronized with the gpg keychain at '/root/.gnupg'

Verify key

$ gpg --list-secret-keys
sec>  rsa3072 2020-09-17 [SC]
      F1C2CD549C3F4564D1825AC627A4902E2038B09F
      Card serial no. = 5990 D0DCA75B
uid           [ unknown] Sample GPG PerUser <sample.peruser@example.com>
uid           [ultimate] Real Name <real.email@example.com>
ssb   rsa3072 2020-09-17 [E]
ssb>  rsa4096 2020-09-17 [A]
ssb>  rsa4096 2020-09-17 [E]

The new key has a couple of differences from the previous key:

  • A card serial number now indicates that this key is now linked to Trust Protection Platform.
  • A second UID was created using the UID values of the imported key. This was necessary since the UID values of the imported key were different from the UID created by the CodeSign Protect environment. The key can now be referenced using either UID.

    If the UID of the imported key and the environment match, then a second UID is not created.