edgecase
Author: StJohn Piano
Published: 2019-04-06
Datafeed Article 97
This article has been digitally signed by Edgecase Datafeed.
This article has been digitally signed by its author.
6436 words - 2597 lines - 65 pages





GOAL



On an instance of GPG 1.4.10, find ways to run basic GPG commands statelessly. "Statelessly" means that commands will always produce the same output regardless of the state of GPG's internal database.




CONTENTS



- Goal
- Contents
- Project Log




PROJECT LOG





In a previous project, I installed GPG 1.4.10 on CentOS 7.6 on my computer Shovel.

Link:
Installing GPG 1.4.10 on CentOS 7.6

System details:
- Name: Shovel
- Specifications: HP 6005 Pro SFF. 3 GHz x86_64 processor (AMD II x4 B95 Quad Core), 4 GB RAM, 1 TB hard drive. Running CentOS 7.6.1810 (Core).
- More information: New computer: Shovel
- Installed items: GCC 4.8.5, Make 3.82.


In another project, I assembled and tested a list of basic GPG commands.
Link:
Testing GPG 1.4.10

I extracted, edited, and re-published the results in a separate article for convenient reference:
Basic GPG Commands







As far as I can tell, GPG is not designed to be used statelessly. However, it does have some options that allow a different home directory and keyring file to be specified in the command.

Examples:

gpg --no-default-keyring --homedir keyring_tmp --keyring pubring.gpg --import edgecase_datafeed_public_key.txt


gpg --no-default-keyring --keyring pubring.gpg --homedir keyring_tmp --verify datafeed_article.sig datafeed_article.txt



This means that I can create a temporary home directory (containing a temporary keyring file), import a public or private key, perform an operation, and then delete the temporary home directory. This is a hacky way of achieving stateless functionality.

I recall from previous work that GPG will automatically create the keyring file, if this file is specified in the command but does not exist.


Create new project directory:
using_gpg_1410_statelessly

Within new project directory, create new work directory:
work


Open a terminal and change directory to the work directory.




[spiano@localhost work]$ mkdir tmp_gpg_home


[spiano@localhost work]$ chmod 700 tmp_gpg_home





I'm going to go through the commands listed in Basic GPG Commands and get them to work in a stateless manner, using a temporary directory as a gpg home directory.


Excerpt from the linked article:

LIST OF COMMANDS



1) Create key
2) Display key
2a) Display public key details
2b) Display private key details
3) Display details of all keys
3a) Display details of all public keys
3b) Display details of all private keys
4) Export key
4a) Export public key
4b) Export private key
5) Delete key
5a) Delete public key
5b) Delete private key
6) Import key
6a) Import public key
6b) Import private key
7) Sign a file using a specific key, producing a detached signature file
8) Verify the detached signature of a file, checking that the signature was made by a specific key
9) Encrypt a message file to a specific public key
10) Decrypt an encrypted message file, checking that the decryption was performed using a specific private key.





The actual GPG commands are listed in the next section (Basic GPG Commands) in the linked article. I won't copy the entire section here verbatim, but I'll use its material as a starting point.







1) Create key

Existing command:
gpg --gen-key


New version:
gpg --no-default-keyring --homedir tmp_gpg_home --gen-key


Interactive steps during key generation:
- 1) key type = "1" (RSA and RSA)
- 2) key size = "4096"
- 3) expiry period = "0" (never)
- 4) confirm expiry period = "y"
- 5) real name = "Test Key 1"
- 6) email address = ""
- 7) comment = ""
- 8) confirm real name, email address, and comment = "o"
- 9) passphrase = ""
- 10) confirm passphrase = ""
- 11) [wait for random bytes to be generated - GPG said that it would create a passphrase anyway]



Output:


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_gpg_home --gen-key

gpg (GnuPG) 1.4.10; Copyright (C) 2008 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 `tmp_gpg_home/secring.gpg' created gpg: keyring `tmp_gpg_home/pubring.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) 4096 Requested keysize is 4096 bits Please specify how long the key should be valid. 0 = key does not expire <n> = key expires in n days <n>w = key expires in n weeks <n>m = key expires in n months <n>y = key expires in n years Key is valid for? (0) 0 Key does not expire at all Is this correct? (y/N) y You need a user ID to identify your key; the software constructs the user ID from the Real Name, Comment and Email Address in this form: "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>" Real name: Test Key 1 Email address: Comment: You selected this USER-ID: "Test Key 1" Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o You need a Passphrase to protect your secret key. You don't want a passphrase - this is probably a *bad* idea! I will do it anyway. You can change your passphrase at any time, using this program with the option "--edit-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. ....+++++ ..... ..................+++++ 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: tmp_gpg_home/trustdb.gpg: trustdb created gpg: key 7DD2451C 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 pub 4096R/7DD2451C 2019-04-02 Key fingerprint = 7ACA BD43 1C15 1F86 E158 E0DB 0D17 B227 7DD2 451C uid Test Key 1 sub 4096R/183E79EE 2019-04-02





Ok.


[spiano@localhost work]$ ls -1 tmp_gpg_home

pubring.gpg
pubring.gpg~
random_seed
secring.gpg
trustdb.gpg




So: GPG created all the database files itself.


Compare with:

[spiano@localhost work]$ ls -1 ~/.gnupg

gpg.conf
pubring.gpg
pubring.gpg~
random_seed
secring.gpg
trustdb.gpg









2) Display key


2a) Display public key details


Existing command:
gpg --list-keys [key]


where [key] is any of the following: real name, short key ID, email address, or fingerprint. The fingerprint should not include spaces.

Add
--fingerprint
to the command to also display the key fingerprint.


New version:
gpg --no-default-keyring --homedir tmp_gpg_home --list-keys Test Key 1



