From 859e4261e04bb9bf1bf38cb336dddda8bad38227 Mon Sep 17 00:00:00 2001 From: Daniel Alley Date: Fri, 27 Oct 2023 21:42:53 -0400 Subject: [PATCH] Convert FileDigest to struct to simplify implementations --- src/constants.rs | 2 +- src/rpm/headers/header.rs | 53 ++++++++++++++++----------------------- src/rpm/headers/types.rs | 3 +-- src/rpm/package.rs | 2 +- src/tests.rs | 8 ++++-- 5 files changed, 31 insertions(+), 37 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 364efb3d..21098307 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -558,7 +558,7 @@ bitflags! { // should be equivalent the value mapping used by `pgp::crypto::hash::HashAlgorithm` // but we have to copy it as not everyone uses the `signature` feature #[repr(u32)] -#[derive(Debug, Clone, Copy, enum_primitive_derive::Primitive)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, enum_primitive_derive::Primitive)] pub enum DigestAlgorithm { Md5 = 1, Sha2_256 = 8, diff --git a/src/rpm/headers/header.rs b/src/rpm/headers/header.rs index 4ac28c75..2be1df87 100644 --- a/src/rpm/headers/header.rs +++ b/src/rpm/headers/header.rs @@ -383,56 +383,47 @@ pub struct FileOwnership { } #[derive(Debug, Clone, Hash, Eq, PartialEq)] -pub enum FileDigest { - Md5(Vec), - Sha2_224(Vec), - Sha2_256(Vec), - Sha2_384(Vec), - Sha2_512(Vec), - // @todo unsupported other types for now +pub struct FileDigest { + digest: String, + algo: DigestAlgorithm, } impl FileDigest { - pub fn load_from_str( + pub(crate) fn new( algorithm: DigestAlgorithm, - stringly_data: impl AsRef, + hex_digest: impl Into, ) -> Result { - let hex: Vec = hex::decode(stringly_data.as_ref())?; + let hex = hex_digest.into(); + let digest = FileDigest { + digest: hex, + algo: algorithm, + }; + Ok(match algorithm { - DigestAlgorithm::Md5 if hex.len() == 16 => FileDigest::Md5(hex), - DigestAlgorithm::Sha2_256 if hex.len() == 32 => FileDigest::Sha2_256(hex), - DigestAlgorithm::Sha2_224 if hex.len() == 30 => FileDigest::Sha2_224(hex), - DigestAlgorithm::Sha2_384 if hex.len() == 48 => FileDigest::Sha2_384(hex), - DigestAlgorithm::Sha2_512 if hex.len() == 64 => FileDigest::Sha2_512(hex), + DigestAlgorithm::Md5 if digest.digest.len() == 32 => digest, + DigestAlgorithm::Sha2_256 if digest.digest.len() == 64 => digest, + DigestAlgorithm::Sha2_224 if digest.digest.len() == 60 => digest, + DigestAlgorithm::Sha2_384 if digest.digest.len() == 96 => digest, + DigestAlgorithm::Sha2_512 if digest.digest.len() == 128 => digest, // @todo disambiguate mismatch of length from unsupported algorithm digest_algo => return Err(Error::UnsupportedDigestAlgorithm(digest_algo)), }) } + /// Return the algorithm that was used for this digest. pub fn algorithm(&self) -> DigestAlgorithm { - match self { - Self::Md5(_) => DigestAlgorithm::Md5, - Self::Sha2_224(_) => DigestAlgorithm::Sha2_224, - Self::Sha2_256(_) => DigestAlgorithm::Sha2_256, - Self::Sha2_384(_) => DigestAlgorithm::Sha2_384, - Self::Sha2_512(_) => DigestAlgorithm::Sha2_512, - } + self.algo } - pub fn as_hex(&self) -> String { - match self { - Self::Md5(d) => hex::encode(d), - Self::Sha2_224(d) => hex::encode(d), - Self::Sha2_256(d) => hex::encode(d), - Self::Sha2_384(d) => hex::encode(d), - Self::Sha2_512(d) => hex::encode(d), - } + /// Return the digest + pub fn as_hex(&self) -> &str { + self.digest.as_str() } } impl Display for FileDigest { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&self.as_hex()) + f.write_str(self.as_hex()) } } diff --git a/src/rpm/headers/types.rs b/src/rpm/headers/types.rs index 4849af36..7c20b870 100644 --- a/src/rpm/headers/types.rs +++ b/src/rpm/headers/types.rs @@ -1,9 +1,8 @@ //! A collection of types used in various header records. -use std::str::FromStr; - use crate::{constants::*, errors, Timestamp}; use capctl::FileCaps; use digest::Digest; +use std::str::FromStr; /// Offsets into an RPM Package (from the start of the file) demarking locations of each section /// diff --git a/src/rpm/package.rs b/src/rpm/package.rs index 21c9642f..3ec7a677 100644 --- a/src/rpm/package.rs +++ b/src/rpm/package.rs @@ -895,7 +895,7 @@ impl PackageMetadata { let digest = if digest.is_empty() { None } else { - Some(FileDigest::load_from_str(algorithm, digest)?) + Some(FileDigest::new(algorithm, digest)?) }; let cap = match caps { Some(caps) => caps.get(idx).map(|x| x.to_owned()), diff --git a/src/tests.rs b/src/tests.rs index 4cc3ff43..6da8b8f7 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -303,8 +303,12 @@ fn test_rpm_header() -> Result<(), Box> { let checksums: Vec<_> = metadata .get_file_entries()? .iter() - .map(|e| e.digest.as_ref().map(|d| d.to_string())) - .map(|d| d.unwrap_or("".to_owned())) + .map(|e| { + e.digest + .as_ref() + .map(|d| d.to_string()) + .unwrap_or("".to_owned()) + }) .collect(); assert_eq!(expected_file_checksums, checksums);