lib.rs

crates/veilvoice-verify/src/lib.rs

veilvoice-verify · 1918 lines · read the source here · or on GitHub

The portable verifier: check a VeilVoice release without GnuPG installed.

What this is for

Verifying a download by hand needs GnuPG and a SHA-256 tool. That is four commands and two dependencies, and on Windows it is usually neither. This is one binary that does the same checks with nothing else installed: the signing key and its fingerprint are compiled into it.

The one thing it cannot embed

It cannot carry the expected hash of the file it is checking. A file cannot contain its own digest -- writing the digest in changes the file, which changes the digest. So the hash has to come from outside, and there are exactly two places it can come from. They prove different things, and this tool is careful never to blur them:

From the published SHA256SUMS -- whose signature this tool checks against the embedded key. A match proves the download is intact: it is byte-for-byte the file that was published, not a corrupted or substituted one. It says nothing about whether that file corresponds to the source, because whoever published it produced both the file and the list.

Typed in by hand, from a hash somebody else produced by building the same tagged source themselves. A match proves something strictly stronger: that the published binary is what that source compiles to, on a machine that is not the publisher's. That is reproducibility, and it is the only check that does not ultimately rest on trusting whoever signed the release.

Most people want the first. The second is what makes the first worth anything, and it needs somebody other than the author to have done a build. docs/REPRODUCIBLE_BUILDS.md says how.

What it does not do

It does not download anything -- this project has no network code and this binary is not the exception. Fetch the files however you like; this reads them from disk. It does not install anything, and it writes nothing.

In plain words

This is the small program you can check a download with before trusting anything else here.

It is deliberately tiny and it is on its own: no window, no other pieces, and it does not need any other software installed -- not even the usual signature program. That matters because it is the first thing you run, and the point of it is to be small enough to be worth reading.

Double-click it and it looks for a downloaded release nearby and checks it. Give it arguments and it does exactly what you asked.

WHAT THIS FILE CONTAINS

1918 lines defining 34 functions (2 public), 1 type and 2 constants. Everything below is read out of the source, so it cannot disagree with the code.

The types it owns.

  • enum Manifest line 976 · What the release said is inside its archives, if anything usable.

What happens when it runs. These are the ways in: public, and nothing else in this file calls them, so they are what an outside caller reaches first.

  • help_text line 165 · The verifier's own help, with its verbosity and exit-status tables.
  • run line 1689 · Run the verifier over args, which are the words after veilvoice verify.
    reaches asked_for, command_auto, command_build, command_deps, command_file_against_hash, command_file_against_sums, command_gnupg, command_hash, command_install, command_key, command_release, command_reproduce

WHAT CALLS WHAT

embedded_key line 140 sha256_file line 151 verify_detached line 156 good line 333 fail line 344 deny line 360 incomplete_deny line 377 cannot line 395 usage line 415 read_text line 437 command_key line 446 command_sums line 469 command_file_against_sums line 512 command_file_against_hash line 608 command_hash line 664 take_value line 682 command_release line 698 command_auto line 779 report_extracted line 912 manifest line 992 report_against_manifest line 1023 run line 1689 entry: a way in: public, and nothing in this file calls it helper: private to this file dashed: a call that goes back up, or across a wrapped rank The functions this file defines, and the calls between them. An edge means the callee's name appears, called, inside the caller's body. This is a syntactic reading, not a type-resolved one. 22 of 34 functions are drawn; the diagram is bounded at 22 so it stays readable.

The functions this file defines, and the calls between them. An edge means the callee's name appears, called, inside the caller's body. This is a syntactic reading, not a type-resolved one. 22 of 34 functions are drawn; the diagram is bounded at 22 so it stays readable.