Let's see:


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_gpg_home --list-keys "Test Key 1"

pub 4096R/7DD2451C 2019-04-02 uid Test Key 1 sub 4096R/183E79EE 2019-04-02


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_gpg_home --fingerprint --list-keys "Test Key 1"

pub 4096R/7DD2451C 2019-04-02 Key fingerprint = 7ACA BD43 1C15 1F86 E158 E0DB 0D17 B227 7DD2 451C uid Test Key 1 sub 4096R/183E79EE 2019-04-02






Hm. Ok. The
--no-default-keyring --homedir tmp_gpg_home

approach appears to work fine.



For actual statelessness, need to re-create the temporary home directory from scratch every time.

I'll try creating the temporary home directory, setting its permissions, importing the public key, then displaying its details.

For this, I will first need to export Test Key 1.






4) Export key


4a) Export public key

Existing command:
gpg --armor --export [key]


where [key] is any of the following: real name, short key ID, email address, or fingerprint. The fingerprint should not include spaces.

Redirect the output to a file to save the key.

New version:
gpg --no-default-keyring --homedir tmp_gpg_home --armor --export [key]



[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_gpg_home --armor --export "Test Key 1" > test_key_1_public_key.txt


[spiano@localhost work]$ ls -1

test_key_1_public_key.txt
tmp_gpg_home

[spiano@localhost work]$ cat test_key_1_public_key.txt

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.10 (GNU/Linux)

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
8MRA4hUcgRES3k2fK9rWjUQG2k1dk6CI
=Cu4t
-----END PGP PUBLIC KEY BLOCK-----





4b) Export private key

Existing command:
gpg --armor --export-secret-keys [key]


where [key] is any of the following: real name, short key ID, email address, or fingerprint. The fingerprint should not include spaces.

Redirect the output to a file to save the key.

New version:
gpg --no-default-keyring --homedir tmp_gpg_home --armor --export-secret-keys [key]



[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_gpg_home --armor --export-secret-keys "Test Key 1" > test_key_1_private_key.txt


[spiano@localhost work]$ ls -1

test_key_1_private_key.txt
test_key_1_public_key.txt
tmp_gpg_home

[spiano@localhost work]$ cat test_key_1_private_key.txt

-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v1.4.10 (GNU/Linux)

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
TZ8r2taNRAbaTV2ToIg=
=sfhq
-----END PGP PRIVATE KEY BLOCK-----








Cool.




Now, remove the temporary home directory.



[spiano@localhost work]$ rm -rf tmp_gpg_home




Let's try the fully stateless approach:
- create the temporary home directory
- set its permissions
- import the public key
- display the public key's details
- delete the temporary home directory


mkdir tmp_gpg_home && chmod 700 tmp_gpg_home && gpg --no-default-keyring --homedir tmp_gpg_home --keyring pubring.gpg --import test_key_1_public_key.txt && gpg --no-default-keyring --homedir tmp_gpg_home --fingerprint --list-keys "Test Key 1" && rm -r tmp_gpg_home





[spiano@localhost work]$ ls -1

test_key_1_private_key.txt
test_key_1_public_key.txt

[spiano@localhost work]$ mkdir tmp_gpg_home && chmod 700 tmp_gpg_home && gpg --no-default-keyring --homedir tmp_gpg_home --keyring pubring.gpg --import test_key_1_public_key.txt && gpg --no-default-keyring --homedir tmp_gpg_home --fingerprint --list-keys "Test Key 1" && rm -r tmp_gpg_home

gpg: keyring `tmp_gpg_home/secring.gpg' created gpg: keyring `tmp_gpg_home/pubring.gpg' created gpg: tmp_gpg_home/trustdb.gpg: trustdb created gpg: key 7DD2451C: public key "Test Key 1" imported gpg: Total number processed: 1 gpg: imported: 1 (RSA: 1) pub 4096R/7DD2451C 2019-04-02 Key fingerprint = 7ACA BD43 1C15 1F86 E158 E0DB 0D17 B227 7DD2 451C uid Test Key 1 sub 4096R/183E79EE 2019-04-02


[spiano@localhost work]$ ls -1

test_key_1_private_key.txt
test_key_1_public_key.txt






Cool.





I'll try suppressing the output of the import command.



[spiano@localhost work]$ mkdir tmp && chmod 700 tmp


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --keyring pubring.gpg --import test_key_1_public_key.txt > /dev/null 2>&1


[spiano@localhost work]$ ls -1 tmp

pubring.gpg
pubring.gpg~
secring.gpg
trustdb.gpg

[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --fingerprint --list-keys "Test Key 1"

pub 4096R/7DD2451C 2019-04-02 Key fingerprint = 7ACA BD43 1C15 1F86 E158 E0DB 0D17 B227 7DD2 451C uid Test Key 1 sub 4096R/183E79EE 2019-04-02


[spiano@localhost work]$ rm -r tmp





Good.








Ok. I'll start from the beginning again, this time focusing much more on pure statelessness (or as pure as possible).











1) Create key


Existing command:
gpg --gen-key



New sequence:

mkdir tmp && chmod 700 tmp


gpg --no-default-keyring --homedir tmp --gen-key


Important choice (because it's used in commands later in the sequence): real name

Interactive steps during key generation:
- 1) key type = "1" (RSA and RSA)
- 2) key size = "4096"
- 3) expiry period = "0" (never)
- 4) confirm expiry period = "y"
- 5) real name = "Test Key 2"
- 6) email address = ""
- 7) comment = ""
- 8) confirm real name, email address, and comment = "o"
- 9) passphrase = ""
- 10) confirm passphrase = ""
- 11) [wait for random bytes to be generated - GPG said that it would create a passphrase anyway]

