Summary
GPG is not designed to be used statelessly. It is built around loading keys into its home directory and managing trust ratings and identity signatures.
In this project, I construct a temporary home directory for each operation, into which only a single key is imported, so that operations can be performed completely independently i.e. in a stateless manner. Keys are stored in text files. With some careful automation, operations such as "display details of all public keys", "verify this signature", and "decrypt this encrypted file" become quite feasible.
In an automated script, it would be most secure to specify a key by its fingerprint, look up the corresponding keyfile, and use this key to perform the required stateless operation. In this way, we avoid the problem of trying to get the full fingerprint from GPG's output (the fingerprint is not always present), by ensuring that one and only one key is available to GPG at any one time.
Contents
- Summary
- List Of Operations
- Notes
- GPG 1.4.10 Stateless Operations
- GPG 1.4.10 Stateless Operations With Example Output
List Of Operations
1) Create keypair and store it in keyfiles
2) Delete key
3) Display key
4) Display key details
5) Display details of all keys
6) Import key
7) Sign a file using a specific private key, producing a detached signature file
8) Verify the detached signature of a file, checking that the signature was made by a specific public 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
Notes
GPG is not designed to be used statelessly. However, a different home directory can be specified in a GPG command, which means that a temporary home directory can be constructed and used for an operation. By only importing a single key into the temporary home directory, we can be sure that the operations succeed or fail based only on the use of this single key.
In this project, keys are stored in text files. I use the term 'keyfile' to refer to a text file that contains a key (whether private or public).
This project draws heavily on prior work in the project Using GPG 1.4.10 statelessly.
In public-key cryptography, a 'key' is really a keypair - a private key and a public key.
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.
These commands emphasise the use of real names, fingerprints, and ASCII armor. A fingerprint is the most unique (least forgeable) way to refer to a key. 'Real name' is just a convenient text value - a key can claim that its real name is X (e.g. "John Smith"), but the actual primary identity is the key. ASCII armor is used for legibility.
A key fingerprint is derived in some way from the hash of a public key. It is a shorthand way to reference the key in a manner that has a good uniqueness guarantee but is shorter than the entire key. User-assigned 'real names' can always be duplicated by a third party, who might wish to create a counterfeit key. A short key ID (the last 8 characters of the fingerprint) is insecure because it is feasible for a third party to attempt to generate another key with the same short key ID. The long key ID (the last 16 characters of the fingerprint) is somewhat harder to forge and is therefore more secure. The real name may be used for convenience and human-readable archival, but the fingerprint should be used within automated scripts. When used as an argument for GPG, a fingerprint must not include spaces.
I initially thought that the private key had its own fingerprint, long key ID, and short key ID. This is not the case. When you display these details for a private key, they are the same as the corresponding details for the public key.
An improved 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.
- back up keys
- maintain a text file that stores records of key details: public keyfile name, private keyfile name, real name, fingerprint, long key ID, long key ID of the public subkey.
- perform cryptographic operations in a dedicated work directory
In this project, everything happens in a single directory, and no record is kept of key details, but the approach described here would be the next logical step.
You can derive keyfile names from the real name by:
- decapitalising any capital letters
- removing punctuation
- replacing spaces with underscores
- adding the suffix "_private_key.txt" for the private keyfile.
- adding the suffix "_public_key.txt" for public keyfile.
Example: For the name "Test Key 1", I used the following keyfile names:
- test_key_1_private_key.txt
- test_key_1_public_key.txt
The command suffix
> /dev/null 2>&1
is used to suppress output. In operation 9) Encrypt a message file to a specific public key, the
--encrypt
command displays the entire fingerprint of the public subkey. This is the only way (that I am aware of) that this can be viewed. The command sequences in this project set permissions to 700 on the temporary gpg home directory in order to avoid this warning in the output when importing a key:
gpg: WARNING: unsafe permissions on homedir `tmp_home'
I have not always preserved the format of any computer output (i.e. 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.
Gpg 1.4.10 Stateless Operations
1) Create keypair and store it in keyfiles
Choose a real name for the key. Examples "John Smith", "Edgecase Corporation", "Server 456 - Clive", "Test Key 1". Try to choose a name that is reasonably human-readable. This name will be used in other commands in this project to specify a particular key.
Derive the keyfile names from the real name by:
- decapitalising any capital letters
- removing punctuation
- replacing spaces with underscores
- adding the suffix "_private_key.txt" for the private keyfile.
- adding the suffix "_public_key.txt" for public keyfile.
Example: For the name "Test Key 1", I will use the following keyfile names:
- test_key_1_private_key.txt
- test_key_1_public_key.txt
Command sequence:
mkdir tmp_home && chmod 700 tmp_home
gpg --no-default-keyring --homedir tmp_home --gen-key
Interactive prompts 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 says that it will create a passphrase anyway if an empty one is specified - but I don't think that it actually does]
"" signifies empty string i.e. no input. Press Enter after each prompt to proceed to the next one.
gpg --no-default-keyring --homedir tmp_home --armor --export-secret-keys "Test Key 1" > test_key_1_private_key.txt
gpg --no-default-keyring --homedir tmp_home --armor --export "Test Key 1" > test_key_1_public_key.txt
rm -r tmp_home
2) Delete key
To delete a key, delete the keyfiles.
Warning: If this is one of your own keys, and the public key has been sent to anyone else, or published somewhere, pause for a minute. You should probably archive it instead of deleting it.
Commands:
rm test_key_1_private_key.txt
rm test_key_1_public_key.txt
3) Display key
To display a key, display the keyfile.
Commands:
cat test_key_1_private_key.txt
cat test_key_1_public_key.txt
4) Display key details
Command sequence for displaying the details of a private key:
mkdir tmp_home && chmod 700 tmp_home
gpg --no-default-keyring --homedir tmp_home --import test_key_1_private_key.txt > /dev/null 2>&1
gpg --no-default-keyring --homedir tmp_home --keyid-format long --fingerprint --list-secret-keys
rm -r tmp_home
Command sequence for displaying the details of a public key:
mkdir tmp_home && chmod 700 tmp_home
gpg --no-default-keyring --homedir tmp_home --import test_key_1_public_key.txt > /dev/null 2>&1
gpg --no-default-keyring --homedir tmp_home --keyid-format long --fingerprint --list-keys
rm -r tmp_home
We can use the
--list-keys
and
--list-secret-keys
commands without specifying a key because there is only one key in the temporary GPG home directory. 5) Display details of all keys
To display the details of all the keys, repeat the steps in 4) Display key details for each key.
This can be done manually, where you change the keyfile name in each use of the command sequence. It can also be automated, using some code.
Here is an example of automating this process:
ls -1 | grep "private_key.txt" | while read input_file; do mkdir tmp_home && chmod 700 tmp_home && gpg --no-default-keyring --homedir tmp_home --import "$input_file" > /dev/null 2>&1 && gpg --no-default-keyring --homedir tmp_home --keyid-format long --fingerprint --list-secret-keys; rm -r tmp_home; done
This Bash command sequence will use GPG to display the key details for all keyfiles in this directory that end in "private_key.txt".
Here is the same example, applied to public keys:
ls -1 | grep "public_key.txt" | while read input_file; do mkdir tmp_home && chmod 700 tmp_home && gpg --no-default-keyring --homedir tmp_home --import "$input_file" > /dev/null 2>&1 && gpg --no-default-keyring --homedir tmp_home --keyid-format long --fingerprint --list-keys; rm -r tmp_home; done
This Bash command sequence will use GPG to display the key details for all keyfiles in this directory that end in "public_key.txt".
6) Import key
In this project's stateless approach, this GPG command is not a standalone operation. Instead, it is used as a component within various operations. I've chosen to explicitly document it as a separate item.
Note: Importing a private key causes GPG to construct and store the corresponding public key.
Command sequence:
mkdir tmp_home && chmod 700 tmp_home
gpg --no-default-keyring --homedir tmp_home --import test_key_1_private_key.txt
rm -r tmp_home
> /dev/null 2>&1
can be used in the second command to suppress its output.Example:
gpg --no-default-keyring --homedir tmp_home --import test_key_1_private_key.txt > /dev/null 2>&1
The command does not vary when importing a public key.
Example:
gpg --no-default-keyring --homedir tmp_home --import test_key_1_public_key.txt > /dev/null 2>&1
7) Sign a file using a specific private key, producing a detached signature file
A file-to-be-signed must already be present.
Command sequence:
mkdir tmp_home && chmod 700 tmp_home
gpg --no-default-keyring --homedir tmp_home --import test_key_1_private_key.txt > /dev/null 2>&1
gpg --no-default-keyring --homedir tmp_home --output detached_signature_file.txt.asc --armor --detach-sign file_to_be_signed.txt
rm -r tmp_home
8) Verify the detached signature of a file, checking that the signature was made by a specific public key
A file and a corresponding detached signature file must already be present.
The command
gpg --list-packets detached_signature_file.txt.asc
can be used to view the long key ID of the signing key. Example:
[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]
The long key ID is 3F84F8FE258E4B1A.
Now use operation 5) Display details of all keys to produce text that can be searched for this long key ID. Alternatively, if you maintain a text file that records keyfile names, long key IDs, etc, you can look up the long key ID in there.
Now choose the public keyfile that corresponds to this long key ID and run the command sequence.
Command sequence:
mkdir tmp_home && chmod 700 tmp_home
gpg --no-default-keyring --homedir tmp_home --import test_key_1_public_key.txt > /dev/null 2>&1
gpg --no-default-keyring --homedir tmp_home --status-fd 1 --verify detached_signature_file.txt.asc file.txt
rm -r tmp_home
The important output line will be:
gpg: Good signature from "Test Key 1"
This shows that GPG considers the digital signature to be mathematically valid. The real name shown in the output line will vary depending on the key that made the signature.
There is also a simpler but slower approach, which is to test all the available public keys against the detached signature file and print output only from a successful verification. This can be done manually, where you change the keyfile name in each use of the command sequence. It can also be automated, using some code.
Here is an example of automating this process:
hello.txt (the file) and hello.txt.asc (the detached signature file) are already present.
ls -1 | grep "public_key.txt" | while read input_file; do mkdir tmp_home && chmod 700 tmp_home && gpg --no-default-keyring --homedir tmp_home --import "$input_file" > /dev/null 2>&1; gpg --no-default-keyring --homedir tmp_home --status-fd 1 --verify hello.txt.asc hello.txt 2>&1 | grep -E "Good signature from|Primary key fingerprint"; rm -r tmp_home; done
This Bash command sequence will use GPG to attempt to verify the detached signature using every keyfile in this directory that ends in "public_key.txt". It will then print output lines that contain either "Good signature from" or "Primary key fingerprint".
9) Encrypt a message file to a specific public key
A file-to-be-encrypted must already be present.
The
--recipient
option needs a value, which can be the real name or the fingerprint. You can use the real name when performing this operation manually, but you should use the fingerprint when writing a script to automate this operation. The
--encrypt
command will produce an interactive prompt, because (I think) no identity signature for this key is present in the GPG temporary home directory. To answer the prompt, press 'y' and then Enter. Note: The
--yes
option (which answers 'y' to most prompts) does not work for this particular prompt.
mkdir tmp_home && chmod 700 tmp_home
gpg --no-default-keyring --homedir tmp_home --import test_key_2_public_key.txt > /dev/null 2>&1
gpg --no-default-keyring --homedir tmp_home --keyid-format long --output encrypted_file.asc --armor --recipient "Test Key 2" --encrypt file_to_be_encrypted.txt
rm -r tmp_home
10) Decrypt an encrypted message file, checking that the decryption was performed using a specific private key
The encrypted file must already be present.
The command
gpg --list-packets encrypted_file.asc
can be used to view the long key ID of the public subkey to which the file was encrypted. I'll refer to this public subkey as the "destination key". Example:
[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 of the destination key is 7CBB1E9750C96C60.
Now use operation 5) Display details of all keys to produce text that can be searched for this long key ID. Alternatively, if you maintain a text file that records keyfile names, long key IDs, long key IDs of public subkeys, etc, you can look up the long key ID in there.
Now choose the private keyfile that corresponds to the long key ID of this destination key and run the command sequence.
Command sequence:
mkdir tmp_home && chmod 700 tmp_home
gpg --no-default-keyring --homedir tmp_home --import test_key_1_private_key.txt > /dev/null 2>&1
gpg --no-default-keyring --homedir tmp_home --status-fd 1 --keyid-format long --output decrypted_file.txt --decrypt encrypted_file.asc
rm -r tmp_home
The output lines will be:
[GNUPG:] ENC_TO 5CE721E1669C4CF2 1 0
[GNUPG:] GOOD_PASSPHRASE
gpg: encrypted with 4096-bit RSA key, ID 5CE721E1669C4CF2, created 2019-04-07
"Test Key 1"
[GNUPG:] BEGIN_DECRYPTION
[GNUPG:] PLAINTEXT 62 1554650007 hello.txt
[GNUPG:] PLAINTEXT_LENGTH 6
[GNUPG:] DECRYPTION_OKAY
[GNUPG:] GOODMDC
[GNUPG:] END_DECRYPTION
The output line
[GNUPG:] DECRYPTION_OKAY
will show that GPG considers the decryption to have been successfully performed. The real name shown in the output will vary depending on the destination key.
Note: The output also contains the real name ("Test Key 1") of the keypair and the long key ID of the destination key (5CE721E1669C4CF2).
There is also a simpler but slower approach, which is to test all the available private keys against the encrypted file and print output only from a successful decryption. This can be done manually, where you change the keyfile name in each use of the command sequence. It can also be automated, using some code.
Here is an example of automating this process:
hello.asc (the encrypted file) is already present.
ls -1 | grep "private_key.txt" | while read input_file; do mkdir tmp_home && chmod 700 tmp_home && gpg --no-default-keyring --homedir tmp_home --import "$input_file" > /dev/null 2>&1; OUTPUT="$(gpg --no-default-keyring --homedir tmp_home --status-fd 1 --keyid-format long --output hello_decrypted.txt --decrypt hello.asc 2>&1)"; echo $OUTPUT | grep "DECRYPTION_OKAY"; rm -r tmp_home; done
This Bash command sequence will use GPG to attempt to decrypt the encrypted file using every keyfile in this directory that ends in "private_key.txt". It will then print output lines that contain the string "DECRYPTION_OKAY".
The output will be:
[GNUPG:] ENC_TO 5CE721E1669C4CF2 1 0 [GNUPG:] GOOD_PASSPHRASE gpg: encrypted with 4096-bit RSA key, ID 5CE721E1669C4CF2, created 2019-04-07 "Test Key 1" [GNUPG:] BEGIN_DECRYPTION [GNUPG:] PLAINTEXT 62 1554650007 hello.txt [GNUPG:] PLAINTEXT_LENGTH 6 [GNUPG:] DECRYPTION_OKAY [GNUPG:] GOODMDC [GNUPG:] END_DECRYPTION
The OUTPUT variable doesn't preserve the newlines in the output of the decryption command, so the output is a single line.
Gpg 1.4.10 Stateless Operations With Example Output
In this section, I'm going to run the commands from the GPG 1.4.10 Stateless Operations section and record the output.
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, Bash 4.2.46(2), GPG 1.4.10, Gnome 3.28.2.
I installed GPG 1.4.10 on CentOS 7.6 on Shovel in a previous project: Installing GPG 1.4.10 on CentOS 7.6
1) Create keypair and store it in keyfiles
Choose a real name for the key. Examples "John Smith", "Edgecase Corporation", "Server 456 - Clive", "Test Key 1". Try to choose a name that is reasonably human-readable. This name will be used in other commands in this project to specify a particular key.
Derive the keyfile names from the real name by:
- decapitalising any capital letters
- removing punctuation
- replacing spaces with underscores
- adding the suffix "_private_key.txt" for the private keyfile.
- adding the suffix "_public_key.txt" for public keyfile.
Example: For the name "Test Key 1", I will use the following keyfile names:
- test_key_1_private_key.txt
- test_key_1_public_key.txt
Command sequence:
mkdir tmp_home && chmod 700 tmp_home
gpg --no-default-keyring --homedir tmp_home --gen-key
Interactive prompts 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 says that it will create a passphrase anyway if an empty one is specified - but I don't think that it actually does]
"" signifies empty string i.e. no input. Press Enter after each prompt to proceed to the next one.
gpg --no-default-keyring --homedir tmp_home --armor --export-secret-keys "Test Key 1" > test_key_1_private_key.txt
gpg --no-default-keyring --homedir tmp_home --armor --export "Test Key 1" > test_key_1_public_key.txt
rm -r tmp_home
Worked example:
[spiano@localhost work]$ ls -1
[spiano@localhost work]$ mkdir tmp_home && chmod 700 tmp_home
[spiano@localhost work]$ ls -1
tmp_home
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_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_home/secring.gpg' created
gpg: keyring `tmp_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_home/trustdb.gpg: trustdb created
gpg: key 9DCC50A2 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/9DCC50A2 2019-04-07
Key fingerprint = 2AF1 4D88 6911 A54A D957 3494 9787 D257 9DCC 50A2
uid Test Key 1
sub 4096R/669C4CF2 2019-04-07
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --armor --export-secret-keys "Test Key 1" > test_key_1_private_key.txt
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --armor --export "Test Key 1" > test_key_1_public_key.txt
[spiano@localhost work]$ ls -1
test_key_1_private_key.txt
test_key_1_public_key.txt
tmp_home
[spiano@localhost work]$ rm -r tmp_home
[spiano@localhost work]$ ls -1
test_key_1_private_key.txt
test_key_1_public_key.txt
2) Delete key
To delete a key, delete the keyfiles.
Warning: If this is one of your own keys, and the public key has been sent to anyone else, or published somewhere, pause for a minute. You should probably archive it instead of deleting it.
Commands:
rm test_key_1_private_key.txt
rm test_key_1_public_key.txt
Worked example:
First, archive the keys.
[spiano@localhost work]$ ls -1
test_key_1_private_key.txt
test_key_1_public_key.txt
[spiano@localhost work]$ mkdir archive
[spiano@localhost work]$ cp *.txt archive/.
[spiano@localhost work]$ ls -1 archive
test_key_1_private_key.txt
test_key_1_public_key.txt
[spiano@localhost work]$ ls -1
archive
test_key_1_private_key.txt
test_key_1_public_key.txt
Next, I'll demonstrate deleting the keys.
[spiano@localhost work]$ rm test_key_1_private_key.txt
[spiano@localhost work]$ rm test_key_1_public_key.txt
[spiano@localhost work]$ ls -1
archive
Next, I'll restore the keys from the archive.
[spiano@localhost work]$ ls -1 archive
test_key_1_private_key.txt
test_key_1_public_key.txt
[spiano@localhost work]$ cp archive/test_key_1_private_key.txt archive/test_key_1_public_key.txt ./
[spiano@localhost work]$ ls -1
archive
test_key_1_private_key.txt
test_key_1_public_key.txt
Finally, I'll delete the archive.
[spiano@localhost work]$ rm -r archive
[spiano@localhost work]$ ls -1
test_key_1_private_key.txt
test_key_1_public_key.txt
3) Display key
To display a key, display the keyfile.
Commands:
cat test_key_1_private_key.txt
cat test_key_1_public_key.txt
Worked example:
[spiano@localhost work]$ ls -1
test_key_1_private_key.txt
test_key_1_public_key.txt
[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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
WqybfU2fDv/simYfFsg=
=S1Fb
-----END PGP PRIVATE KEY BLOCK-----
[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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
al6muBvK+HSr8Fqsm31Nnw7/7IpmHxbI
=4uC0
-----END PGP PUBLIC KEY BLOCK-----
4) Display key details
Command sequence for displaying the details of a private key:
mkdir tmp_home && chmod 700 tmp_home
gpg --no-default-keyring --homedir tmp_home --import test_key_1_private_key.txt > /dev/null 2>&1
gpg --no-default-keyring --homedir tmp_home --keyid-format long --fingerprint --list-secret-keys
rm -r tmp_home
Command sequence for displaying the details of a public key:
mkdir tmp_home && chmod 700 tmp_home
gpg --no-default-keyring --homedir tmp_home --import test_key_1_public_key.txt > /dev/null 2>&1
gpg --no-default-keyring --homedir tmp_home --keyid-format long --fingerprint --list-keys
rm -r tmp_home
We can use the
--list-keys
and
--list-secret-keys
commands without specifying a key because there is only one key in the temporary GPG home directory. Worked example:
a) Display the details of a private key
[spiano@localhost work]$ ls -1
test_key_1_private_key.txt
test_key_1_public_key.txt
[spiano@localhost work]$ mkdir tmp_home && chmod 700 tmp_home
[spiano@localhost work]$ ls -1
test_key_1_private_key.txt
test_key_1_public_key.txt
tmp_home
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --import test_key_1_private_key.txt > /dev/null 2>&1
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --keyid-format long --fingerprint --list-secret-keys
tmp_home/secring.gpg
--------------------
sec 4096R/9787D2579DCC50A2 2019-04-07
Key fingerprint = 2AF1 4D88 6911 A54A D957 3494 9787 D257 9DCC 50A2
uid Test Key 1
ssb 4096R/5CE721E1669C4CF2 2019-04-07
[spiano@localhost work]$ rm -r tmp_home
[spiano@localhost work]$ ls -1
test_key_1_private_key.txt
test_key_1_public_key.txt
The 16-character hex string in the 3rd line is the long key ID:
9787D2579DCC50A2
It is the same as the last 16 characters of the key fingerprint.
The 16-character hex string in the 6th line is the long key ID of the public subkey:
5CE721E1669C4CF2
b) Display the details of a public key
[spiano@localhost work]$ ls -1
test_key_1_private_key.txt
test_key_1_public_key.txt
[spiano@localhost work]$ mkdir tmp_home && chmod 700 tmp_home
[spiano@localhost work]$ ls -1
test_key_1_private_key.txt
test_key_1_public_key.txt
tmp_home
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --import test_key_1_public_key.txt > /dev/null 2>&1
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --keyid-format long --fingerprint --list-keys
tmp_home/pubring.gpg
--------------------
pub 4096R/9787D2579DCC50A2 2019-04-07
Key fingerprint = 2AF1 4D88 6911 A54A D957 3494 9787 D257 9DCC 50A2
uid Test Key 1
sub 4096R/5CE721E1669C4CF2 2019-04-07
[spiano@localhost work]$ rm -r tmp_home
[spiano@localhost work]$ ls -1
test_key_1_private_key.txt
test_key_1_public_key.txt
The 16-character hex string in the 3rd line is the long key ID:
9787D2579DCC50A2
It is the same as the last 16 characters of the key fingerprint.
The 16-character hex string in the 6th line is the long key ID of the public subkey:
5CE721E1669C4CF2
5) Display details of all keys
To display the details of all the keys, repeat the steps in 4) Display key details for each key.
This can be done manually, where you change the keyfile name in each use of the command sequence. It can also be automated, using some code.
Here is an example of automating this process:
ls -1 | grep "private_key.txt" | while read input_file; do mkdir tmp_home && chmod 700 tmp_home && gpg --no-default-keyring --homedir tmp_home --import "$input_file" > /dev/null 2>&1 && gpg --no-default-keyring --homedir tmp_home --keyid-format long --fingerprint --list-secret-keys; rm -r tmp_home; done
This Bash command sequence will use GPG to display the key details for all keyfiles in this directory that end in "private_key.txt".
Here is the same example, applied to public keys:
ls -1 | grep "public_key.txt" | while read input_file; do mkdir tmp_home && chmod 700 tmp_home && gpg --no-default-keyring --homedir tmp_home --import "$input_file" > /dev/null 2>&1 && gpg --no-default-keyring --homedir tmp_home --keyid-format long --fingerprint --list-keys; rm -r tmp_home; done
This Bash command sequence will use GPG to display the key details for all keyfiles in this directory that end in "public_key.txt".
Worked example:
First, create a second keypair named "Test Key 2". This step is not shown here.
a) Display details of all private keys
[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]$ ls -1 | grep "private_key.txt" | while read input_file; do mkdir tmp_home && chmod 700 tmp_home && gpg --no-default-keyring --homedir tmp_home --import "$input_file" > /dev/null 2>&1 && gpg --no-default-keyring --homedir tmp_home --keyid-format long --fingerprint --list-secret-keys; rm -r tmp_home; done
tmp_home/secring.gpg
--------------------
sec 4096R/9787D2579DCC50A2 2019-04-07
Key fingerprint = 2AF1 4D88 6911 A54A D957 3494 9787 D257 9DCC 50A2
uid Test Key 1
ssb 4096R/5CE721E1669C4CF2 2019-04-07
tmp_home/secring.gpg
--------------------
sec 4096R/0661DB47BAB31156 2019-04-07
Key fingerprint = AAEB 1B64 81CE 89E0 D8C5 FBBC 0661 DB47 BAB3 1156
uid Test Key 2
ssb 4096R/73ECB41DA1D93BF7 2019-04-07
b) Display details of all public keys
[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]$ ls -1 | grep "public_key.txt" | while read input_file; do mkdir tmp_home && chmod 700 tmp_home && gpg --no-default-keyring --homedir tmp_home --import "$input_file" > /dev/null 2>&1 && gpg --no-default-keyring --homedir tmp_home --keyid-format long --fingerprint --list-keys; rm -r tmp_home; done
tmp_home/pubring.gpg
--------------------
pub 4096R/9787D2579DCC50A2 2019-04-07
Key fingerprint = 2AF1 4D88 6911 A54A D957 3494 9787 D257 9DCC 50A2
uid Test Key 1
sub 4096R/5CE721E1669C4CF2 2019-04-07
tmp_home/pubring.gpg
--------------------
pub 4096R/0661DB47BAB31156 2019-04-07
Key fingerprint = AAEB 1B64 81CE 89E0 D8C5 FBBC 0661 DB47 BAB3 1156
uid Test Key 2
sub 4096R/73ECB41DA1D93BF7 2019-04-07
6) Import key
In the stateless approach in this project, this GPG command is not a standalone operation. Instead, it is used as a component within various operations. It is worth explicitly documenting as a separate item.
Note: Importing a private key causes GPG to construct and store the corresponding public key.
Command sequence:
mkdir tmp_home && chmod 700 tmp_home
gpg --no-default-keyring --homedir tmp_home --import test_key_1_private_key.txt
rm -r tmp_home
> /dev/null 2>&1
can be used in the second command to suppress its output.Example:
gpg --no-default-keyring --homedir tmp_home --import test_key_1_private_key.txt > /dev/null 2>&1
The command does not vary when importing a public key.
Example:
gpg --no-default-keyring --homedir tmp_home --import test_key_1_public_key.txt > /dev/null 2>&1
Worked example:
a) Import a private key
[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]$ mkdir tmp_home && chmod 700 tmp_home
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --import test_key_1_private_key.txt
gpg: keyring `tmp_home/secring.gpg' created
gpg: keyring `tmp_home/pubring.gpg' created
gpg: key 9DCC50A2: secret key imported
gpg: tmp_home/trustdb.gpg: trustdb created
gpg: key 9DCC50A2: public key "Test Key 1" 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_home
b) Import a private key and suppress the output
[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]$ mkdir tmp_home && chmod 700 tmp_home
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --import test_key_1_private_key.txt > /dev/null 2>&1
[spiano@localhost work]$ rm -r tmp_home
c) Import a public key
[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]$ mkdir tmp_home && chmod 700 tmp_home
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --import test_key_1_public_key.txt
gpg: keyring `tmp_home/secring.gpg' created
gpg: keyring `tmp_home/pubring.gpg' created
gpg: tmp_home/trustdb.gpg: trustdb created
gpg: key 9DCC50A2: public key "Test Key 1" imported
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)
[spiano@localhost work]$ rm -r tmp_home
d) Import a public key and suppress the output
[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]$ mkdir tmp_home && chmod 700 tmp_home
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --import test_key_1_private_key.txt > /dev/null 2>&1
[spiano@localhost work]$ rm -r tmp_home
7) Sign a file using a specific private key, producing a detached signature file
A file-to-be-signed must already be present.
Command sequence:
mkdir tmp_home && chmod 700 tmp_home
gpg --no-default-keyring --homedir tmp_home --import test_key_1_private_key.txt > /dev/null 2>&1
gpg --no-default-keyring --homedir tmp_home --output detached_signature_file.txt.asc --armor --detach-sign file_to_be_signed.txt
rm -r tmp_home
Worked example:
First, create a file-to-be-signed: hello.txt
[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]$ echo "world" > hello.txt
[spiano@localhost work]$ cat hello.txt
world
Next: Sign the file hello.txt.
[spiano@localhost work]$ ls -1
hello.txt
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]$ mkdir tmp_home && chmod 700 tmp_home
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --import test_key_1_private_key.txt > /dev/null 2>&1
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --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_home
[spiano@localhost work]$ rm -r tmp_home
[spiano@localhost work]$ cat hello.txt.asc
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
iQIcBAABAgAGBQJcqgvJAAoJEJeH0ledzFCiXIMP/ilrdyl9/JZEV6EA3i89FwQW
1jNwjJ1WCmrYt3ydMxhvXbM6Ygd0V0sUNWFW/74CrDsV4PeqVP11WNUtCSlQEJ1G
/R/JjFegHv5dc3dHbhOeHIUqqP9SQb/KyjL59Hp/cVBmvKCqVZrgg9q0/nmhC3rh
205CGZnbcT/HjQj9wFIQ/p26GoFLFIJ937hOU3z3OlgZA4LfN/WnXvbbNMVn1zry
vz40L4Mbqd4BbUqsjSscY3xPUPlP3RnvHu5juXUByzVxV4zy17b+a0PGpSckTMHO
yQbYS53mX8j8G68KxGmFuB8Uwq/5QxvvmuMBOHsvJnF71d1zMsHRrWcBaE24hDlY
qYTfwnjhXsK/N/xA4PrzwhGZy1i1rOq1PMAQHuTFuuUxJUsOJLp7/BC5fBT3HXoj
vynQv0pk/eThz16DZPPlQ4P/ypfAYuruxMLkgnGlUjnB2vc05kAgTYV2z/YgOMxM
ZVZgtRFIw1G2rqYzvx7uiseQFbl9osi+Iab9SMmixBVClMA+qYHPYzbxEy223N5d
OTIADtci0jcS2L0DzXdLFhiHtHtt9/SZSZsXw+R1y1vZv/QcCZYrSPuqbRn6vssT
VlW67Jqnx5Zx4Y9VpxKmPrX7rEVqOgNgPh0IfgzaKJstb7Kmr8Nz/RByeWxYRg9e
zvXZSkj35QaJWhATLiCY
=PRNX
-----END PGP SIGNATURE-----
8) Verify the detached signature of a file, checking that the signature was made by a specific public key
A file and a corresponding detached signature file must already be present.
The command
gpg --list-packets detached_signature_file.txt.asc
can be used to view the long key ID of the signing key. Example:
[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]
The long key ID is 3F84F8FE258E4B1A.
Now use operation 5) Display details of all keys to display the details of all the public keys. These details can then be searched for this long key ID. Alternatively, if you maintain a text file that records keyfile names, long key IDs, etc, you can look up the long key ID in there.
Now choose the public keyfile that corresponds to this long key ID and run the command sequence.
Command sequence:
mkdir tmp_home && chmod 700 tmp_home
gpg --no-default-keyring --homedir tmp_home --import test_key_1_public_key.txt > /dev/null 2>&1
gpg --no-default-keyring --homedir tmp_home --status-fd 1 --verify detached_signature_file.txt.asc file.txt
rm -r tmp_home
The important output line will be:
gpg: Good signature from "Test Key 1"
This shows that GPG considers the digital signature to be mathematically valid. The real name shown in the output line will vary depending on the key that made the signature.
There is also a simpler but slower approach, which is to test all the available public keys against the detached signature file and print output only from a successful verification. This can be done manually, where you change the keyfile name in each use of the command sequence. It can also be automated, using some code.
Here is an example of automating this process:
hello.txt (the file) and hello.txt.asc (the detached signature file) are already present.
ls -1 | grep "public_key.txt" | while read input_file; do mkdir tmp_home && chmod 700 tmp_home && gpg --no-default-keyring --homedir tmp_home --import "$input_file" > /dev/null 2>&1; gpg --no-default-keyring --homedir tmp_home --status-fd 1 --verify hello.txt.asc hello.txt 2>&1 | grep -E "Good signature from|Primary key fingerprint"; rm -r tmp_home; done
This Bash command sequence will use GPG to attempt to verify the detached signature using every keyfile in this directory that ends in "public_key.txt". It will then print output lines that contain either "Good signature from" or "Primary key fingerprint".
Worked example:
First, find the long key ID in the detached signature file.
[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]$ gpg --list-packets hello.txt.asc
:signature packet: algo 1, keyid 9787D2579DCC50A2
version 4, created 1554648009, md5len 0, sigclass 0x00
digest algo 2, begin of digest 5c 83
hashed subpkt 2 len 4 (sig created 2019-04-07)
subpkt 16 len 8 (issuer key ID 9787D2579DCC50A2)
data: [4094 bits]
The long key ID is 9787D2579DCC50A2.
Next: Use operation 5) Display details of all keys to display the details of all the public keys. These details can then be searched for this long key ID.
[spiano@localhost work]$ ls -1 | grep "public_key.txt" | while read input_file; do mkdir tmp_home && chmod 700 tmp_home && gpg --no-default-keyring --homedir tmp_home --import "$input_file" > /dev/null 2>&1 && gpg --no-default-keyring --homedir tmp_home --keyid-format long --fingerprint --list-keys; rm -r tmp_home; done
tmp_home/pubring.gpg
--------------------
pub 4096R/9787D2579DCC50A2 2019-04-07
Key fingerprint = 2AF1 4D88 6911 A54A D957 3494 9787 D257 9DCC 50A2
uid Test Key 1
sub 4096R/5CE721E1669C4CF2 2019-04-07
tmp_home/pubring.gpg
--------------------
pub 4096R/0661DB47BAB31156 2019-04-07
Key fingerprint = AAEB 1B64 81CE 89E0 D8C5 FBBC 0661 DB47 BAB3 1156
uid Test Key 2
sub 4096R/73ECB41DA1D93BF7 2019-04-07
The long key ID 9787D2579DCC50A2 is included in the details of Test Key 1.
Next: Choose the public keyfile that corresponds to this long key ID and run the command sequence.
The corresponding public keyfile is: test_key_1_public_key.txt
Next: Using this keyfile, attempt to verify the detached signature.
[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]$ mkdir tmp_home && chmod 700 tmp_home
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --import test_key_1_public_key.txt > /dev/null 2>&1
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --status-fd 1 --verify hello.txt.asc hello.txt
gpg: Signature made Sun 07 Apr 2019 03:40:09 PM BST using RSA key ID 9DCC50A2
[GNUPG:] SIG_ID OL6x/b9jybO1S8r4KfiK38aOcMI 2019-04-07 1554648009
[GNUPG:] GOODSIG 9787D2579DCC50A2 Test Key 1
gpg: Good signature from "Test Key 1"
[GNUPG:] VALIDSIG 2AF14D886911A54AD95734949787D2579DCC50A2 2019-04-07 1554648009 0 4 0 1 2 00 2AF14D886911A54AD95734949787D2579DCC50A2
[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: 2AF1 4D88 6911 A54A D957 3494 9787 D257 9DCC 50A2
[spiano@localhost work]$ rm -r tmp_home
The important output line is:
gpg: Good signature from "Test Key 1"
This shows that GPG considers the digital signature to be mathematically valid.
There is also a simpler but slower approach, which is to test all the available public keys against the detached signature file and print output only from a successful verification. This can be done manually, where you change the keyfile name in each use of the command sequence. It can also be automated, using some code.
Here is an example of automating this process:
hello.txt (the file) and hello.txt.asc (the detached signature file) are already present.
[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]$ ls -1 | grep "public_key.txt" | while read input_file; do mkdir tmp_home && chmod 700 tmp_home && gpg --no-default-keyring --homedir tmp_home --import "$input_file" > /dev/null 2>&1; gpg --no-default-keyring --homedir tmp_home --status-fd 1 --verify hello.txt.asc hello.txt 2>&1 | grep -E "Good signature from|Primary key fingerprint"; rm -r tmp_home; done
gpg: Good signature from "Test Key 1"
Primary key fingerprint: 2AF1 4D88 6911 A54A D957 3494 9787 D257 9DCC 50A2
Delete the detached signature file:
[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]$ rm hello.txt.asc
9) Encrypt a message file to a specific public key
A file-to-be-encrypted must already be present.
The
--recipient
option needs a value, which can be the real name or the fingerprint. You can use the real name when performing this operation manually, but you should use the fingerprint when writing a script to automate this operation. The
--encrypt
command will produce an interactive prompt, because (I think) no identity signature for this key is present in the GPG temporary home directory. To answer the prompt, press 'y' and then Enter. Note: The
--yes
option (which answers 'y' to most prompts) does not work for this particular prompt.
mkdir tmp_home && chmod 700 tmp_home
gpg --no-default-keyring --homedir tmp_home --import test_key_2_public_key.txt > /dev/null 2>&1
gpg --no-default-keyring --homedir tmp_home --keyid-format long --output encrypted_file.asc --armor --recipient "Test Key 2" --encrypt file_to_be_encrypted.txt
rm -r tmp_home
Worked example:
hello.txt is already present.
[spiano@localhost work]$ ls -1
hello.txt
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
a) Encrypt the file to a public key, using the real name to specify the key.
[spiano@localhost work]$ mkdir tmp_home && chmod 700 tmp_home
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --import test_key_1_public_key.txt > /dev/null 2>&1
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --keyid-format long --output hello.asc --armor --recipient "Test Key 1" --encrypt hello.txt
gpg: 5CE721E1669C4CF2: There is no assurance this key belongs to the named user
pub 4096R/5CE721E1669C4CF2 2019-04-07 Test Key 1
Primary key fingerprint: 2AF1 4D88 6911 A54A D957 3494 9787 D257 9DCC 50A2
Subkey fingerprint: 0CE7 3FCB E2D8 4B0A 82C7 C44F 5CE7 21E1 669C 4CF2
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_home
[spiano@localhost work]$ ls -1
hello.asc
hello.txt
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.asc
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1.4.10 (GNU/Linux)
hQIMA1znIeFmnEzyAQ//SLcu90980BEAtOCSNFW6g83DaJq/ibse+JD+lNQFnuep
DEABpx3Ghxi0AadXyXBqbZina43osZ+Fbp5bRQfgC9j/vtu73n2pmHAoFLc9tKVB
8lRvKw7Bew/b6vihcwfoY14uRmltEipDeinjUSSiXd+hC/v1uPUhUEFO5IBp6vK/
NuhubFPra3oZ7nhy6jzBUIq6CCEciYjS3ZtOXjUO/Dt4WXOmXCbixdkRIe65fxmN
9Cxa88Hyt6+HFshWO6V5t4ddVrM37nWpxiF8wgofOK3k+NFFZn2c28H+kIT3TJjW
eBvxPBSMPfTnO4XdgYHdhOykAQ375LOXgnlN2wQIgDuS33t69T2/cOfb9HeFDYDD
VQ4fq1BAonoCBGBRM4ZOShlGtXYDqqgF/rWajS+KYjB3V4LSOQQNQqboRXlIoM+C
Gq6lMXTVBRWfAIC1Xhiy/6rT0MiSuzpt0QEyV1LIcdxtbK/xNaJ1fCGzZCgza0Y/
FlmPgKSf3/84zpyTzTbQ558QHrJrPrKIzijGT8zKRtyIzeeJrbVQijp0eazB4Bwg
wRU8kPQeuJ/ruQyx1dhzeseMDvY9FgkwrwU2B4f8cGLrZ/n+qn+HKnvcdpiovD/x
ZvhhFgAZFH4/qyHYiKQClxMCoTRrQTtItXjyA+6V/RI10M0WBk8aaYZ8sExmk9/S
SgHJkZtCMvsMFWB9jkdlESNXUlD6kO9N/E04Gx6Y34MUGRyTq/ZXWno3TT7Go8Sp
MibiCJyYNh56IjAoNCSgr4qhUz6O4CHFi/tA
=0W9/
-----END PGP MESSAGE-----
b) Encrypt the file to a public key, using the fingerprint to specify the key.
First, delete the existing encrypted file.
[spiano@localhost work]$ ls -1
hello.asc
hello.txt
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.asc
Next: Use operation 5) Display details of all keys to display the details of all the public keys. Choose a key to which to encrypt the file hello.txt, then select this key's fingerprint. Remove all spaces from the fingerprint. Alternatively, if you maintain a text file that records keyfile names, fingerprints, etc, you can look up the fingerprint in there.
[spiano@localhost work]$ ls -1 | grep "public_key.txt" | while read input_file; do mkdir tmp_home && chmod 700 tmp_home && gpg --no-default-keyring --homedir tmp_home --import "$input_file" > /dev/null 2>&1 && gpg --no-default-keyring --homedir tmp_home --keyid-format long --fingerprint --list-keys; rm -r tmp_home; done
tmp_home/pubring.gpg
--------------------
pub 4096R/9787D2579DCC50A2 2019-04-07
Key fingerprint = 2AF1 4D88 6911 A54A D957 3494 9787 D257 9DCC 50A2
uid Test Key 1
sub 4096R/5CE721E1669C4CF2 2019-04-07
tmp_home/pubring.gpg
--------------------
pub 4096R/0661DB47BAB31156 2019-04-07
Key fingerprint = AAEB 1B64 81CE 89E0 D8C5 FBBC 0661 DB47 BAB3 1156
uid Test Key 2
sub 4096R/73ECB41DA1D93BF7 2019-04-07
I'll select Test Key 1. Its fingerprint is:
2AF1 4D88 6911 A54A D957 3494 9787 D257 9DCC 50A2
Without spaces, its fingerprint is:
2AF14D886911A54AD95734949787D2579DCC50A2
Next: Encrypt the file hello.txt to the public key, using the fingerprint to specify the key.
[spiano@localhost work]$ mkdir tmp_home && chmod 700 tmp_home
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --import test_key_1_public_key.txt > /dev/null 2>&1
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --keyid-format long --output hello.asc --armor --recipient 2AF14D886911A54AD95734949787D2579DCC50A2 --encrypt hello.txt
gpg: 5CE721E1669C4CF2: There is no assurance this key belongs to the named user
pub 4096R/5CE721E1669C4CF2 2019-04-07 Test Key 1
Primary key fingerprint: 2AF1 4D88 6911 A54A D957 3494 9787 D257 9DCC 50A2
Subkey fingerprint: 0CE7 3FCB E2D8 4B0A 82C7 C44F 5CE7 21E1 669C 4CF2
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_home
[spiano@localhost work]$ ls -1
hello.asc
hello.txt
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.asc
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1.4.10 (GNU/Linux)
hQIMA1znIeFmnEzyARAArkrCNtwP7Og6PmfVkSbhRCPlHzZiUY7+5h6m4YiOYZA8
bpSGZd4CKHeJhHeN5HGVe87Ce0liWxls16KpKsPNwTM/AixljMaSNkHeoQ4vZkWB
xjppZxvS5OiaPgbVHukffqYc6nv6N8y7WwLKXsk+YoluuiBN16HieDtxHe2+ao2a
SwvOnW/Mw7yQFKRDPBopjc7n3+KIQnbVchbC0gkIJQsLm6oPgJrHUmBXNRB/VJYT
GcVHeCweOb2KF6D8TvgGKPmHffyUpCnl2Jt22wmpLJIzEvyxcpzv4p9vcBiaZ5By
Wt73AUHF0hr3a82waRrCjlzwLpwQONQSFwjNbQCw8lmKlv3DbvI3BYMyOJ6PGsbR
7tBZI6JZjj90Ur5HdORV2xzRYWmVBQFgcMMDTE6E5qCCcI8hV+fUm+ByeShVLnHG
bSID5gdRLEQr/b+N4C8WRpRWm8kztym2QxlHQhB/Sn1P+cUAmQ5qTfGswisaW9eX
vwl1hl8ZBWAgtr/OhLQ+9a4UINTA9dPqMcN/I1wWjaxjHssg9y348c4x+aIHiLL1
vR/sbKJwRa7ZlnyE2T7rXYzPfTOaKaVxuKdzOKc8hg6Jqt70wcJ7CE1k39cJCfMY
nG0dFxMMCg/tFSyAIcuYufG+/Ab2sPaSqRH5YkKgikKn9yEC7VInfZ1vfCg0LqTS
SgHxSuN+8w5CcAmkXwDwvu296iUpA39c4xHgxXemZy62dJOAPh77VmYXQIUlfAeF
oMhjZatToFAqu7zUYSDUu6YO/JcvtyYOBEky
=5kYR
-----END PGP MESSAGE-----
10) Decrypt an encrypted message file, checking that the decryption was performed using a specific private key
The encrypted file must already be present.
The command
gpg --list-packets encrypted_file.asc
can be used to view the long key ID of the public subkey to which the file was encrypted. I'll refer to this public subkey as the "destination key". Example:
[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 of the destination key is 7CBB1E9750C96C60.
Now use operation 5) Display details of all keys to produce text that can be searched for this long key ID. Alternatively, if you maintain a text file that records keyfile names, long key IDs, long key IDs of public subkeys, etc, you can look up the long key ID in there.
Now choose the private keyfile that corresponds to the long key ID of this destination key and run the command sequence.
Command sequence:
mkdir tmp_home && chmod 700 tmp_home
gpg --no-default-keyring --homedir tmp_home --import test_key_1_private_key.txt > /dev/null 2>&1
gpg --no-default-keyring --homedir tmp_home --status-fd 1 --keyid-format long --output decrypted_file.txt --decrypt encrypted_file.asc
rm -r tmp_home
The output lines will be:
[GNUPG:] ENC_TO 5CE721E1669C4CF2 1 0
[GNUPG:] GOOD_PASSPHRASE
gpg: encrypted with 4096-bit RSA key, ID 5CE721E1669C4CF2, created 2019-04-07
"Test Key 1"
[GNUPG:] BEGIN_DECRYPTION
[GNUPG:] PLAINTEXT 62 1554650007 hello.txt
[GNUPG:] PLAINTEXT_LENGTH 6
[GNUPG:] DECRYPTION_OKAY
[GNUPG:] GOODMDC
[GNUPG:] END_DECRYPTION
The output line
[GNUPG:] DECRYPTION_OKAY
will show that GPG considers the decryption to have been successfully performed. The real name shown in the output will vary depending on the destination key.
Note: The output also contains the real name ("Test Key 1") of the keypair and the long key ID of the public subkey (5CE721E1669C4CF2).
There is also a simpler but slower approach, which is to test all the available private keys against the encrypted file and print output only from a successful decryption. This can be done manually, where you change the keyfile name in each use of the command sequence. It can also be automated, using some code.
Here is an example of automating this process:
hello.asc (the encrypted file) is already present.
ls -1 | grep "private_key.txt" | while read input_file; do mkdir tmp_home && chmod 700 tmp_home && gpg --no-default-keyring --homedir tmp_home --import "$input_file" > /dev/null 2>&1; OUTPUT="$(gpg --no-default-keyring --homedir tmp_home --status-fd 1 --keyid-format long --output hello_decrypted.txt --decrypt hello.asc 2>&1)"; echo $OUTPUT | grep "DECRYPTION_OKAY"; rm -r tmp_home; done
This Bash command sequence will use GPG to attempt to decrypt the encrypted file using every keyfile in this directory that ends in "private_key.txt". It will then print output lines that contain the string "DECRYPTION_OKAY".
The output will be:
[GNUPG:] ENC_TO 5CE721E1669C4CF2 1 0 [GNUPG:] GOOD_PASSPHRASE gpg: encrypted with 4096-bit RSA key, ID 5CE721E1669C4CF2, created 2019-04-07 "Test Key 1" [GNUPG:] BEGIN_DECRYPTION [GNUPG:] PLAINTEXT 62 1554650007 hello.txt [GNUPG:] PLAINTEXT_LENGTH 6 [GNUPG:] DECRYPTION_OKAY [GNUPG:] GOODMDC [GNUPG:] END_DECRYPTION
The OUTPUT variable doesn't preserve the newlines in the output of the decryption command, so the output is a single line.
Worked example:
The encrypted file hello.asc is already present.
First, find the long key ID in the encrypted file.
[spiano@localhost work]$ ls -1
hello.asc
hello.txt
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]$ gpg --list-packets hello.asc
:pubkey enc packet: version 3, algo 1, keyid 5CE721E1669C4CF2
data: [4096 bits]
:encrypted data packet:
length: 74
mdc_method: 2
gpg: encrypted with RSA key, ID 669C4CF2
gpg: decryption failed: secret key not available
The long key ID of the destination key is 5CE721E1669C4CF2.
Next: Use operation 5) Display details of all keys to display the details of all the public keys. These details can then be searched for this long key ID of the destination key.
[spiano@localhost work]$ ls -1 | grep "public_key.txt" | while read input_file; do mkdir tmp_home && chmod 700 tmp_home && gpg --no-default-keyring --homedir tmp_home --import "$input_file" > /dev/null 2>&1 && gpg --no-default-keyring --homedir tmp_home --keyid-format long --fingerprint --list-keys; rm -r tmp_home; done
tmp_home/pubring.gpg
--------------------
pub 4096R/9787D2579DCC50A2 2019-04-07
Key fingerprint = 2AF1 4D88 6911 A54A D957 3494 9787 D257 9DCC 50A2
uid Test Key 1
sub 4096R/5CE721E1669C4CF2 2019-04-07
tmp_home/pubring.gpg
--------------------
pub 4096R/0661DB47BAB31156 2019-04-07
Key fingerprint = AAEB 1B64 81CE 89E0 D8C5 FBBC 0661 DB47 BAB3 1156
uid Test Key 2
sub 4096R/73ECB41DA1D93BF7 2019-04-07
The long key ID 5CE721E1669C4CF2 is included in the details of Test Key 1, in the line that starts with "sub".
Next: Choose the private keyfile that corresponds to this long key ID and run the command sequence.
The corresponding private keyfile is: test_key_1_private_key.txt
Next: Using this keyfile, attempt to decrypt the encrypted file.
[spiano@localhost work]$ ls -1
hello.asc
hello.txt
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]$ mkdir tmp_home && chmod 700 tmp_home
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --import test_key_1_private_key.txt > /dev/null 2>&1
[spiano@localhost work]$ gpg --no-default-keyring --homedir tmp_home --status-fd 1 --keyid-format long --output hello_decrypted.txt --decrypt hello.asc
[GNUPG:] ENC_TO 5CE721E1669C4CF2 1 0
[GNUPG:] GOOD_PASSPHRASE
gpg: encrypted with 4096-bit RSA key, ID 5CE721E1669C4CF2, created 2019-04-07
"Test Key 1"
[GNUPG:] BEGIN_DECRYPTION
[GNUPG:] PLAINTEXT 62 1554650007 hello.txt
[GNUPG:] PLAINTEXT_LENGTH 6
[GNUPG:] DECRYPTION_OKAY
[GNUPG:] GOODMDC
[GNUPG:] END_DECRYPTION
[spiano@localhost work]$ rm -r tmp_home
[spiano@localhost work]$ ls -1
hello.asc
hello_decrypted.txt
hello.txt
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_decrypted.txt
world
[spiano@localhost work]$ cat hello.txt
world
The output line
[GNUPG:] DECRYPTION_OKAY
shows that GPG considers the decryption to have been successfully performed.
Delete the decrypted file:
[spiano@localhost work]$ rm hello_decrypted.txt
There is also a simpler but slower approach, which is to test all the available private keys against the encrypted file and print output only from a successful decryption. This can be done manually, where you change the keyfile name in each use of the command sequence. It can also be automated, using some code.
Here is an example of automating this process:
hello.asc (the encrypted file) is already present.
[spiano@localhost work]$ ls -1
hello.asc
hello.txt
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]$ ls -1 | grep "private_key.txt" | while read input_file; do mkdir tmp_home && chmod 700 tmp_home && gpg --no-default-keyring --homedir tmp_home --import "$input_file" > /dev/null 2>&1; OUTPUT="$(gpg --no-default-keyring --homedir tmp_home --status-fd 1 --keyid-format long --output hello_decrypted.txt --decrypt hello.asc 2>&1)"; echo $OUTPUT | grep "DECRYPTION_OKAY"; rm -r tmp_home; done
[GNUPG:] ENC_TO 5CE721E1669C4CF2 1 0 [GNUPG:] GOOD_PASSPHRASE gpg: encrypted with 4096-bit RSA key, ID 5CE721E1669C4CF2, created 2019-04-07 "Test Key 1" [GNUPG:] BEGIN_DECRYPTION [GNUPG:] PLAINTEXT 62 1554650007 hello.txt [GNUPG:] PLAINTEXT_LENGTH 6 [GNUPG:] DECRYPTION_OKAY [GNUPG:] GOODMDC [GNUPG:] END_DECRYPTION
[spiano@localhost work]$ ls -1
hello.asc
hello_decrypted.txt
hello.txt
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_decrypted.txt
world
[spiano@localhost work]$ cat hello.txt
world
That's the end of this project.