I have:
- A file
- A detached PGP signature of that file in ASCII armor format and
- A 40-character (long-format) fingerprint identifying the one key that must have a valid signature
What is the correct way to write a BASH script to verify that the given signature is valid (only for the given fingerprint) for the given file using the gpg
command on *nix?
Note: The solution ideally would not just parse STDOUT from
gpg
--such that the BASH script in the solution provided wouldn't break if the words or format of the output are slightly changed in the future.And, especially important, detached signatures can be signed by multiple keys. So this solution should fail if, for example, an attacker took the file and its detached signature and edited the file while adding their own signature to the detached signature. Note that, with this attack, there would be a BAD signature present from the key whose fingerprint we're pinning in our script and a GOOD signature from the attacker's key, which is irrelevant. In this case, the solution must fail.
For example, consider the following:
- https://files.pythonhosted.org/packages/cb/85/8a1588a04172e0853352ecfe214264c65a62ab35374d9ad9c569cf94c2a3/python_gnupg-0.4.6-py2.py3-none-any.whl
- https://files.pythonhosted.org/packages/cb/85/8a1588a04172e0853352ecfe214264c65a62ab35374d9ad9c569cf94c2a3/python_gnupg-0.4.6-py2.py3-none-any.whl.asc
CA749061914EAC138E66EADB9147B477339A9B86
Currently I have the following in my BASH script
#!/bin/bash
ONLY_TRUST_THIS_FINGERPRINT='CA749061914EAC138E66EADB9147B477339A9B86'
tmpDir="`mktemp -d`" || exit 1
pushd "${tmpDir}"
wget https://files.pythonhosted.org/packages/cb/85/8a1588a04172e0853352ecfe214264c65a62ab35374d9ad9c569cf94c2a3/python_gnupg-0.4.6-py2.py3-none-any.whl
wget https://files.pythonhosted.org/packages/cb/85/8a1588a04172e0853352ecfe214264c65a62ab35374d9ad9c569cf94c2a3/python_gnupg-0.4.6-py2.py3-none-any.whl.asc
wget https://keys.openpgp.org/vks/v1/by-fingerprint/CA749061914EAC138E66EADB9147B477339A9B86
mkdir gnupg
gpg --homedir "${tmpDir}/gnupg" --import CA749061914EAC138E66EADB9147B477339A9B86
What command(s) should follow in the script above to safely confirm that the file has a valid signature from the private key matching our pinned fingerprint?
EDIT: Here's an example output of a simple gpg --verify ...
that has a GOOD signature by an attacker and a BAD signature from the actual developer; it should fail.
user@disp2952:/tmp/tmp.nUmxfwbwfK$ gpg --homedir gnupg/ --verify python_gnupg-0.4.6-py2.py3-none-any.whl.asc
gpg: WARNING: unsafe permissions on homedir '/tmp/tmp.nUmxfwbwfK/gnupg'
gpg: assuming signed data in 'python_gnupg-0.4.6-py2.py3-none-any.whl'
gpg: Signature made Sat 29 Aug 2020 10:04:03 PM +0545
gpg: using RSA key 2DA3BAD0DB41087CA7E5E4C1F93C17B957F73F5A
gpg: Good signature from "Mallory <[email protected]>" [unknown]
gpg: Signature made Fri 17 Apr 2020 07:54:23 PM +0545
gpg: using RSA key 9147B477339A9B86
gpg: BAD signature from "Vinay Sajip (CODE SIGNING KEY) <[email protected]>" [unknown]
user@disp2952:/tmp/tmp.nUmxfwbwfK$ echo $?
1
user@disp2952:/tmp/tmp.nUmxfwbwfK$