Skip to content

Commit

Permalink
fix: using base_path to preserve relative inner folders in signature …
Browse files Browse the repository at this point in the history
…manifest
  • Loading branch information
evilsocket committed Oct 30, 2024
1 parent 40e2a70 commit cd11ab0
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 34 deletions.
19 changes: 15 additions & 4 deletions src/cli/signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,15 @@ fn signature_path(file_path: &Path, signature_path: Option<PathBuf>) -> PathBuf
pub(crate) fn sign(args: SignArgs) -> anyhow::Result<()> {
// load the private key for signing
let signing_key = crate::core::signing::load_key(&args.key_path)?;
// create the manifest
let mut manifest = Manifest::from_signing_key(signing_key);
// get the paths to sign
let mut paths_to_sign = get_paths_of_interest(args.format, &args.file_path)?;
let base_path = if args.file_path.is_file() {
args.file_path.parent().unwrap().to_path_buf()
} else {
args.file_path.to_path_buf()
};
// create the manifest
let mut manifest = Manifest::from_signing_key(&base_path, signing_key)?;

// sign
let signature = manifest.sign(&mut paths_to_sign)?;
Expand All @@ -95,15 +100,21 @@ pub(crate) fn sign(args: SignArgs) -> anyhow::Result<()> {
}

pub(crate) fn verify(args: VerifyArgs) -> anyhow::Result<()> {
let base_path = if args.file_path.is_file() {
args.file_path.parent().unwrap().to_path_buf()
} else {
args.file_path.to_path_buf()
};

// load signature file to verify
let signature_path = signature_path(&args.file_path, args.signature);

println!("Verifying signature: {}", signature_path.display());

let signature = Manifest::from_signature_path(&signature_path)?;
let signature = Manifest::from_signature_path(&base_path, &signature_path)?;

// load the public key to verify against
let mut manifest = Manifest::from_public_key_path(&args.key_path)?;
let mut manifest = Manifest::from_public_key_path(&base_path, &args.key_path)?;
// get the paths to verify
let mut paths_to_verify = get_paths_of_interest(args.format, &args.file_path)?;

Expand Down
123 changes: 93 additions & 30 deletions src/core/signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,24 +77,31 @@ pub(crate) struct Manifest {
// hex-encoded signature of the checksums
pub(crate) signature: String,

#[serde(skip_serializing, skip_deserializing)]
base_path: PathBuf,
#[serde(skip_serializing, skip_deserializing)]
signing_key: Option<signature::Ed25519KeyPair>,
#[serde(skip_serializing, skip_deserializing)]
verifying_key: Option<UnparsedPublicKey<Vec<u8>>>,
}

impl Manifest {
pub(crate) fn from_signature_path(path: &Path) -> anyhow::Result<Self> {
Ok(serde_json::from_str(&std::fs::read_to_string(path)?)?)
pub(crate) fn from_signature_path(base_path: &Path, path: &Path) -> anyhow::Result<Self> {
let mut this: Manifest = serde_json::from_str(&std::fs::read_to_string(path)?)?;
this.base_path = base_path.canonicalize()?;
Ok(this)
}

pub(crate) fn from_signing_key(signing_key: signature::Ed25519KeyPair) -> Self {
pub(crate) fn from_signing_key(
base_path: &Path,
signing_key: signature::Ed25519KeyPair,
) -> anyhow::Result<Self> {
let public_key = signing_key.public_key();
let mut hasher = Blake2b512::new();
hasher.update(public_key.as_ref());
let hash = hasher.finalize();

Self {
Ok(Self {
version: Version::V1,
signed_at: chrono::Utc::now().to_rfc3339(),
signed_with: format!("tensor-man v{}", env!("CARGO_PKG_VERSION")),
Expand All @@ -108,10 +115,14 @@ impl Manifest {
signature: String::new(),
signing_key: Some(signing_key),
verifying_key: None,
}
base_path: base_path.canonicalize()?,
})
}

pub(crate) fn from_public_key(public_key_bytes: Vec<u8>) -> anyhow::Result<Self> {
pub(crate) fn from_public_key(
base_path: &Path,
public_key_bytes: Vec<u8>,
) -> anyhow::Result<Self> {
let public_key = UnparsedPublicKey::new(&ED25519, public_key_bytes);
let mut hasher = Blake2b512::new();
hasher.update(public_key.as_ref());
Expand All @@ -131,12 +142,16 @@ impl Manifest {
signature: String::new(),
signing_key: None,
verifying_key: Some(public_key),
base_path: base_path.canonicalize()?,
})
}

pub(crate) fn from_public_key_path(public_key: &Path) -> anyhow::Result<Self> {
pub(crate) fn from_public_key_path(
base_path: &Path,
public_key: &Path,
) -> anyhow::Result<Self> {
let public_key_bytes = std::fs::read(public_key)?;
Self::from_public_key(public_key_bytes)
Self::from_public_key(base_path, public_key_bytes)
}

fn compute_checksum(&mut self, path: &Path) -> anyhow::Result<()> {
Expand All @@ -145,8 +160,10 @@ impl Manifest {

// let start = Instant::now();

let path = path.canonicalize()?;

let mut hasher = Blake2b512::new();
let mut file = std::fs::File::open(path)?;
let mut file = std::fs::File::open(&path)?;
let _ = std::io::copy(&mut file, &mut hasher)?;
let hash_bytes = hasher.finalize();
let hash = hex::encode(hash_bytes);
Expand All @@ -159,8 +176,20 @@ impl Manifest {
start.elapsed()
); */

if let Err(e) = path.strip_prefix(&self.base_path) {
panic!(
"base_path={} path={} error={}",
self.base_path.display(),
path.display(),
e
);
}

self.checksums.insert(
path.file_name().unwrap().to_string_lossy().to_string(),
path.strip_prefix(&self.base_path)
.unwrap()
.to_string_lossy()
.to_string(),
hash,
);
Ok(())
Expand Down Expand Up @@ -278,10 +307,13 @@ mod tests {
#[test]
fn test_will_create_a_signature() {
let keypair = create_test_keypair();
let mut manifest = Manifest::from_signing_key(keypair);

let temp_file = create_temp_file_with_content("test").unwrap();

let base_path = temp_file.path().parent().unwrap();

let mut manifest = Manifest::from_signing_key(&base_path, keypair).unwrap();

manifest.compute_checksum(&temp_file.path()).unwrap();
let signature = manifest.create_signature().unwrap();

Expand All @@ -308,16 +340,16 @@ mod tests {
fn test_will_verify_correct_signature() {
let keypair = create_test_keypair();
let pub_key = keypair.public_key().as_ref().to_vec();

let mut ref_manifest = Manifest::from_signing_key(keypair);

let temp_file = create_temp_file_with_content("test").unwrap();
let base_path = temp_file.path().parent().unwrap();

let mut ref_manifest = Manifest::from_signing_key(&base_path, keypair).unwrap();

let mut paths = vec![temp_file.path().to_path_buf()];

_ = ref_manifest.sign(&mut paths).unwrap();

let mut manifest = Manifest::from_public_key(pub_key).unwrap();
let mut manifest = Manifest::from_public_key(&base_path, pub_key).unwrap();

manifest.verify(&mut paths, &ref_manifest).unwrap();
}
Expand All @@ -327,16 +359,17 @@ mod tests {
let keypair = create_test_keypair();
let other_keypair = create_test_keypair();
let pub_key = other_keypair.public_key().as_ref().to_vec();
let temp_file = create_temp_file_with_content("test").unwrap();
let base_path = temp_file.path().parent().unwrap();

let mut ref_manifest = Manifest::from_signing_key(keypair);
let mut ref_manifest = Manifest::from_signing_key(&base_path, keypair).unwrap();

let temp_file = create_temp_file_with_content("test").unwrap();
let mut paths = vec![temp_file.path().to_path_buf()];

ref_manifest.compute_checksum(&temp_file.path()).unwrap();
ref_manifest.create_signature().unwrap();

let mut manifest = Manifest::from_public_key(pub_key).unwrap();
let mut manifest = Manifest::from_public_key(&base_path, pub_key).unwrap();

manifest.compute_checksum(&temp_file.path()).unwrap();

Expand All @@ -348,15 +381,17 @@ mod tests {
let keypair = create_test_keypair();
let pub_key = keypair.public_key().as_ref().to_vec();

let mut ref_manifest = Manifest::from_signing_key(keypair);

let temp_file = create_temp_file_with_content("test").unwrap();
let base_path = temp_file.path().parent().unwrap();

let mut ref_manifest = Manifest::from_signing_key(&base_path, keypair).unwrap();

let mut paths = vec![temp_file.path().to_path_buf()];

ref_manifest.compute_checksum(&temp_file.path()).unwrap();
ref_manifest.create_signature().unwrap();

let mut manifest = Manifest::from_public_key(pub_key).unwrap();
let mut manifest = Manifest::from_public_key(&base_path, pub_key).unwrap();

let temp_file = create_temp_file_with_content("tost").unwrap();

Expand All @@ -370,15 +405,17 @@ mod tests {
let keypair = create_test_keypair();
let pub_key = keypair.public_key().as_ref().to_vec();

let mut ref_manifest = Manifest::from_signing_key(keypair);

let temp_file = create_temp_file_with_content("test").unwrap();
let base_path = temp_file.path().parent().unwrap();

let mut ref_manifest = Manifest::from_signing_key(&base_path, keypair).unwrap();

let mut paths = vec![temp_file.path().to_path_buf()];

ref_manifest.compute_checksum(&temp_file.path()).unwrap();
ref_manifest.create_signature().unwrap();

let mut manifest = Manifest::from_public_key(pub_key).unwrap();
let mut manifest = Manifest::from_public_key(&base_path, pub_key).unwrap();

let empty_file = create_temp_file_with_content("").unwrap();
manifest.compute_checksum(&empty_file.path()).unwrap();
Expand All @@ -391,15 +428,17 @@ mod tests {
let keypair = create_test_keypair();
let pub_key = keypair.public_key().as_ref().to_vec();

let mut ref_manifest = Manifest::from_signing_key(keypair);

let temp_file = create_temp_file_with_content("test").unwrap();
let base_path = temp_file.path().parent().unwrap();

let mut ref_manifest = Manifest::from_signing_key(&base_path, keypair).unwrap();

let mut paths = vec![temp_file.path().to_path_buf()];

ref_manifest.compute_checksum(&temp_file.path()).unwrap();
ref_manifest.create_signature().unwrap();

let mut manifest = Manifest::from_public_key(pub_key).unwrap();
let mut manifest = Manifest::from_public_key(&base_path, pub_key).unwrap();

// Compute checksum for original file
manifest.compute_checksum(&temp_file.path()).unwrap();
Expand All @@ -416,17 +455,41 @@ mod tests {
let keypair = create_test_keypair();
let pub_key = keypair.public_key().as_ref().to_vec();

let mut ref_manifest = Manifest::from_signing_key(keypair);

let temp_file = create_temp_file_with_content("test").unwrap();
let base_path = temp_file.path().parent().unwrap();

let mut ref_manifest = Manifest::from_signing_key(&base_path, keypair).unwrap();

ref_manifest.compute_checksum(&temp_file.path()).unwrap();
// Deliberately skip creating signature

let mut manifest = Manifest::from_public_key(pub_key).unwrap();
let mut manifest = Manifest::from_public_key(&base_path, pub_key).unwrap();
manifest.compute_checksum(&temp_file.path()).unwrap();

let mut paths = vec![temp_file.path().to_path_buf()];

assert!(manifest.verify(&mut paths, &ref_manifest).is_err());
}

#[test]
fn test_inner_folder_name_preserved() {
let keypair = create_test_keypair();

// Create a temporary directory with a nested file structure
let temp_dir = tempfile::tempdir().unwrap();
let inner_dir = temp_dir.path().join("inner");
std::fs::create_dir(&inner_dir).unwrap();

let test_file = inner_dir.join("test.txt");
std::fs::write(&test_file, "test content").unwrap();

let base_path = temp_dir.path();

let mut manifest = Manifest::from_signing_key(&base_path, keypair).unwrap();

manifest.compute_checksum(&test_file).unwrap();

// Verify the checksum key preserves the inner folder name
assert!(manifest.checksums.contains_key("inner/test.txt"));
}
}

0 comments on commit cd11ab0

Please sign in to comment.