mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 23:09:44 -04:00
contrib: Add verifybinaries command for specifying files to verify
In addition to verifying the published releases with the `pub` command, the verifybinaries script is updated to take a `bin` command where the user specifies the local files, sums, and sigs to verify.
This commit is contained in:
parent
e4d5778228
commit
6b2cebfa2f
1 changed files with 79 additions and 3 deletions
|
@ -42,7 +42,7 @@ import textwrap
|
||||||
import urllib.request
|
import urllib.request
|
||||||
import enum
|
import enum
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
from pathlib import Path
|
from pathlib import PurePath
|
||||||
|
|
||||||
# The primary host; this will fail if we can't retrieve files from here.
|
# The primary host; this will fail if we can't retrieve files from here.
|
||||||
HOST1 = "https://bitcoincore.org"
|
HOST1 = "https://bitcoincore.org"
|
||||||
|
@ -440,11 +440,11 @@ def verify_shasums_signature(
|
||||||
return (ReturnCode.SUCCESS, good_trusted, good_untrusted, unknown, bad)
|
return (ReturnCode.SUCCESS, good_trusted, good_untrusted, unknown, bad)
|
||||||
|
|
||||||
|
|
||||||
def parse_sums_file(sums_file_path: Path, filename_filter: str) -> t.List[t.List[str]]:
|
def parse_sums_file(sums_file_path: str, filename_filter: t.List[str]) -> t.List[t.List[str]]:
|
||||||
# extract hashes/filenames of binaries to verify from hash file;
|
# extract hashes/filenames of binaries to verify from hash file;
|
||||||
# each line has the following format: "<hash> <binary_filename>"
|
# each line has the following format: "<hash> <binary_filename>"
|
||||||
with open(sums_file_path, 'r', encoding='utf8') as hash_file:
|
with open(sums_file_path, 'r', encoding='utf8') as hash_file:
|
||||||
return [line.split()[:2] for line in hash_file if filename_filter in line]
|
return [line.split()[:2] for line in hash_file if len(filename_filter) == 0 or any(f in line for f in filename_filter)]
|
||||||
|
|
||||||
|
|
||||||
def verify_binary_hashes(hashes_to_verify: t.List[t.List[str]]) -> t.Tuple[ReturnCode, t.Dict[str, str]]:
|
def verify_binary_hashes(hashes_to_verify: t.List[t.List[str]]) -> t.Tuple[ReturnCode, t.Dict[str, str]]:
|
||||||
|
@ -579,6 +579,73 @@ def verify_published_handler(args: argparse.Namespace) -> ReturnCode:
|
||||||
return ReturnCode.SUCCESS
|
return ReturnCode.SUCCESS
|
||||||
|
|
||||||
|
|
||||||
|
def verify_binaries_handler(args: argparse.Namespace) -> ReturnCode:
|
||||||
|
binary_to_basename = {}
|
||||||
|
for file in args.binary:
|
||||||
|
binary_to_basename[PurePath(file).name] = file
|
||||||
|
|
||||||
|
sums_sig_path = None
|
||||||
|
if args.sums_sig_file:
|
||||||
|
sums_sig_path = Path(args.sums_sig_file)
|
||||||
|
else:
|
||||||
|
log.info(f"No signature file specified, assuming it is {args.sums_file}.asc")
|
||||||
|
sums_sig_path = Path(args.sums_file).with_suffix(".asc")
|
||||||
|
|
||||||
|
# Verify the signature on the SHA256SUMS file
|
||||||
|
sigs_status, good_trusted, good_untrusted, unknown, bad = verify_shasums_signature(sums_sig_path, args.sums_file, args)
|
||||||
|
if sigs_status != ReturnCode.SUCCESS:
|
||||||
|
return sigs_status
|
||||||
|
|
||||||
|
# Extract hashes and filenames
|
||||||
|
hashes_to_verify = parse_sums_file(args.sums_file, [k for k, n in binary_to_basename.items()])
|
||||||
|
if not hashes_to_verify:
|
||||||
|
log.error(f"No files in {args.sums_file} match the specified binaries")
|
||||||
|
return ReturnCode.NO_BINARIES_MATCH
|
||||||
|
|
||||||
|
# Make sure all files are accounted for
|
||||||
|
sums_file_path = Path(args.sums_file)
|
||||||
|
missing_files = []
|
||||||
|
files_to_hash = []
|
||||||
|
if len(binary_to_basename) > 0:
|
||||||
|
for file_hash, file in hashes_to_verify:
|
||||||
|
files_to_hash.append([file_hash, binary_to_basename[file]])
|
||||||
|
del binary_to_basename[file]
|
||||||
|
if len(binary_to_basename) > 0:
|
||||||
|
log.error(f"Not all specified binaries are in {args.sums_file}")
|
||||||
|
return ReturnCode.NO_BINARIES_MATCH
|
||||||
|
else:
|
||||||
|
log.info(f"No binaries specified, assuming all files specified in {args.sums_file} are located relatively")
|
||||||
|
for file_hash, file in hashes_to_verify:
|
||||||
|
file_path = Path(sums_file_path.parent.joinpath(file))
|
||||||
|
if file_path.exists():
|
||||||
|
files_to_hash.append([file_hash, str(file_path)])
|
||||||
|
else:
|
||||||
|
missing_files.append(file)
|
||||||
|
|
||||||
|
# verify hashes
|
||||||
|
hashes_status, files_to_hashes = verify_binary_hashes(files_to_hash)
|
||||||
|
if hashes_status != ReturnCode.SUCCESS:
|
||||||
|
return hashes_status
|
||||||
|
|
||||||
|
if args.json:
|
||||||
|
output = {
|
||||||
|
'good_trusted_sigs': [str(s) for s in good_trusted],
|
||||||
|
'good_untrusted_sigs': [str(s) for s in good_untrusted],
|
||||||
|
'unknown_sigs': [str(s) for s in unknown],
|
||||||
|
'bad_sigs': [str(s) for s in bad],
|
||||||
|
'verified_binaries': files_to_hashes,
|
||||||
|
"missing_binaries": missing_files,
|
||||||
|
}
|
||||||
|
print(json.dumps(output, indent=2))
|
||||||
|
else:
|
||||||
|
for filename in files_to_hashes:
|
||||||
|
print(f"VERIFIED: {filename}")
|
||||||
|
for filename in missing_files:
|
||||||
|
print(f"MISSING: {filename}")
|
||||||
|
|
||||||
|
return ReturnCode.SUCCESS
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description=__doc__)
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
|
@ -638,6 +705,15 @@ def main():
|
||||||
'(Sometimes bitcoin.org lags behind bitcoincore.org.)')
|
'(Sometimes bitcoin.org lags behind bitcoincore.org.)')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
bin_parser = subparsers.add_parser("bin", help="Verify local binaries.")
|
||||||
|
bin_parser.set_defaults(func=verify_binaries_handler)
|
||||||
|
bin_parser.add_argument("--sums-sig-file", "-s", help="Path to the SHA256SUMS.asc file to verify")
|
||||||
|
bin_parser.add_argument("sums_file", help="Path to the SHA256SUMS file to verify")
|
||||||
|
bin_parser.add_argument(
|
||||||
|
"binary", nargs="*",
|
||||||
|
help="Path to a binary distribution file to verify. Can be specified multiple times for multiple files to verify."
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
if args.quiet:
|
if args.quiet:
|
||||||
log.setLevel(logging.WARNING)
|
log.setLevel(logging.WARNING)
|
||||||
|
|
Loading…
Add table
Reference in a new issue