hexz_cli/cmd/sys/verify.rs
1//! Verify Ed25519 signatures on Hexz archives.
2//!
3//! This module implements the `verify` command, which validates the cryptographic
4//! signature on a signed Hexz archive to ensure authenticity and integrity.
5//!
6//! # Verification Process
7//!
8//! The verification operation follows these steps:
9//!
10//! 1. **Load Header**: Read archive header and extract signature metadata
11//! 2. **Check Signature Exists**: Verify the archive has been signed
12//! 3. **Read Signature**: Load the 64-byte Ed25519 signature from the archive
13//! 4. **Read Master Index**: Read the index structure that was signed
14//! 5. **Compute Digest**: Calculate SHA-256 hash of the index
15//! 6. **Verify Signature**: Validate Ed25519 signature using public key
16//!
17//! # What Gets Verified
18//!
19//! The signature verification checks:
20//! - The **Master Index** has not been modified since signing
21//! - The signature was created by the holder of the corresponding private key
22//! - The signature is mathematically valid (correct Ed25519 signature)
23//!
24//! # Security Guarantees
25//!
26//! A valid signature proves:
27//! - **Authenticity**: Archive was signed by holder of the private key
28//! - **Integrity**: Index structure has not been tampered with
29//! - **Trust**: If you trust the public key, you can trust the archive
30//!
31//! # Limitations
32//!
33//! Signature verification does NOT protect against:
34//! - **Replay attacks**: Old valid archives can be replayed
35//! - **Data block modification**: Individual blocks could be swapped if hashes collide
36//! - **Header manipulation**: Some header fields are mutable (e.g., signature metadata)
37//!
38//! # Usage
39//!
40//! ```bash
41//! # Verify an archive signature
42//! hexz sys verify --key ~/.hexz/keys/public.key snapshot.st
43//!
44//! # On success
45//! # => Signature Verified! The image index is authentic.
46//!
47//! # On failure
48//! # => Error: Signature verification failed
49//! ```
50//!
51//! # Exit Codes
52//!
53//! - **0**: Signature is valid
54//! - **Non-zero**: Verification failed (invalid signature or archive not signed)
55
56use anyhow::Result;
57use hexz_core::ops::sign::verify_snapshot;
58use std::path::PathBuf;
59
60/// Verify the Ed25519 signature on a signed Hexz archive.
61///
62/// This function validates that the archive's Master Index has not been modified
63/// since it was signed, and that the signature was created by the holder of the
64/// corresponding private key.
65///
66/// # Arguments
67///
68/// * `key_path` - Path to the Ed25519 public key file (32 bytes)
69/// * `image_path` - Path to the signed Hexz archive file
70///
71/// # Process
72///
73/// 1. Opens the archive and reads the header
74/// 2. Checks that signature metadata exists in header
75/// 3. Reads the 64-byte signature from the file
76/// 4. Reads the Master Index (from header.index_offset to signature offset)
77/// 5. Computes SHA-256 digest of the index
78/// 6. Verifies the Ed25519 signature against the digest
79///
80/// # Returns
81///
82/// Returns `Ok(())` if signature is valid, or an error if:
83/// - Archive is not signed (missing signature metadata)
84/// - Public key file cannot be read
85/// - Archive file is malformed
86/// - Signature length is invalid (not 64 bytes)
87/// - Signature verification fails (tampered index or wrong key)
88///
89/// # Example
90///
91/// ```no_run
92/// # use std::path::PathBuf;
93/// # use hexz_cli::cmd::sys::verify;
94/// let key = PathBuf::from("~/.hexz/keys/public.key");
95/// let archive = PathBuf::from("snapshot.hxz");
96///
97/// match verify::run(key, archive) {
98/// Ok(()) => println!("✓ Signature valid"),
99/// Err(e) => eprintln!("✗ Verification failed: {}", e),
100/// }
101/// # Ok::<(), anyhow::Error>(())
102/// ```
103pub fn run(key_path: PathBuf, image_path: PathBuf) -> Result<()> {
104 println!("Verifying {:?} with key {:?}...", image_path, key_path);
105 verify_snapshot(&image_path, &key_path)?;
106 println!("Signature Verified! The image index is authentic.");
107 Ok(())
108}