gpg --no-default-keyring --homedir tmp --armor --export "Test Key 2" > test_key_2_public_key.txt


gpg --no-default-keyring --homedir tmp --armor --export-secret-keys "Test Key 2" > test_key_2_private_key.txt


rm -r tmp




Output:


[spiano@localhost work]$ mkdir tmp && chmod 700 tmp



[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --gen-key

gpg (GnuPG) 1.4.10; Copyright (C) 2008 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 `tmp/secring.gpg' created gpg: keyring `tmp/pubring.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) 4096 Requested keysize is 4096 bits Please specify how long the key should be valid. 0 = key does not expire <n> = key expires in n days <n>w = key expires in n weeks <n>m = key expires in n months <n>y = key expires in n years Key is valid for? (0) 0 Key does not expire at all Is this correct? (y/N) y You need a user ID to identify your key; the software constructs the user ID from the Real Name, Comment and Email Address in this form: "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>" Real name: Test Key 2 Email address: Comment: You selected this USER-ID: "Test Key 2" Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o You need a Passphrase to protect your secret key. You don't want a passphrase - this is probably a *bad* idea! I will do it anyway. You can change your passphrase at any time, using this program with the option "--edit-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. ..+++++ +++++ 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: tmp/trustdb.gpg: trustdb created gpg: key 258E4B1A 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 pub 4096R/258E4B1A 2019-04-05 Key fingerprint = 766A 976F 1056 B47E 3062 B002 3F84 F8FE 258E 4B1A uid Test Key 2 sub 4096R/50C96C60 2019-04-05



[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --armor --export "Test Key 2" > test_key_2_public_key.txt



[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --armor --export-secret-keys "Test Key 2" > test_key_2_private_key.txt



[spiano@localhost work]$ ls -1 tmp

pubring.gpg
pubring.gpg~
random_seed
secring.gpg
trustdb.gpg


[spiano@localhost work]$ rm -r tmp



[spiano@localhost work]$ ls -1

test_key_1_private_key.txt
test_key_1_public_key.txt
test_key_2_private_key.txt
test_key_2_public_key.txt


[spiano@localhost work]$ cat test_key_2_private_key.txt

-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v1.4.10 (GNU/Linux)

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
QANR85ll1yC7eNPJRbE=
=H1mc
-----END PGP PRIVATE KEY BLOCK-----


[spiano@localhost work]$ cat test_key_2_public_key.txt

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.10 (GNU/Linux)

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
7OBAt3uKsvA4a0ADUfOZZdcgu3jTyUWx
=lXxt
-----END PGP PUBLIC KEY BLOCK-----












2) Display key


2a) Display public key details

Existing command:
gpg --list-keys [key]


where [key] is any of the following: real name, short key ID, email address, or fingerprint. The fingerprint should not include spaces.

Add
--fingerprint
to the command to also display the key fingerprint.



New sequence:

mkdir tmp && chmod 700 tmp


gpg --no-default-keyring --homedir tmp --keyring pubring.gpg --import test_key_2_public_key.txt > /dev/null 2>&1


gpg --no-default-keyring --homedir tmp --keyring pubring.gpg --fingerprint --list-keys "Test Key 2"


rm -r tmp





Output:


[spiano@localhost work]$ mkdir tmp && chmod 700 tmp


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --keyring pubring.gpg --import test_key_2_public_key.txt > /dev/null 2>&1


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --keyring pubring.gpg --fingerprint --list-keys "Test Key 2"

pub 4096R/258E4B1A 2019-04-05 Key fingerprint = 766A 976F 1056 B47E 3062 B002 3F84 F8FE 258E 4B1A uid Test Key 2 sub 4096R/50C96C60 2019-04-05





Further experimentation: There is an option to show the long key IDs, rather than the short ones.


[note: forgot to record the output at the time. the output shown here is from a re-run.]
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --keyring pubring.gpg --keyid-format long --fingerprint --list-keys "Test Key 2"

pub 4096R/3F84F8FE258E4B1A 2019-04-05 Key fingerprint = 766A 976F 1056 B47E 3062 B002 3F84 F8FE 258E 4B1A uid Test Key 2 sub 4096R/7CBB1E9750C96C60 2019-04-05


[spiano@localhost work]$ ls -1 tmp

pubring.gpg
pubring.gpg~
secring.gpg
trustdb.gpg

[spiano@localhost work]$ rm -r tmp


[spiano@localhost work]$ ls -1

test_key_1_private_key.txt
test_key_1_public_key.txt
test_key_2_private_key.txt
test_key_2_public_key.txt






2b) Display private key details

Existing command:
gpg --fingerprint --list-secret-keys [key]


where [key] is any of the following: real name, short key ID, email address, or fingerprint. The fingerprint should not include spaces.



New sequence:

mkdir tmp && chmod 700 tmp


gpg --no-default-keyring --homedir tmp --keyring secring.gpg --import test_key_2_private_key.txt > /dev/null 2>&1


gpg --no-default-keyring --homedir tmp --keyring secring.gpg --keyid-format long --fingerprint --list-secret-keys "Test Key 2"


rm -r tmp




