GPG/PGP Key Generation and Management

GPG/PGP Key Generation and Management

·

4 min read

Recently had to generate new GPG keys. If on Windows Gpg4win or Kleopatra is recommended. Below are using GnuPG in Ubuntu Linux to generate asymmetric keys for encryption.

sudo apt-get install gnupg

Key Generation

This will start the key-generation prompts

gpg --full-generate-key

The default is rsa3072(previously 2048) but will be using 4096-bit key.

gpg --default-new-key-algo rsa4096 --full-generate-key

Unattended/Batch

You can also do an unintended uninstall if provided a file.

cat >key_gen_info <<EOF
     %echo Generating a basic OpenPGP key
     Key-Type: RSA
     Key-Length: 3072
     Subkey-Type: RSA
     Subkey-Length: 3072
     Name-Real: Wind010
     Name-Comment: Example Key
     Name-Email: tester@test.com
     Expire-Date: 1y
     Passphrase: <your_password_here>
     # Do a commit here, so that we can later print "done"
     %commit
     %echo done
EOF

Then pass it in with --batch flag:

 gpg --batch --generate-key key_gen_info

Add some entropy by pressing the keys and moving the mouse when generating the keys:

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.

Because computers are deterministic the pseudorandom number generator needs some external input as a seed.

You'll get an error message if there is insufficient randomness:

Not enough random bytes available. Please do some other work to give the OS a chance to collect more entropy! (Need 210 more bytes)**

NOTE: If you cancel out of the passphrase entry stage on a prompted key generation, it may hang. You can look up the gpg-agent process with ps aux and kill the process id with kill -9 <gpg_agent_process_id>.

Show/List Keys

Once the keys are generated you can list the public and private keys using the following:

gpg --list-keys
gpg --list-secret-keys

The keys can be identified with the email address provided or the unique user key.

Export Keys

I'm exporting to with --armor for an ASCII armored file instead of binary.

Public Key

gpg --output public.asc --armor --export [email_or_user_id]

Private Key

gpg --output private.asc --armor --export-secret-key [email_or_user_id]

Or with a passphrase provided (single quotes to avoid string interpolation/expansion):

gpg --output private.asc --armor --batch --pinentry-mode=loopback --yes --passphrase '[your_password]' --export-secret-key [email_or_user_id]

Import Key

gpg --import [your_public_or_private_key]

Encryption/Decryption

Encrypt

Use the public key to encrypt the specified file.

gpg --output [your_encrypted_filename] --encrypt --recipient [email_or_user_id] [your_unencrypted_filename]

Decrypt

If you have the private key imported the decryption occurs without specifying the private key.

gpg --output [your_unencrypted_filename] --decrypt [your_encrypted_filename]

or

gpg --output [your_unencrypted_filename] --passphrase [your passphrase]--decrypt [your_encrypted_filename]

Delete

Public Key

gpg --delete-key [email_or_user_id]

Private Key

gpg --delete-secret-key [email_or_user_id]

With no prompts include --batch --yes as options. The --yes is specific to private key deletion. Note that deleting the private key will not automatically delete your public key from the keyring (~/.gnupg/pubring.pbx).

Additional

If you wanted to remove all newlines from the file or replace newlines with \n for storage in say KeyVault:

Delete

tr --delete '\n' < pub.asc

Replace

sed -E ':a;N;$!ba;s/\r{0,1}\n/\\n/g' file

or with Powershell

Delete

(Get-Content -Path 'public.asc') -Join | Out-File -Path 'new_public.asc'
# OR
(GC 'public.asc') -Join > 'new_public.asc'

Replace

(Get-Content -Path '.\public_test.asc') -Join "\n"
# OR
(GC 'public.asc') -Join "\n"

To format the one-line key back to its original format something like this could be done:

sed 's/\\n/\'$'\n''/g'

You can also just echo the single line in the shell which would interpret the \n as a newline.

Powershell

(GC 'public.asc') -Replace "\n" "`r`n"

If the header and footer were removed and newlines or newline indicators/characters were removed:

Updates

  • If you use Azure CLI to pull down these keys with windows it stores the file encoded as UTF-32 LE which could cause issues with search and replace needed to replace \n with actual newline. Best to re-encode it to ASCII.

References