The same graph as Mermaid source
%%{init: {"theme":"base","themeVariables":{"background":"#1a1b26","primaryColor":"#1f2335","primaryTextColor":"#c0caf5","primaryBorderColor":"#7aa2f7","secondaryColor":"#16161e","tertiaryColor":"#16161e","lineColor":"#737aa2","textColor":"#c0caf5","mainBkg":"#1f2335","nodeBorder":"#7aa2f7","clusterBkg":"#16161e","clusterBorder":"#2f3549","fontFamily":"ui-monospace, SFMono-Regular, Consolas, monospace","fontSize":"14px"}}}%%
flowchart TD
    n_embedded_key["embedded_key<br/>line 140"]
    n_sha256_file["sha256_file<br/>line 151"]
    n_verify_detached["verify_detached<br/>line 156"]
    n_good["good<br/>line 333"]
    n_fail["fail<br/>line 344"]
    n_deny["deny<br/>line 360"]
    n_incomplete_deny["incomplete_deny<br/>line 377"]
    n_cannot["cannot<br/>line 395"]
    n_usage["usage<br/>line 415"]
    n_read_text["read_text<br/>line 437"]
    n_command_key["command_key<br/>line 446"]
    n_command_sums["command_sums<br/>line 469"]
    n_command_file_against_sums["command_file_against_sums<br/>line 512"]
    n_command_file_against_hash["command_file_against_hash<br/>line 608"]
    n_command_hash["command_hash<br/>line 664"]
    n_take_value["take_value<br/>line 682"]
    n_command_release["command_release<br/>line 698"]
    n_command_auto["command_auto<br/>line 779"]
    n_report_extracted["report_extracted<br/>line 912"]
    n_manifest["manifest<br/>line 992"]
    n_report_against_manifest["report_against_manifest<br/>line 1023"]
    n_run(["run<br/>line 1689"])
    n_command_auto --> n_command_file_against_sums
    n_command_auto --> n_incomplete_deny
    n_command_auto --> n_report_extracted
    n_command_file_against_hash --> n_cannot
    n_command_file_against_hash --> n_deny
    n_command_file_against_hash --> n_good
    n_command_file_against_hash --> n_sha256_file
    n_command_file_against_hash --> n_usage
    n_command_file_against_sums --> n_cannot
    n_command_file_against_sums --> n_deny
    n_command_file_against_sums --> n_embedded_key
    n_command_file_against_sums --> n_good
    n_command_file_against_sums --> n_read_text
    n_command_file_against_sums --> n_sha256_file
    n_command_file_against_sums --> n_verify_detached
    n_command_hash --> n_cannot
    n_command_hash --> n_sha256_file
    n_command_key --> n_deny
    n_command_key --> n_embedded_key
    n_command_release --> n_command_file_against_sums
    n_command_release --> n_command_sums
    n_command_release --> n_fail
    n_command_release --> n_usage
    n_command_sums --> n_cannot
    n_command_sums --> n_deny
    n_command_sums --> n_embedded_key
    n_command_sums --> n_good
    n_command_sums --> n_read_text
    n_command_sums --> n_verify_detached
    n_manifest --> n_read_text
    n_report_against_manifest --> n_good
    n_report_extracted --> n_manifest
    n_report_extracted --> n_report_against_manifest
    n_run --> n_command_auto
    n_run --> n_command_file_against_hash
    n_run --> n_command_file_against_sums
    n_run --> n_command_hash
    n_run --> n_command_key
    n_run --> n_command_release
    n_run --> n_command_sums
    n_run --> n_take_value
    n_run --> n_usage
    click n_embedded_key href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L140" "open the source"
    click n_sha256_file href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L151" "open the source"
    click n_verify_detached href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L156" "open the source"
    click n_good href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L333" "open the source"
    click n_fail href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L344" "open the source"
    click n_deny href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L360" "open the source"
    click n_incomplete_deny href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L377" "open the source"
    click n_cannot href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L395" "open the source"
    click n_usage href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L415" "open the source"
    click n_read_text href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L437" "open the source"
    click n_command_key href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L446" "open the source"
    click n_command_sums href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L469" "open the source"
    click n_command_file_against_sums href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L512" "open the source"
    click n_command_file_against_hash href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L608" "open the source"
    click n_command_hash href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L664" "open the source"
    click n_take_value href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L682" "open the source"
    click n_command_release href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L698" "open the source"
    click n_command_auto href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L779" "open the source"
    click n_report_extracted href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L912" "open the source"
    click n_manifest href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L992" "open the source"
    click n_report_against_manifest href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L1023" "open the source"
    click n_run href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-verify/src/lib.rs#L1689" "open the source"
    classDef entry fill:#1f2335,stroke:#7aa2f7,color:#c0caf5
    class n_run entry
    classDef helper fill:#1f2335,stroke:#bb9af7,color:#c0caf5
    class n_embedded_key,n_sha256_file,n_verify_detached,n_good,n_fail,n_deny,n_incomplete_deny,n_cannot,n_usage,n_read_text,n_command_key,n_command_sums,n_command_file_against_sums,n_command_file_against_hash,n_command_hash,n_take_value,n_command_release,n_command_auto,n_report_extracted,n_manifest,n_report_against_manifest helper

This site loads no third-party script, so it cannot run Mermaid; the diagram above is the same nodes and edges drawn by the generator instead. GitHub renders the source below directly.

ITEMS

ItemLineDocumentation
embedded_key fn140The embedded key, with its fingerprint checked against FINGERPRINT.
sha256_file fn151SHA-256 of a file, as this program's Result<_, String>.
verify_detached fn156Verify a detached signature, as this program's Result<_, String>.
help_text pub fn165The verifier's own help, with its verbosity and exit-status tables.
USAGE const169
EXPLAIN const285
good fn333One line of a passing check, in the shape every other line here uses.
fail fn344A failure that is not a refusal: something did not happen, rather than something was checked and found wrong.
deny fn360Every refusal goes through here, so every refusal names the check.
incomplete_deny fn377Nothing could be checked, with the same shape of detail as a refusal.
cannot fn395A file this program was told to read could not be read.
usage fn415The command line could not be understood, so nothing was attempted.
read_text fn437A file as text, with the path in the error rather than just the reason.
command_key fn446veilvoice verify key: what the key compiled into this binary is.
command_sums fn469veilvoice verify sums: the signature over a hash list, and nothing else.
command_file_against_sums fn512veilvoice verify file: the whole chain for one download.
command_file_against_hash fn608veilvoice verify file --sha256: one file against one hash typed by hand.
command_hash fn664veilvoice verify hash: print a file's SHA-256 and stop.
take_value fn682The value after a flag, or a message naming the flag that is missing one.
command_release fn698Fetch a release and check it, in one step.
command_auto fn779Find a release near the user and check it, with nothing else to type.
report_extracted fn912Roadmap item 97.
Manifest enum976What the release said is inside its archives, if anything usable.
manifest fn992Read CONTENTS.sha256, having first proved it is the published one.
report_against_manifest fn1023Check one extracted folder against the section of the list that covers it.
digest_for fn1097The published hash for one path, for a --verbose line.
report_runnable fn1112Whether the operating system will run the programs that are there.
report_presence_only fn1136The old report, for a release that published no contents list.
report_gnupg fn1179Roadmap item 97.
command_gnupg fn1264Roadmap item 91.
command_deps fn1309What this machine needs before it can build VeilVoice.
command_build fn1381Build the workspace from source and hash what came out.
do_build fn1399Everything both build commands do before they differ.
command_reproduce fn1468Build here, and compare against the published hashes for this platform.
command_install fn1577Put binaries where a shell will find them.
asked_for fn1666Print something the reader asked for by name, at any level.
run pub fn1689Run the verifier over args, which are the words after veilvoice verify.