After some experimentation, I find that including the option
--keyring secring.gpg
causes GPG to not derive the public key from the private key. This would not be a problem, except that this then causes GPG to not display details for the private key when the
--list-secret-keys "Test Key 2"
command is run (although
--list-secret-keys
works by itself.


Example output:


[spiano@localhost work]$ mkdir tmp && chmod 700 tmp


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --keyring secring.gpg --import test_key_2_private_key.txt > /dev/null 2>&1


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --keyring secring.gpg --keyid-format long --fingerprint --list-secret-keys "Test Key 2"

gpg: tmp/trustdb.gpg: trustdb created
gpg: key 3F84F8FE258E4B1A: secret key without public key - skipped
gpg: error reading key: secret key not available

[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --keyring secring.gpg --keyid-format long --fingerprint --list-secret-keys

tmp/secring.gpg --------------- sec 4096R/3F84F8FE258E4B1A 2019-04-05 Key fingerprint = 766A 976F 1056 B47E 3062 B002 3F84 F8FE 258E 4B1A uid Test Key 2 ssb 4096R/7CBB1E9750C96C60 2019-04-05


[spiano@localhost work]$ rm -r tmp






Hm. Let's try not using the
--keyring
option.



Output:


[spiano@localhost work]$ mkdir tmp && chmod 700 tmp


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --import test_key_2_private_key.txt > /dev/null 2>&1


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --keyid-format long --fingerprint --list-secret-keys "Test Key 2"

sec 4096R/3F84F8FE258E4B1A 2019-04-05 Key fingerprint = 766A 976F 1056 B47E 3062 B002 3F84 F8FE 258E 4B1A uid Test Key 2 ssb 4096R/7CBB1E9750C96C60 2019-04-05


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --keyid-format long --fingerprint --list-keys "Test Key 2"

pub 4096R/3F84F8FE258E4B1A 2019-04-05 Key fingerprint = 766A 976F 1056 B47E 3062 B002 3F84 F8FE 258E 4B1A uid Test Key 2 sub 4096R/7CBB1E9750C96C60 2019-04-05


[spiano@localhost work]$ rm -r tmp




Good.


New sequence:

mkdir tmp && chmod 700 tmp


gpg --no-default-keyring --homedir tmp --import test_key_2_private_key.txt > /dev/null 2>&1


gpg --no-default-keyring --homedir tmp --keyid-format long --fingerprint --list-secret-keys "Test Key 2"


rm -r tmp





Hm. Strange. The long key ID, the fingerprint, and the long key ID of the subkey are the same in the output of the
--list-secret-keys
and the
--list-keys
command.

Perhaps the short key ID, the long key ID, and the fingerprint are only derived from the public key.

I had previously thought that both the public and private keys had key IDs and fingerprints. Looking back at Basic GPG Commands, in the Basic GPG Commands With Example Output section, item 3) Display details of all keys, I can see that the keyIDs are the same when either the public key details or the private key details are displayed.











3) Display details of all keys


3a) Display details of all public keys

Existing command:
gpg --list-keys


Add
--fingerprint
to the command to also display the key fingerprint.


The possibility that concerns me is:
- Key A is already in the temporary gpg keyring. It has key ID A.
- I import a new key B. It has key ID B.
- Key ID A == key ID B.
- GPG overwrites key A with key B, and key A will then be missing from the list of keys.


So, I'm going to treat this command as a repeated version of command 2a) Display public key details.



New sequence:

ls -1 | grep "public_key.txt" | while read input_file; do mkdir tmp && chmod 700 tmp && gpg --no-default-keyring --homedir tmp --import "$input_file" > /dev/null 2>&1 && gpg --no-default-keyring --homedir tmp --fingerprint --list-keys && rm -r tmp; done




This sequence will cause GPG to attempt to list public key details for all file in this directory that end in "public_key.txt".

Note: I've removed the
--keyring pubring.gpg
option.



Output:

[spiano@localhost work]$ ls -1 | grep "public_key.txt" | while read input_file; do mkdir tmp && chmod 700 tmp && gpg --no-default-keyring --homedir tmp --import "$input_file" > /dev/null 2>&1 && gpg --no-default-keyring --homedir tmp --fingerprint --list-keys && rm -r tmp; done

tmp/pubring.gpg --------------- pub 4096R/7DD2451C 2019-04-02 Key fingerprint = 7ACA BD43 1C15 1F86 E158 E0DB 0D17 B227 7DD2 451C uid Test Key 1 sub 4096R/183E79EE 2019-04-02 tmp/pubring.gpg --------------- pub 4096R/258E4B1A 2019-04-05 Key fingerprint = 766A 976F 1056 B47E 3062 B002 3F84 F8FE 258E 4B1A uid Test Key 2 sub 4096R/50C96C60 2019-04-05





3b) Display details of all private keys

Existing command:
gpg --list-secret-keys


Add
--fingerprint
to the command to also display the key fingerprint.



Same approach as for 3a.


New sequence:


ls -1 | grep "private_key.txt" | while read input_file; do mkdir tmp && chmod 700 tmp && gpg --no-default-keyring --homedir tmp --import "$input_file" > /dev/null 2>&1 && gpg --no-default-keyring --homedir tmp --fingerprint --list-secret-keys && rm -r tmp; done




This sequence will cause GPG to attempt to list private key details for all file in this directory that end in "private_key.txt".



Output:

[spiano@localhost work]$ ls -1 | grep "private_key.txt" | while read input_file; do mkdir tmp && chmod 700 tmp && gpg --no-default-keyring --homedir tmp --import "$input_file" > /dev/null 2>&1 && gpg --no-default-keyring --homedir tmp --fingerprint --list-secret-keys && rm -r tmp; done

tmp/secring.gpg --------------- sec 4096R/7DD2451C 2019-04-02 Key fingerprint = 7ACA BD43 1C15 1F86 E158 E0DB 0D17 B227 7DD2 451C uid Test Key 1 ssb 4096R/183E79EE 2019-04-02 tmp/secring.gpg --------------- sec 4096R/258E4B1A 2019-04-05 Key fingerprint = 766A 976F 1056 B47E 3062 B002 3F84 F8FE 258E 4B1A uid Test Key 2 ssb 4096R/50C96C60 2019-04-05






I'm going to skip 4) Export key (public, private) because, in my stateless approach, this operation is only used within 1) Create key in order to get the key out of the GPG data store.




