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",
]
[[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"

View file

@ -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"

View file

@ -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