From afe1f86e1c84cb86befdf1b251c3a7159e78db8c Mon Sep 17 00:00:00 2001 From: Artemis Tosini Date: Mon, 8 Jul 2024 03:25:13 +0000 Subject: [PATCH] nardl: fix hashing --- rust/nardl/Cargo.lock | 15 ++++++++++++++- rust/nardl/Cargo.toml | 3 ++- rust/nardl/src/main.rs | 40 ++++++++++++++++++++++++++++------------ 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/rust/nardl/Cargo.lock b/rust/nardl/Cargo.lock index 2fabfed..e5caa93 100644 --- a/rust/nardl/Cargo.lock +++ b/rust/nardl/Cargo.lock @@ -367,6 +367,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + [[package]] name = "der" version = "0.7.9" @@ -879,12 +885,13 @@ version = "0.1.0" dependencies = [ "async-compression", "async-tempfile", - "base64", "color-eyre", + "data-encoding", "ed25519-dalek", "env_logger", "log", "narinfo", + "nix-base32", "nix-nar", "reqwest", "sha2", @@ -902,6 +909,12 @@ dependencies = [ "derive_builder", ] +[[package]] +name = "nix-base32" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8548db8274cf1b2b4c093557783f99e9ad64ffdaaa29a6c1af0abc9895c15612" + [[package]] name = "nix-nar" version = "0.3.0" diff --git a/rust/nardl/Cargo.toml b/rust/nardl/Cargo.toml index 925ea57..ba993c3 100644 --- a/rust/nardl/Cargo.toml +++ b/rust/nardl/Cargo.toml @@ -6,12 +6,13 @@ edition = "2021" [dependencies] async-compression = { version = "0.4.11", features = [ "tokio", "xz", "bzip2", "zstd", "brotli" ] } async-tempfile = "0.6.0" -base64 = "0.22.1" color-eyre = "0.6" +data-encoding = "2.6.0" ed25519-dalek = "2.1.1" env_logger = "0.11" log = "0.4" narinfo = "1.0.1" +nix-base32 = "0.1.1" nix-nar = "0.3.0" reqwest = { version = "0.12.5", features = ["http2", "stream", "rustls-tls", "zstd"], default-features = false } sha2 = "0.10.8" diff --git a/rust/nardl/src/main.rs b/rust/nardl/src/main.rs index cf45724..95ca93d 100644 --- a/rust/nardl/src/main.rs +++ b/rust/nardl/src/main.rs @@ -1,15 +1,10 @@ #![allow(dead_code)] -use base64::{ - engine::general_purpose::{ - STANDARD as BASE64_STANDARD, STANDARD_NO_PAD as BASE64_STANDARD_NO_PAD, - }, - Engine, -}; use color_eyre::eyre::{self, Context, OptionExt}; use ed25519_dalek::{Signature, VerifyingKey}; use sha2::Digest; use std::{ collections::{HashMap, HashSet}, + os::unix::fs::MetadataExt, path::Path, pin::Pin, }; @@ -58,8 +53,8 @@ async fn main() -> eyre::Result<()> { .iter() .map(|key| -> eyre::Result<_> { let (name, public_str) = key.split_once(":").ok_or_eyre("Key has no name")?; - let public_bytes = BASE64_STANDARD_NO_PAD - .decode(public_str.trim_end_matches("=")) + let public_bytes = data_encoding::BASE64_NOPAD + .decode(public_str.trim_end_matches("=").as_bytes()) .wrap_err("Invalid base64 in key")?; Ok(( name, @@ -166,12 +161,30 @@ async fn main() -> eyre::Result<()> { .write(true) .truncate(true) .create(true) - .open(temp_dir.as_ref().join("temp.nar")) + .open(temp_dir.join("temp.nar")) .await?; tokio::io::copy(&mut decompressed_stream, &mut out_file).await?; out_file.seek(std::io::SeekFrom::Start(0)).await?; + // Verify nar + let found_size = out_file.metadata().await?.size(); + if found_size != narinfo_parsed.nar_size as u64 { + eyre::bail!("Wrong nar size for {}", output); + } + + let (hash_algorithm, hash_expected) = narinfo_parsed + .nar_hash + .as_ref() + .split_once(":") + .ok_or_eyre("Invalid hash in nar")?; + + if hash_algorithm != "sha256" { + eyre::bail!("who is using hashes other than sha256????"); + } + + log::trace!("expected hash: {}", hash_expected); + let mut buf = [0u8; 1024]; let mut hasher = sha2::Sha256::new(); loop { @@ -182,8 +195,11 @@ async fn main() -> eyre::Result<()> { hasher.update(&buf[0..num_read]); } - let found_hash = hasher.finalize(); - log::trace!("Got hash {:?}", found_hash); + let hash_found = hasher.finalize(); + + if &nix_base32::to_nix_base32(hash_found.as_ref()) != hash_expected { + eyre::bail!("Incorrect hash when downloading {}", output) + } } Ok(()) @@ -226,7 +242,7 @@ fn verify_signature( let Some(key) = trusted_keys.get(sig_info.key_name.as_ref()) else { continue; }; - let signature_bytes = BASE64_STANDARD.decode(sig_info.sig.as_ref())?; + let signature_bytes = data_encoding::BASE64.decode(sig_info.sig.as_ref().as_bytes())?; let signature = Signature::from_bytes( signature_bytes