Next is 5) Delete key (public, private), which is also no longer useful, because this operation can be accomplished by deleting the relevant key file on the filesystem.

Example key files:

[spiano@localhost work]$ ls -1

test_key_1_private_key.txt
test_key_1_public_key.txt
test_key_2_private_key.txt
test_key_2_public_key.txt





Next: 6) Import key (public, private). This is somewhat useful, in the sense that it is now a preparatory step in these commands:
2) Display key
3) Display details of all keys


It will also be a preparatory step in later commands. It's probably worth explicitly documenting it.




6) Import key


6a) Import public key

Existing command:
gpg --import [file_name]


where [file_name] is the name of the file containing a GPG public key.



New sequence:


mkdir tmp && chmod 700 tmp


gpg --no-default-keyring --homedir tmp --import test_key_2_public_key.txt


rm -r tmp



> /dev/null 2>&1
can be used in the second command to suppress its output.

Example:

gpg --no-default-keyring --homedir tmp --import test_key_2_public_key.txt > /dev/null 2>&1




Output:


[spiano@localhost work]$ mkdir tmp && chmod 700 tmp


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --import test_key_2_public_key.txt

gpg: keyring `tmp/secring.gpg' created gpg: keyring `tmp/pubring.gpg' created gpg: tmp/trustdb.gpg: trustdb created gpg: key 258E4B1A: public key "Test Key 2" imported gpg: Total number processed: 1 gpg: imported: 1 (RSA: 1)


[spiano@localhost work]$ rm -r tmp




Output with suppression:

[spiano@localhost work]$ mkdir tmp && chmod 700 tmp && gpg --no-default-keyring --homedir tmp --import test_key_2_public_key.txt > /dev/null 2>&1 && rm -r tmp






6b) Import private key

Existing command:
gpg --import [file_path]


where [file_name] is the name of the file containing a GPG private key.

Note: Importing a private key causes GPG to construct and store the corresponding public key.




New sequence:


mkdir tmp && chmod 700 tmp


gpg --no-default-keyring --homedir tmp --import test_key_2_private_key.txt


rm -r tmp



> /dev/null 2>&1
can be used in the second command to suppress its output.

Example:

gpg --no-default-keyring --homedir tmp --import test_key_2_private_key.txt > /dev/null 2>&1




Output:


[spiano@localhost work]$ mkdir tmp && chmod 700 tmp


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --import test_key_2_private_key.txt

gpg: keyring `tmp/secring.gpg' created gpg: keyring `tmp/pubring.gpg' created gpg: key 258E4B1A: secret key imported gpg: tmp/trustdb.gpg: trustdb created gpg: key 258E4B1A: public key "Test Key 2" imported gpg: Total number processed: 1 gpg: imported: 1 (RSA: 1) gpg: secret keys read: 1 gpg: secret keys imported: 1


[spiano@localhost work]$ rm -r tmp




Output with suppression:

[spiano@localhost work]$ mkdir tmp && chmod 700 tmp && gpg --no-default-keyring --homedir tmp --import test_key_2_private_key.txt > /dev/null 2>&1 && rm -r tmp





















7) Sign a file using a specific key, producing a detached signature file

Existing command:
gpg --detach-sign --armor --local-user [key] [file_name]


where [key] is any of the following: real name, short key ID, email address, or fingerprint. The fingerprint should not include spaces.

and where [file_name] is the name of the file-to-be-signed.

Notes:
- The detached signature file will have the name
[file_name].asc
.
- The option
--output [output_file_name]
allows you to specify the name of the detached signature file. I have not tested this.


This time, there's no need to specify the local user (i.e. a specific key) for signing. I'm only importing a single key.



New sequence:

A file-to-be-signed should already be prepared.

mkdir tmp && chmod 700 tmp


gpg --no-default-keyring --homedir tmp --import test_key_2_private_key.txt > /dev/null 2>&1


gpg --no-default-keyring --homedir tmp --output file_to_be_signed.txt.asc --armor --detach-sign file_to_be_signed.txt


rm -r tmp





Output:

[spiano@localhost work]$ echo 'world' > hello.txt


[spiano@localhost work]$ mkdir tmp && chmod 700 tmp


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --import test_key_2_private_key.txt > /dev/null 2>&1


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --output hello.txt.asc --armor --detach-sign hello.txt


[spiano@localhost work]$ ls -1

hello.txt
hello.txt.asc
test_key_1_private_key.txt
test_key_1_public_key.txt
test_key_2_private_key.txt
test_key_2_public_key.txt
tmp

[spiano@localhost work]$ cat hello.txt

world

[spiano@localhost work]$ cat hello.txt.asc

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)

iQIcBAABAgAGBQJcp4l8AAoJED+E+P4ljksa2MgQAJzHlFzXoRSLlAN8wf6c7dDb
tyFwJGQbaLKFR0MkXkdlDb4Abju4dMuEHKdX76DHkLJhLe7zYdmGneaaYC1NgqTt
jAAZacq6u/1YeAPOW+mW8ZLiJPHDNQzT7Mb2Vk1RYyxBM7Lyp4kxBjUrkoQdxf4d
HyKbUoIYoLVtj98Jp+fuNXnz5jALE0gx27mLcj4I2ZIHpj1TQLzxPF6txaH93C/x
SYTjeEmQf27LFhpqctI00Cv65plSuxAAxvO4iScjtv1ZgXUd2SJsYnf19GTT5MS7
IxdTysgRrdRuIoVDLOokv+hlzhEaGbgIC2gjTEyztAH9PYOoQa5lkEYA5l9AxvAe
0zHeuR6eIQI3ykZ82itxiupM7wjwq4/Es8K2qoZV+TaFAtyOiMGvEvTHAr6KmZRB
FdHzggnNeYHJ3vSiqhxoy4uMpQf5ySA+Ghq4VZJYxKjXAclvVfSm3B5Ru5wPbByA
iI5xbvDYStg/c/01Jj11J//6Uz6speIcLkCZgRNKb3r4DckS9DI0qWEfvvgZA5c2
U0YnK3xXmDB0KL2aatmWqAh8vcNsMAJyI9suRT/3WLhbEGGrvQgOjUwcdfDDhCII
lDEP9ldfQkcL9Q7qN2NyvtyNw+AD4bNqveISXndJdaW8AkXc0VHa4anOdr7gRt45
MNZE1zPu4NhvGuJzJ6ba
=RwW+
-----END PGP SIGNATURE-----

