nardl: fix hashing

This commit is contained in:
Artemis Tosini 2024-07-08 03:25:13 +00:00
parent 25a01aad83
commit afe1f86e1c
Signed by: artemist
GPG key ID: EE5227935FE3FF18
3 changed files with 44 additions and 14 deletions

15
rust/nardl/Cargo.lock generated
View file

@ -367,6 +367,12 @@ dependencies = [
"syn 1.0.109", "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]] [[package]]
name = "der" name = "der"
version = "0.7.9" version = "0.7.9"
@ -879,12 +885,13 @@ version = "0.1.0"
dependencies = [ dependencies = [
"async-compression", "async-compression",
"async-tempfile", "async-tempfile",
"base64",
"color-eyre", "color-eyre",
"data-encoding",
"ed25519-dalek", "ed25519-dalek",
"env_logger", "env_logger",
"log", "log",
"narinfo", "narinfo",
"nix-base32",
"nix-nar", "nix-nar",
"reqwest", "reqwest",
"sha2", "sha2",
@ -902,6 +909,12 @@ dependencies = [
"derive_builder", "derive_builder",
] ]
[[package]]
name = "nix-base32"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8548db8274cf1b2b4c093557783f99e9ad64ffdaaa29a6c1af0abc9895c15612"
[[package]] [[package]]
name = "nix-nar" name = "nix-nar"
version = "0.3.0" version = "0.3.0"

View file

@ -6,12 +6,13 @@ edition = "2021"
[dependencies] [dependencies]
async-compression = { version = "0.4.11", features = [ "tokio", "xz", "bzip2", "zstd", "brotli" ] } async-compression = { version = "0.4.11", features = [ "tokio", "xz", "bzip2", "zstd", "brotli" ] }
async-tempfile = "0.6.0" async-tempfile = "0.6.0"
base64 = "0.22.1"
color-eyre = "0.6" color-eyre = "0.6"
data-encoding = "2.6.0"
ed25519-dalek = "2.1.1" ed25519-dalek = "2.1.1"
env_logger = "0.11" env_logger = "0.11"
log = "0.4" log = "0.4"
narinfo = "1.0.1" narinfo = "1.0.1"
nix-base32 = "0.1.1"
nix-nar = "0.3.0" nix-nar = "0.3.0"
reqwest = { version = "0.12.5", features = ["http2", "stream", "rustls-tls", "zstd"], default-features = false } reqwest = { version = "0.12.5", features = ["http2", "stream", "rustls-tls", "zstd"], default-features = false }
sha2 = "0.10.8" sha2 = "0.10.8"

View file

@ -1,15 +1,10 @@
#![allow(dead_code)] #![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 color_eyre::eyre::{self, Context, OptionExt};
use ed25519_dalek::{Signature, VerifyingKey}; use ed25519_dalek::{Signature, VerifyingKey};
use sha2::Digest; use sha2::Digest;
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
os::unix::fs::MetadataExt,
path::Path, path::Path,
pin::Pin, pin::Pin,
}; };
@ -58,8 +53,8 @@ async fn main() -> eyre::Result<()> {
.iter() .iter()
.map(|key| -> eyre::Result<_> { .map(|key| -> eyre::Result<_> {
let (name, public_str) = key.split_once(":").ok_or_eyre("Key has no name")?; let (name, public_str) = key.split_once(":").ok_or_eyre("Key has no name")?;
let public_bytes = BASE64_STANDARD_NO_PAD let public_bytes = data_encoding::BASE64_NOPAD
.decode(public_str.trim_end_matches("=")) .decode(public_str.trim_end_matches("=").as_bytes())
.wrap_err("Invalid base64 in key")?; .wrap_err("Invalid base64 in key")?;
Ok(( Ok((
name, name,
@ -166,12 +161,30 @@ async fn main() -> eyre::Result<()> {
.write(true) .write(true)
.truncate(true) .truncate(true)
.create(true) .create(true)
.open(temp_dir.as_ref().join("temp.nar")) .open(temp_dir.join("temp.nar"))
.await?; .await?;
tokio::io::copy(&mut decompressed_stream, &mut out_file).await?; tokio::io::copy(&mut decompressed_stream, &mut out_file).await?;
out_file.seek(std::io::SeekFrom::Start(0)).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 buf = [0u8; 1024];
let mut hasher = sha2::Sha256::new(); let mut hasher = sha2::Sha256::new();
loop { loop {
@ -182,8 +195,11 @@ async fn main() -> eyre::Result<()> {
hasher.update(&buf[0..num_read]); hasher.update(&buf[0..num_read]);
} }
let found_hash = hasher.finalize(); let hash_found = hasher.finalize();
log::trace!("Got hash {:?}", found_hash);
if &nix_base32::to_nix_base32(hash_found.as_ref()) != hash_expected {
eyre::bail!("Incorrect hash when downloading {}", output)
}
} }
Ok(()) Ok(())
@ -226,7 +242,7 @@ fn verify_signature(
let Some(key) = trusted_keys.get(sig_info.key_name.as_ref()) else { let Some(key) = trusted_keys.get(sig_info.key_name.as_ref()) else {
continue; 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( let signature = Signature::from_bytes(
signature_bytes signature_bytes