Debian Verifier
1. Introduction
Whenever it is recommended that the digital signature and hashes of a file be verified to avoid files being modified in transit or at rest by trojans or any other malicious code, the average user encounters some difficulties in understanding the process and executing the necessary commands. Sometimes because the user lacks technical knowledge, or because the process may vary depending on how the signature was generated or with the cryptographic method chosen.
The Debian Verifier script does just that: it downloads a Debian Linux image, its digital signatures and hashes from the official website and verifies that the signature is valid and that the hashes match. It is a script (bash or python) that does not need root privileges and runs on macOS and Linux (python version is supposed to run on Windows). The developers generated a SHA-256 hash of each file, inserted these hashes into a text file named SHA256SUMS
, and this file was digitally signed.
To download the public key that verifies the authenticity of Debian Linux the script will initiate a TCP 11371 (hkp) connection to the Debian key server, and to download the image from Debian website it will be necessary to ‘talk’ TCP 443 (https).
Learn more about the verification of digital signatures or about the procedures to verify the digital signature of Debian Linux.
2. Bash Script
To run the script, paste the ~200 lines of code below to a local file and add the executable attribute as shown here:
$ chmod +x debian_verifier.sh
Debian Verifier:
#! /bin/bash -
# Debian Verifier v0.2.1
# This script downloads and verifies the digital signature of Debian Linux (stables releases only).
# Reference: https://www.debian.org/CD/verify
# Author: Marcelo Martins (stakey.club)
# Syntax: debian_verifier.sh -v [version number | "current"] -a $ARCH -m ["cd" | "dvd"]
# -v: Debian version: defaults to 'current' if left blank. Ex: 9.8.0
# -a: Architecture: amd64, arm64, armel, armhf, i386, mips, mips64el, mipsel, ppc64el, s390x, source or multi-arch
# $ARCH defaults to 'multi-arch' if left blank
# -m: Media type: 'cd' or 'dvd', defaults to 'cd' if left blank
# Examples: ./debian_verifier.sh
# ./debian_verifier.sh -v 9.8.0 -a i386 -m dvd
# ./debian_verifier.sh -v 9.8.0 -a amd64 -m cd
usage() {
echo "Usage: $0 [-v <string>] [-a <\$ARCH>] [-m <cd|dvd>]" 1>&2
echo "-v: Debian version: defaults to 'current' if left blank. Ex: 9.8.0"
echo "-a: \$ARCH may be one of these: amd64, arm64, armel, armhf, i386, mips, mips64el, mipsel, ppc64el, s390x, multi-arch"
echo " \$ARCH defaults to 'multi-arch' if left blank"
echo "-m: Media type: 'cd' or 'dvd', defaults to 'cd' if left blank"
exit 1
}
while getopts ":a:v:m:" o; do
case "${o}" in
a)
a=${OPTARG}
;;
v)
v=${OPTARG}
;;
m)
m=${OPTARG}
;;
*)
usage
;;
esac
done
shift $((OPTIND-1))
if [[ -z ${v} ]]; then
VERSION="current"
elif [[ ${v} =~ ^[0-9]\.[0-9]{1,2}\.?[0-9]{0,2} ]]; then
VERSION=${v}
else
echo -e "ERROR: Package version seems to be in the wrong format.\n"
usage
fi
if [[ -z ${a} || ${a} == "multi-arch" ]]; then
ARCH_DIR="multi-arch"
ARCH_FILE="amd64-i386"
elif [[ ${a} =~ [amd64|arm64|armel|armhf|i386|mips|mips64el|mipsel|ppc64el|s390x] ]]; then
ARCH_DIR=${a}
ARCH_FILE=${a}
else
echo -e "ERROR: Architecture is invalid.\n"
usage
fi
if [[ -z ${m} || ${m} == "cd" ]]; then
MEDIA_DIR="iso-cd"
MEDIA_FILE="netinst"
MEDIA="CD"
elif [[ ${m} == "dvd" ]]; then
MEDIA_DIR="iso-dvd"
MEDIA_FILE="DVD-1"
MEDIA="DVD"
else
echo -e "ERROR: Media is invalid.\n"
usage
fi
ARCHIVE_DOWNLOAD="https://cdimage.debian.org/cdimage/archive/$VERSION/$ARCH_DIR/$MEDIA_DIR"
RELEASE_DOWNLOAD="https://cdimage.debian.org/debian-cd/$VERSION/$ARCH_DIR/$MEDIA_DIR"
DEBIAN_DOWNLOAD=""
DEBIAN_MANIFEST="SHA256SUMS"
DEBIAN_MANIFEST_SIGN="SHA256SUMS.sign"
DEBIAN_KEYHOST="keyring.debian.org"
# The keys will be kept hardcoded.
DEBIAN_KEY_FP=(64E6EA7D 6294BE9B 09EA8AC3)
DEBIAN_KEY_ID=()
for k in ${!DEBIAN_KEY_FP[*]}; do
DEBIAN_KEY_ID=${DEBIAN_KEY_ID[*]}" 0x"${DEBIAN_KEY_FP[k]}
done
[[ ! -x `which gpg` ]] && echo "ERROR: Could not locate gpg." && exit 5
if [[ `uname -a | grep -c "Darwin"` -gt 0 ]]; then
FLAVOR="Mac"
[[ ! -x `which curl` ]] && echo "ERROR: Could not locate curl." && exit 6
LATEST_VERSION=`curl -Ssf -L https://cdimage.debian.org/debian-cd/ | grep '[0-9]\{1,2\}\.[0-9]\{1,2\}.*/' | grep "folder" | grep -v "live" | cut -d'>' -f 3 | cut -d'"' -f 2 | cut -d'/' -f 1`
if [[ $VERSION == "current" || $VERSION == $LATEST_VERSION ]]; then
VERSION_NUMBER=`curl -s -L $RELEASE_DOWNLOAD | grep -m 1 "debian-[0-9]" | cut -d'>' -f 3 | cut -d'-' -f 2`
DEBIAN_DOWNLOAD=$RELEASE_DOWNLOAD
else
VERSION_NUMBER=$VERSION
DEBIAN_DOWNLOAD=$ARCHIVE_DOWNLOAD
fi
if [[ `curl -Is $DEBIAN_DOWNLOAD/ | head -n 1 | grep -c "404"` -gt 0 ]]; then
echo "ERROR: could not find folder $DEBIAN_DOWNLOAD/."
if [[ $DEBIAN_DOWNLOAD == $ARCHIVE_DOWNLOAD ]]; then
echo "The latest version of Debian Linux is $LATEST_VERSION."
echo "You asked for version $VERSION, for platform $ARCH_DIR in $MEDIA_DIR media."
echo "There is a chance this media does not exist in the archives anymore."
fi
exit 8
fi
else
FLAVOR="Linux"
[[ ! -x `which wget` ]] && echo "ERROR: Could not locate wget." && exit 7
LATEST_VERSION=`wget -q -O - https://cdimage.debian.org/debian-cd/ | grep '[0-9]\{1,2\}\.[0-9]\{1,2\}.*/' | grep "folder" | grep -v "live" | cut -d'>' -f 3 | cut -d'"' -f 2 | cut -d'/' -f 1`
if [[ $VERSION == "current" || $VERSION == $LATEST_VERSION ]]; then
VERSION_NUMBER=`wget -q -O - $RELEASE_DOWNLOAD | grep -m 1 "debian-[0-9]" | cut -d'>' -f 3 | cut -d'-' -f 2`
DEBIAN_DOWNLOAD=$RELEASE_DOWNLOAD
else
VERSION_NUMBER=$VERSION
DEBIAN_DOWNLOAD=$ARCHIVE_DOWNLOAD
fi
if [[ `wget -S -nv -q -O - $DEBIAN_DOWNLOAD/ | head -n 1 | grep -c "404"` -gt 0 ]]; then
echo "ERROR: could not find folder $DEBIAN_DOWNLOAD/."
if [[ $DEBIAN_DOWNLOAD == $ARCHIVE_DOWNLOAD ]]; then
echo "The latest version of Debian Linux is $LATEST_VERSION."
echo "You asked for version $VERSION, for platform $ARCH_DIR in $MEDIA_DIR media."
echo "There is a chance this media does not exist in the archives anymore."
fi
exit 8
fi
fi
DEBIAN_IMAGE="debian-$VERSION_NUMBER-$ARCH_FILE-$MEDIA_FILE.iso"
GREP_STRING="'"
for k in ${!DEBIAN_KEY_FP[*]}; do
GREP_STRING="$GREP_STRING\|${DEBIAN_KEY_FP[k]}"
done
GREP_STRING="$GREP_STRING\|'"
if [[ `gpg --with-colons -k "Debian" | grep 'fpr' | grep -c "$GREP_STRING"` -eq 3 ]]; then
echo "Debian signing public keys { ${DEBIAN_KEY_ID[*]} } have already been imported."
else
# Uses keyring.debian.org to import the key (uses HKP, depends on TCP 11371).
for i in ${!DEBIAN_KEY_ID[*]}; do
if [[ `gpg --with-colons -k "Debian" | grep 'fpr' | grep -c ${DEBIAN_KEY_FP[i]}` -eq 0 ]]; then
echo "Importing Debian signing public key ${DEBIAN_KEY_ID[i]} from $DEBIAN_KEYHOST"
GPG_OUT=$(gpg --with-colons --status-fd 1 --keyserver $DEBIAN_KEYHOST --recv-keys ${DEBIAN_KEY_ID[i]} 2> /dev/null)
if [[ `echo $GPG_OUT | grep -c "FAILURE"` -eq 1 ]]; then
echo "[ FAIL ] GPG failed to import key ${DEBIAN_KEY_ID[i]} from $DEBIAN_KEYHOST. It may have timed out."
echo "Make sure you can send traffic using port TCP 11371."
exit 2
fi
fi
done
fi
DOWNLOAD_DIR=${DEBIAN_IMAGE%.*} # Manifest and signature files have the same name for all versions.
[[ ! -d $DOWNLOAD_DIR ]] && mkdir $DOWNLOAD_DIR
if [[ ! -f $DOWNLOAD_DIR/$DEBIAN_IMAGE || ! -f $DOWNLOAD_DIR/$DEBIAN_MANIFEST || ! -f $DOWNLOAD_DIR/$DEBIAN_MANIFEST_SIGN ]]; then
echo "Downloading files from Debian website to local directory '$DOWNLOAD_DIR'..."
if [[ $FLAVOR == "Mac" ]]; then
[[ ! -f $DOWNLOAD_DIR/$DEBIAN_IMAGE ]] && echo "- $DEBIAN_IMAGE" && curl -C - -L -# $DEBIAN_DOWNLOAD/$DEBIAN_IMAGE -o $DOWNLOAD_DIR/$DEBIAN_IMAGE
[[ ! -f $DOWNLOAD_DIR/$DEBIAN_MANIFEST ]] && echo "- $DEBIAN_MANIFEST" && curl -L -# $DEBIAN_DOWNLOAD/$DEBIAN_MANIFEST -o $DOWNLOAD_DIR/$DEBIAN_MANIFEST
[[ ! -f $DOWNLOAD_DIR/$DEBIAN_MANIFEST_SIGN ]] && echo "- $DEBIAN_MANIFEST_SIGN" && curl -L -# $DEBIAN_DOWNLOAD/$DEBIAN_MANIFEST_SIGN -o $DOWNLOAD_DIR/$DEBIAN_MANIFEST_SIGN
else
[[ ! -f $DOWNLOAD_DIR/$DEBIAN_IMAGE ]] && wget -c -nv -q --show-progress $DEBIAN_DOWNLOAD/$DEBIAN_IMAGE -O $DOWNLOAD_DIR/$DEBIAN_IMAGE
[[ ! -f $DOWNLOAD_DIR/$DEBIAN_MANIFEST ]] && wget -nv -q --show-progress $DEBIAN_DOWNLOAD/$DEBIAN_MANIFEST -O $DOWNLOAD_DIR/$DEBIAN_MANIFEST
[[ ! -f $DOWNLOAD_DIR/$DEBIAN_MANIFEST_SIGN ]] && wget -nv -q --show-progress $DEBIAN_DOWNLOAD/$DEBIAN_MANIFEST_SIGN -O $DOWNLOAD_DIR/$DEBIAN_MANIFEST_SIGN
fi
else
echo "All files have already been copied to local directory '$DOWNLOAD_DIR'."
echo "- $DEBIAN_IMAGE"
echo "- $DEBIAN_MANIFEST"
echo "- $DEBIAN_MANIFEST_SIGN"
fi
echo -e "\nVerifying digital signature and hashes...\n"
GPG_OUT2=$(gpg --with-colons --status-fd 1 --verify $DOWNLOAD_DIR/$DEBIAN_MANIFEST_SIGN 2> /dev/null)
if [[ `echo $GPG_OUT2 | grep -c "GOOD"` -eq 1 ]]; then
if [[ $FLAVOR == "Mac" ]]; then
[[ ! -x `which shasum` ]] && echo "ERROR: Could not locate shasum." && exit 9
SHASUM=`shasum -a 256 $DOWNLOAD_DIR/$DEBIAN_IMAGE | cut -d' ' -f1`
else # Linux or ARM
[[ ! -x `which sha256sum` ]] && echo "ERROR: Could not locate sha256sum." && exit 9
SHASUM=`sha256sum $DOWNLOAD_DIR/$DEBIAN_IMAGE | cut -d' ' -f1`
fi
if [[ `grep -c $SHASUM $DOWNLOAD_DIR/$DEBIAN_MANIFEST` -eq 1 ]]; then
echo -e "[ SUCCESS ] GPG signature for $DEBIAN_MANIFEST successfully verified."
echo -e "[ SUCCESS ] SHA-256 hash of $DEBIAN_IMAGE successfully verified.\n"
# The script won't delete files.
echo -e "It's now safe to delete files $DEBIAN_MANIFEST and $DEBIAN_MANIFEST_SIGN\n"
echo "RESULT: SUCCESS. It means that $DEBIAN_IMAGE wasn't modified after its creation"
echo "and that the file $DEBIAN_MANIFEST that contains the proof was signed by Debian signing private key."
echo -e "Learn more at https://stakey.club/en/verifying-digital-signatures/\n"
# The script won't do anything to the downloaded image.
echo "To use the image:"
echo "1. burn $DEBIAN_IMAGE to a $MEDIA; or"
echo "2. use it to boot a virtual machine"
else
echo -e "[ SUCCESS ] GPG signature for $DEBIAN_IMAGE successfully verified."
echo -e "[ FAIL ] SHA-256 hash of $DEBIAN_IMAGE verification FAILED!\n"
echo "RESULT: FAIL. It means that the manifest wasn't modified after its creation"
echo "but $DEBIAN_IMAGE is incomplete or was probably modified after its creation."
exit 3
fi
else
echo -e "[ FAIL ] GPG did not find a \"good signature\" for $DEBIAN_IMAGE. Verification FAILED!"
exit 4
fi
3. Python Script
To execute this Python script, the following packages must be installed on the computer. On Windows, Python and gpg4win must be installed:
$ sudo pip install python-gnupg
$ sudo pip install certifi
$ python debian_verifier.sh
Debian Verifier:
#!/usr/bin/env python3
import argparse
from pathlib import Path
import re
import urllib.request
import ssl
import hashlib
import gnupg
import shutil
import certifi
# Debian Verifier v0.2
# This script downloads and verifies the digital signature of Debian Linux (stables releases only).
# Reference: https://www.debian.org/CD/verify
# Author: Marcelo Martins (stakey.club)
# Syntax: debian_verifier.py -v [version number | "current"] -a $ARCH -m ["cd" | "dvd"]
# -v: Debian version: defaults to 'current' if left blank. Ex: 9.8.0
# -a: Architecture: amd64, arm64, armel, armhf, i386, mips, mips64el, mipsel, ppc64el, s390x, source or multi-arch
# $ARCH defaults to 'multi-arch' if left blank
# -m: Media type: 'cd' or 'dvd', defaults to 'cd' if left blank
# Examples: $ python debian_verifier.py
# $ python debian_verifier.py -v 9.8.0 -a i386 -m dvd
# $ python debian_verifier.py -v 9.8.0 -a amd64 -m cd
parser = argparse.ArgumentParser()
parser.add_argument("-v", "--version", help="Version to download", dest='version')
parser.add_argument("-a", "--arch", help="Architecture", dest='arch')
parser.add_argument("-m", "--media", help="Media", dest='media')
args = parser.parse_args()
__version__ = '0.2'
def usage():
print("Usage: $0 [-v <string>] [-a <$ARCH>] [-m <cd|dvd>]")
print("-v: Debian version: defaults to 'current' if left blank. Ex: 9.8.0")
print("-a: $ARCH may be one of these: amd64, arm64, armel, armhf, i386, mips, mips64el, "
"mipsel, ppc64el, s390x, multi-arch")
print(" $ARCH defaults to 'multi-arch' if left blank")
print("-m: Media type: 'cd' or 'dvd', defaults to 'cd' if left blank")
exit(1)
if not args.version:
VERSION = "current"
elif re.search('^[0-9]{1,2}.[0-9]{1,2}.?[0-9]{0,2}', args.version):
VERSION = args.version
else:
VERSION = ""
print("ERROR: Package version seems to be in the wrong format.\n")
usage()
if not args.arch:
ARCH_DIR = "multi-arch"
ARCH_FILE = "amd64-i386"
elif re.search('amd64|arm64|armel|armhf|i386|mips|mips64el|mipsel|ppc64el|s390x', args.arch):
ARCH_DIR = args.arch
ARCH_FILE = args.arch
else:
ARCH_DIR, ARCH_FILE = "", ""
print("ERROR: Architecture is invalid.\n")
usage()
if not args.media or args.media == "cd":
MEDIA_DIR = "iso-cd"
MEDIA_FILE = "netinst"
MEDIA = "CD"
elif args.media == "dvd":
MEDIA_DIR = "iso-dvd"
MEDIA_FILE = "DVD-1"
MEDIA = "DVD"
else:
MEDIA_DIR, MEDIA_FILE, MEDIA = "", "", ""
print("ERROR: Media is invalid.\n")
usage()
HASH_BLOCKSIZE = 65536
ARCHIVE_DOWNLOAD = "https://cdimage.debian.org/cdimage/archive/" + VERSION + "/" + ARCH_DIR + "/" + MEDIA_DIR
RELEASE_DOWNLOAD = "https://cdimage.debian.org/debian-cd/" + VERSION + "/" + ARCH_DIR + "/" + MEDIA_DIR
DEBIAN_DOWNLOAD = ""
DEBIAN_MANIFEST = "SHA256SUMS"
DEBIAN_MANIFEST_SIGN = "SHA256SUMS.sign"
DEBIAN_KEYHOST = "keyring.debian.org"
# The keys will be kept hardcoded.
DEBIAN_KEY_FP = ["64E6EA7D", "6294BE9B", "09EA8AC3"]
DEBIAN_KEY_ID = []
for k in DEBIAN_KEY_FP:
DEBIAN_KEY_ID.append("0x" + k)
client_context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_CLIENT)
client_context.options |= ssl.OP_NO_TLSv1
client_context.options |= ssl.OP_NO_TLSv1_1
client_context.load_default_certs(purpose=ssl.Purpose.SERVER_AUTH)
client_context.load_verify_locations(capath=certifi.where())
LATEST_VERSION = re.search('([0-9]{1,2}.[0-9]{1,2}.?[0-9]{0,2}?)/',
str(urllib.request.urlopen("https://cdimage.debian.org/debian-cd/",
context=client_context).read(3000))).group(1)
if VERSION == "current" or VERSION == LATEST_VERSION:
VERSION_NUMBER = re.search('debian-([0-9]{1,2}.[0-9]{1,2}.?[0-9]{0,2})',
str(urllib.request.urlopen(RELEASE_DOWNLOAD,
context=client_context).read(9000))).group(1)
DEBIAN_DOWNLOAD = RELEASE_DOWNLOAD
else:
VERSION_NUMBER = VERSION
DEBIAN_DOWNLOAD = ARCHIVE_DOWNLOAD
response = urllib.request.urlopen(DEBIAN_DOWNLOAD, context=client_context)
if response.code == 404:
print("ERROR: could not find folder", DEBIAN_DOWNLOAD + "/.")
if DEBIAN_DOWNLOAD == ARCHIVE_DOWNLOAD:
print("The latest version of Debian Linux is", LATEST_VERSION + ".")
print("You asked for version", VERSION + ", for platform", ARCH_DIR, "in", MEDIA_DIR, "media.")
print("There is a chance this media does not exist in the archives anymore.")
exit(8)
DEBIAN_IMAGE = "debian-" + VERSION_NUMBER + "-" + ARCH_FILE + "-" + MEDIA_FILE + ".iso"
gpg = gnupg.GPG()
if len(list(set(re.findall("|".join(DEBIAN_KEY_FP), str(gpg.list_keys(keys=DEBIAN_KEY_ID)))))) == 3:
print("Debian signing public keys", DEBIAN_KEY_ID, "have already been imported.")
else:
# Uses keyring.debian.org to import the key (uses HKP, depends on TCP 11371).
for idx, k in enumerate(DEBIAN_KEY_FP):
if len(list(set(re.findall(str(k), str(gpg.list_keys(keys=DEBIAN_KEY_ID)))))) == 0:
print("Importing Debian signing public key", DEBIAN_KEY_ID[idx], "from", DEBIAN_KEYHOST)
gpg_out = gpg.recv_keys(DEBIAN_KEYHOST, DEBIAN_KEY_ID)
if not gpg_out.results[0]['ok']:
print("[ FAIL ] GPG failed to import key ${DEBIAN_KEY_ID[i]} from", DEBIAN_KEYHOST,
". It may have timed out.")
print("Make sure you can send traffic using port TCP 11371.")
exit(2)
DOWNLOAD_DIR = "debian-" + VERSION_NUMBER + "-" + ARCH_FILE + "-" + MEDIA_FILE
not Path(DOWNLOAD_DIR).is_dir() and Path(DOWNLOAD_DIR).mkdir()
if not Path(DOWNLOAD_DIR + "/" + DEBIAN_IMAGE).is_file() and \
not Path(DOWNLOAD_DIR + "/" + DEBIAN_MANIFEST).is_file() and \
not Path(DOWNLOAD_DIR + "/" + DEBIAN_MANIFEST_SIGN).is_file():
print("Downloading files from Debian website to local directory '" + DOWNLOAD_DIR + "'...")
if not Path(DOWNLOAD_DIR + "/" + DEBIAN_MANIFEST_SIGN).is_file():
print("-", DEBIAN_MANIFEST_SIGN)
with urllib.request.urlopen(DEBIAN_DOWNLOAD + "/" + DEBIAN_MANIFEST_SIGN, context=client_context) as response, \
open(DOWNLOAD_DIR + "/" + DEBIAN_MANIFEST_SIGN, 'wb') as out_file:
shutil.copyfileobj(response, out_file)
if not Path(DOWNLOAD_DIR + "/" + DEBIAN_MANIFEST).is_file():
print("-", DEBIAN_MANIFEST)
with urllib.request.urlopen(DEBIAN_DOWNLOAD + "/" + DEBIAN_MANIFEST, context=client_context) as response, \
open(DOWNLOAD_DIR + "/" + DEBIAN_MANIFEST, 'wb') as out_file:
shutil.copyfileobj(response, out_file)
if not Path(DOWNLOAD_DIR + "/" + DEBIAN_IMAGE).is_file():
print("-", DEBIAN_IMAGE)
with urllib.request.urlopen(DEBIAN_DOWNLOAD + "/" + DEBIAN_IMAGE, context=client_context) as response, \
open(DOWNLOAD_DIR + "/" + DEBIAN_IMAGE, 'wb') as out_file:
shutil.copyfileobj(response, out_file)
else:
print("All files have already been copied to local directory '" + DOWNLOAD_DIR + "'.")
print("-", DEBIAN_IMAGE)
print("-", DEBIAN_MANIFEST)
print("-", DEBIAN_MANIFEST_SIGN)
print("\nVerifying digital signature and hashes...\n")
v = open(DOWNLOAD_DIR + "/" + DEBIAN_MANIFEST_SIGN, "rb")
verify_result = gpg.verify_file(v, DOWNLOAD_DIR + "/" + DEBIAN_MANIFEST)
v.close()
if verify_result.status == "signature valid":
hasher = hashlib.sha256()
with open(DOWNLOAD_DIR + "/" + DEBIAN_IMAGE, 'rb') as hf:
buf = hf.read(HASH_BLOCKSIZE)
while len(buf) > 0:
hasher.update(buf)
buf = hf.read(HASH_BLOCKSIZE)
DIGEST = hasher.hexdigest()
hash_found = False
file = open(DOWNLOAD_DIR + "/" + DEBIAN_MANIFEST, "r")
for line in file:
if re.search(DIGEST, line):
hash_found = True
file.close()
if hash_found:
print("[ SUCCESS ] GPG signature for", DEBIAN_MANIFEST, "successfully verified.")
print("[ SUCCESS ] SHA-256 hash of", DEBIAN_IMAGE, "successfully verified.\n")
# The script won't delete files.
print("It's now safe to delete files", DEBIAN_MANIFEST, "and", DEBIAN_MANIFEST_SIGN, "\n")
print("RESULT: SUCCESS. It means that", DEBIAN_IMAGE, "wasn't modified after its creation")
print("and that the file", DEBIAN_MANIFEST, "that contains the proof was signed by Debian signing private key.")
print("Learn more at https://stakey.club/en/verifying-digital-signatures/\n")
# The script won't do anything to the downloaded image.
print("To use the image:")
print("1. burn", DEBIAN_IMAGE, "to a", MEDIA + "; or")
print("2. use it to boot a virtual machine")
else:
print("[ SUCCESS ] GPG signature for", DEBIAN_IMAGE, "successfully verified.")
print("[ FAIL ] SHA-256 hash of", DEBIAN_IMAGE, "verification FAILED!\n")
print("RESULT: FAIL. It means that the manifest wasn't modified after its creation")
print("but", DEBIAN_IMAGE, "is incomplete or was probably modified after its creation.")
exit(3)
else:
print("[ FAIL ] GPG did not find a \"good signature\" for", DEBIAN_IMAGE + ". Verification FAILED!")
exit(4)