[spiano@localhost work]$ rm -r tmp















8) Verify the detached signature of a file, checking that the signature was made by a specific key

gpg --verify [file_name].asc [file_name]


where [file_name].asc is the name of the detached signature file and [file_name] is the name of the original file.

Add
--status-fd 1
to the command to also display the fingerprint of the key that made the signature.

Use
grep
to filter the output for a specific fingerprint and
wc -l
to turn this into a binary result (0 or 1). This works only because the fingerprint (without spaces) will be included on only 1 line of the output.

Note: I found that the GPG output is sent to stderr. Redirecting it to stdout using
2>&1
stops it being printed to the terminal when using
grep
+
wc -l
.




Hm. No need to use
grep
this time. I can instead import a single key and see if the signature can be verified.






New sequence:

A file and a corresponding detached signature file must already be present.

mkdir tmp && chmod 700 tmp


gpg --no-default-keyring --homedir tmp --import test_key_2_private_key.txt > /dev/null 2>&1


gpg --no-default-keyring --homedir tmp --status-fd 1 --verify detached_signature_file.txt.asc signed_file.txt


rm -r tmp





Output:

hello.txt and hello.txt.asc are already present.


[spiano@localhost work]$ mkdir tmp && chmod 700 tmp


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --import test_key_2_private_key.txt > /dev/null 2>&1


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --status-fd 1 --verify hello.txt.asc hello.txt

gpg: Signature made Fri 05 Apr 2019 05:59:40 PM BST using RSA key ID 258E4B1A [GNUPG:] SIG_ID kxQhcZnsq5bWZ7OfkhzuV455uFE 2019-04-05 1554483580 [GNUPG:] GOODSIG 3F84F8FE258E4B1A Test Key 2 gpg: Good signature from "Test Key 2" [GNUPG:] VALIDSIG 766A976F1056B47E3062B0023F84F8FE258E4B1A 2019-04-05 1554483580 0 4 0 1 2 00 766A976F1056B47E3062B0023F84F8FE258E4B1A [GNUPG:] TRUST_UNDEFINED gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: 766A 976F 1056 B47E 3062 B002 3F84 F8FE 258E 4B1A


[spiano@localhost work]$ rm -r tmp













What if I want to test all public keys in sequence and see which one signed the file?



Hm. Need to stop if a verification attempt is successful.



Well, let's see what an unsuccessful attempt looks like. I'll use Test Key 1.




hello.txt and hello.txt.asc are already present.


[spiano@localhost work]$ mkdir tmp && chmod 700 tmp


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --import test_key_1_private_key.txt > /dev/null 2>&1


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --status-fd 1 --verify hello.txt.asc hello.txt

gpg: Signature made Fri 05 Apr 2019 05:59:40 PM BST using RSA key ID 258E4B1A [GNUPG:] ERRSIG 3F84F8FE258E4B1A 1 2 00 1554483580 9 [GNUPG:] NO_PUBKEY 3F84F8FE258E4B1A gpg: Can't check signature: public key not found


[spiano@localhost work]$ rm -r tmp






Ok.

Hm.

The string "Good signature from" in the output indicates success.

The string "Can't check signature" indicates failure.





New sequence:

ls -1 | grep "public_key.txt" | while read input_file; do mkdir tmp && chmod 700 tmp && gpg --no-default-keyring --homedir tmp --import "$input_file" > /dev/null 2>&1; gpg --no-default-keyring --homedir tmp --status-fd 1 --verify hello.txt.asc hello.txt 2>&1 | grep -E "Good signature from|Primary key fingerprint"; rm -r tmp; done



Note the use of semicolons around the verification command (it can fail).




Output:

[spiano@localhost work]$ ls -1 | grep "public_key.txt" | while read input_file; do mkdir tmp && chmod 700 tmp && gpg --no-default-keyring --homedir tmp --import "$input_file" > /dev/null 2>&1; gpg --no-default-keyring --homedir tmp --status-fd 1 --verify hello.txt.asc hello.txt 2>&1 | grep -E "Good signature from|Primary key fingerprint"; rm -r tmp; done

gpg: Good signature from "Test Key 2" Primary key fingerprint: 766A 976F 1056 B47E 3062 B002 3F84 F8FE 258E 4B1A




Excellent.




Note: Using the
gpg --list-packets detached_signature_file.txt.asc
, the long key ID of the signing key can be viewed.




[spiano@localhost work]$ gpg --list-packets hello.txt.asc

:signature packet: algo 1, keyid 3F84F8FE258E4B1A version 4, created 1554483580, md5len 0, sigclass 0x00 digest algo 2, begin of digest d8 c8 hashed subpkt 2 len 4 (sig created 2019-04-05) subpkt 16 len 8 (issuer key ID 3F84F8FE258E4B1A) data: [4096 bits]



Comparing
3F84F8FE258E4B1A

with
gpg: Good signature from "Test Key 2"
Primary key fingerprint: 766A 976F 1056 B47E 3062 B002 3F84 F8FE 258E 4B1A

I can see that the expected long key ID is present at the end of the fingerprint.


Update:
- The long key ID is displayed in the output of
gpg --list-packets signed_file.txt.asc
. Using a lookup table that maps long key IDs to keys, the correct key could be chosen for verifying the signature, instead of attempting to use every key in a loop.













9) Encrypt a message file to a specific public key

gpg --encrypt --recipient [key] --armor [file_name]


where [key] is any of the following: real name, short key ID, email address, or fingerprint. The fingerprint should not include spaces.

and where [file_name] is the name of the file-to-be-encrypted.

Notes:
- The encrypted file will be called
[file_name].asc
.
- The option
--output [output_file_name]
allows you to specify the name of the encrypted file. I have not tested this.






New sequence:

A file-to-be-encrypted should already be prepared.

mkdir tmp && chmod 700 tmp


gpg --no-default-keyring --homedir tmp --import test_key_2_public_key.txt > /dev/null 2>&1


gpg --no-default-keyring --homedir tmp --output encrypted_file.asc --armor --recipient "Test Key 2" --encrypt file_to_be_encrypted.txt


rm -r tmp




Some experimentation showed me that the
--recipient [key]
option is required.



Output:

[spiano@localhost work]$ ls -1

hello.txt
hello.txt.asc
test_key_1_private_key.txt
test_key_1_public_key.txt
test_key_2_private_key.txt
test_key_2_public_key.txt

[spiano@localhost work]$ cat hello.txt

world

[spiano@localhost work]$ mkdir tmp && chmod 700 tmp


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --import test_key_2_public_key.txt > /dev/null 2>&1


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --output hello.asc --armor --recipient "Test Key 2" --encrypt hello.txt

gpg: 50C96C60: There is no assurance this key belongs to the named user pub 4096R/50C96C60 2019-04-05 Test Key 2 Primary key fingerprint: 766A 976F 1056 B47E 3062 B002 3F84 F8FE 258E 4B1A Subkey fingerprint: 45F1 A0BB E6CC 9CD7 56FF F01F 7CBB 1E97 50C9 6C60 It is NOT certain that the key belongs to the person named in the user ID. If you *really* know what you are doing, you may answer the next question with yes. Use this key anyway? (y/N) y


[spiano@localhost work]$ rm -r tmp


[spiano@localhost work]$ rm hello.asc




Hm. Interesting. This is the first time that I've ever seen the subkey's entire fingerprint.


How do I automatically answer "y" (yes) to the interactive prompt?

The man page says that I can use
--yes
.


Hm. I was unable to get
--yes
to work. I tried it in several positions within the command.



Ah well. A solution probably involves either patching GPG or using
expect
.

















10) Decrypt an encrypted message file, checking that the decryption was performed using a specific private key.

gpg --decrypt --output [file_name] [file_name].asc


where [file_name] is the name of the decrypted file (to be created by this command) and [file_name].asc is the name of the detached signature file.

Notes:
- A GPG key contains a primary keypair and a subkeypair. The primary keypair is used for signing. The subkeypair is used for encryption. Other people's encrypted messages are encrypted to the public subkey. The private subkey is used to decrypt messages.
- You will be able to see that the short key ID in the decryption output is not that of the main public key. This short key ID will be visible in the output of
gpg --list-keys
as the short key ID of the subkey of the main public key.



Decryption requires the private key, so that's what we'll import.



New sequence:

The encrypted file should already be present.

mkdir tmp && chmod 700 tmp


gpg --no-default-keyring --homedir tmp --import test_key_2_private_key.txt > /dev/null 2>&1


gpg --no-default-keyring --homedir tmp --keyid-format long --output decrypted_file.txt --decrypt encrypted_file.asc


rm -r tmp






Output:

[spiano@localhost work]$ ls -1

hello.asc
hello.txt
hello.txt.asc
test_key_1_private_key.txt
test_key_1_public_key.txt
test_key_2_private_key.txt
test_key_2_public_key.txt

[spiano@localhost work]$ mv hello.txt hello.txt.bak


[spiano@localhost work]$ mkdir tmp && chmod 700 tmp


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --import test_key_2_private_key.txt > /dev/null 2>&1


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --keyid-format long --output hello.txt --decrypt hello.asc

gpg: encrypted with 4096-bit RSA key, ID 7CBB1E9750C96C60, created 2019-04-05 "Test Key 2"


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --keyid-format long --fingerprint --list-keys

tmp/pubring.gpg --------------- pub 4096R/3F84F8FE258E4B1A 2019-04-05 Key fingerprint = 766A 976F 1056 B47E 3062 B002 3F84 F8FE 258E 4B1A uid Test Key 2 sub 4096R/7CBB1E9750C96C60 2019-04-05


[spiano@localhost work]$ rm -r tmp


[spiano@localhost work]$ ls -1

hello.asc
hello.txt
hello.txt.asc
hello.txt.bak
test_key_1_private_key.txt
test_key_1_public_key.txt
test_key_2_private_key.txt
test_key_2_public_key.txt

[spiano@localhost work]$ cat hello.txt

world




Note that the long key ID that appears in the decryption output is the same as the subkey's long key ID in the key details output.





What does an unsuccessful decryption attempt look like?

Let's try with Test Key 1.





[spiano@localhost work]$ ls -1

hello.asc
hello.txt
hello.txt.asc
hello.txt.bak
test_key_1_private_key.txt
test_key_1_public_key.txt
test_key_2_private_key.txt
test_key_2_public_key.txt

[spiano@localhost work]$ rm hello.txt


[spiano@localhost work]$ mkdir tmp && chmod 700 tmp


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --import test_key_1_private_key.txt > /dev/null 2>&1


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --keyid-format long --output hello.txt --decrypt hello.asc

gpg: encrypted with RSA key, ID 7CBB1E9750C96C60 gpg: decryption failed: secret key not available


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --keyid-format long --fingerprint --list-keys

tmp/pubring.gpg --------------- pub 4096R/0D17B2277DD2451C 2019-04-02 Key fingerprint = 7ACA BD43 1C15 1F86 E158 E0DB 0D17 B227 7DD2 451C uid Test Key 1 sub 4096R/3EB540FD183E79EE 2019-04-02


[spiano@localhost work]$ rm -r tmp


[spiano@localhost work]$ ls -1

hello.asc
hello.txt.asc
hello.txt.bak
test_key_1_private_key.txt
test_key_1_public_key.txt
test_key_2_private_key.txt
test_key_2_public_key.txt





Ok.


Let's see the output of
gpg --list-packets encrypted_file.asc
.



[spiano@localhost work]$ gpg --list-packets hello.asc

:pubkey enc packet: version 3, algo 1, keyid 7CBB1E9750C96C60 data: [4095 bits] :encrypted data packet: length: 74 mdc_method: 2 gpg: encrypted with RSA key, ID 50C96C60 gpg: decryption failed: secret key not available




The long key ID is displayed. This means that, using a lookup table, the long key ID could be used to check which key to use for decryption.




What if I prefer to just try all keys and see which one works?




Here, the
--yes
option allows GPG to overwrite the decrypted file if it already exists.



New sequence:

ls -1 | grep "private_key.txt" | while read input_file; do mkdir tmp && chmod 700 tmp && gpg --no-default-keyring --homedir tmp --import "$input_file" > /dev/null 2>&1; OUTPUT="$(gpg --yes --no-default-keyring --homedir tmp --keyid-format long --output hello.txt --decrypt hello.asc 2>&1)"; echo $OUTPUT | grep -v "decryption failed: secret key not available"; rm -r tmp; done




Note the use of semicolons around the decryption command (it can fail).

The OUTPUT variable doesn't appear to have preserved the newlines in the output of the decryption command.




Output:

[spiano@localhost work]$ ls -1 | grep "private_key.txt" | while read input_file; do mkdir tmp && chmod 700 tmp && gpg --no-default-keyring --homedir tmp --import "$input_file" > /dev/null 2>&1; OUTPUT="$(gpg --yes --no-default-keyring --homedir tmp --keyid-format long --output hello.txt --decrypt hello.asc 2>&1)"; echo $OUTPUT | grep -v "decryption failed: secret key not available"; rm -r tmp; done

gpg: encrypted with 4096-bit RSA key, ID 7CBB1E9750C96C60, created 2019-04-05 "Test Key 2"




Good.







Hm.



I'll go over the first few commands again, and see if they work without the
--keyring pubring.gpg
option.


Reading back over the log, I see that I just need to do 2a) Display public key details.






2) Display key


2a) Display public key details

Existing command:
gpg --list-keys [key]


where [key] is any of the following: real name, short key ID, email address, or fingerprint. The fingerprint should not include spaces.

Add
--fingerprint
to the command to also display the key fingerprint.



New sequence:

mkdir tmp && chmod 700 tmp


gpg --no-default-keyring --homedir tmp --import test_key_2_public_key.txt > /dev/null 2>&1


gpg --no-default-keyring --homedir tmp --fingerprint --list-keys "Test Key 2"


rm -r tmp




Output:


[spiano@localhost work]$ mkdir tmp && chmod 700 tmp


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --import test_key_2_public_key.txt > /dev/null 2>&1


[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp --keyid-format long --fingerprint --list-keys "Test Key 2"

pub 4096R/3F84F8FE258E4B1A 2019-04-05 Key fingerprint = 766A 976F 1056 B47E 3062 B002 3F84 F8FE 258E 4B1A uid Test Key 2 sub 4096R/7CBB1E9750C96C60 2019-04-05


[spiano@localhost work]$ rm -r tmp




Good.






That's the end of this project.












[start of notes]



If you don't set permissions to 700 on the temporary gpg home directory, you will probably see this warning in the output from importing a key:
gpg: WARNING: unsafe permissions on homedir `tmp'



Approach for using GPG statelessly:
- store all private keys as text files in a directory.
- store all public keys as text files in a second directory.
- maintain a text file that stores records of key details: key file name, real name, fingerprint, long key ID, corresponding public / private key, long key ID of the public subkey.
- to turn the real name into a text file name, decapitalise and replace spaces with underscores. Example: "Test Key 2" becomes test_key_2_private_key.txt.


When creating a key, the email address can be an empty string.


gpg --list-packets [filename]
can be used to find the long key ID of the relevant key from a detached signature file and from an encrypted file. If the file is signed, the relevant key will be the public key. If the file is encrypted, the relevant key will be the public subkey. This long key ID can be looked up in the key details text file, in order to select the correct private key for signature verification or for decryption. Alternative: Loop over all keys in storage and see if one produces a "success" message for signature verification or for decryption.

Note:
- A GPG key contains a primary keypair and a subkeypair. The primary keypair is used for signing. The subkeypair is used for encryption. Other people's encrypted messages are encrypted to the public subkey. The private subkey is used to decrypt messages.


expect
could be used for automating responses to interactive prompts.


The short key ID, the long key ID, and the fingerprint are only derived from the public key. When GPG displays details concerning the private key, such as short key ID, long key ID, and fingerprint, these are the same as the details for the corresponding public key.


The encryption command displayed the entire fingerprint of the public subkey.


Changes from the original text:
- I have not always preserved the format of any computer output (e.g. from running bash commands). Examples: Setting input lines in bold text, adding/removing newlines in order to make a sequence of commands easier to read, using hyphens for lists and sublists instead of indentation, breaking wide tables into consecutive sections.


[end of notes]