Skip to content

Commit cd11ab0

Browse files
committed
fix: using base_path to preserve relative inner folders in signature manifest
1 parent 40e2a70 commit cd11ab0

File tree

2 files changed

+108
-34
lines changed

2 files changed

+108
-34
lines changed

src/cli/signing.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,15 @@ fn signature_path(file_path: &Path, signature_path: Option<PathBuf>) -> PathBuf
7575
pub(crate) fn sign(args: SignArgs) -> anyhow::Result<()> {
7676
// load the private key for signing
7777
let signing_key = crate::core::signing::load_key(&args.key_path)?;
78-
// create the manifest
79-
let mut manifest = Manifest::from_signing_key(signing_key);
8078
// get the paths to sign
8179
let mut paths_to_sign = get_paths_of_interest(args.format, &args.file_path)?;
80+
let base_path = if args.file_path.is_file() {
81+
args.file_path.parent().unwrap().to_path_buf()
82+
} else {
83+
args.file_path.to_path_buf()
84+
};
85+
// create the manifest
86+
let mut manifest = Manifest::from_signing_key(&base_path, signing_key)?;
8287

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

97102
pub(crate) fn verify(args: VerifyArgs) -> anyhow::Result<()> {
103+
let base_path = if args.file_path.is_file() {
104+
args.file_path.parent().unwrap().to_path_buf()
105+
} else {
106+
args.file_path.to_path_buf()
107+
};
108+
98109
// load signature file to verify
99110
let signature_path = signature_path(&args.file_path, args.signature);
100111

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

103-
let signature = Manifest::from_signature_path(&signature_path)?;
114+
let signature = Manifest::from_signature_path(&base_path, &signature_path)?;
104115

105116
// load the public key to verify against
106-
let mut manifest = Manifest::from_public_key_path(&args.key_path)?;
117+
let mut manifest = Manifest::from_public_key_path(&base_path, &args.key_path)?;
107118
// get the paths to verify
108119
let mut paths_to_verify = get_paths_of_interest(args.format, &args.file_path)?;
109120

src/core/signing.rs

Lines changed: 93 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -77,24 +77,31 @@ pub(crate) struct Manifest {
7777
// hex-encoded signature of the checksums
7878
pub(crate) signature: String,
7979

80+
#[serde(skip_serializing, skip_deserializing)]
81+
base_path: PathBuf,
8082
#[serde(skip_serializing, skip_deserializing)]
8183
signing_key: Option<signature::Ed25519KeyPair>,
8284
#[serde(skip_serializing, skip_deserializing)]
8385
verifying_key: Option<UnparsedPublicKey<Vec<u8>>>,
8486
}
8587

8688
impl Manifest {
87-
pub(crate) fn from_signature_path(path: &Path) -> anyhow::Result<Self> {
88-
Ok(serde_json::from_str(&std::fs::read_to_string(path)?)?)
89+
pub(crate) fn from_signature_path(base_path: &Path, path: &Path) -> anyhow::Result<Self> {
90+
let mut this: Manifest = serde_json::from_str(&std::fs::read_to_string(path)?)?;
91+
this.base_path = base_path.canonicalize()?;
92+
Ok(this)
8993
}
9094

91-
pub(crate) fn from_signing_key(signing_key: signature::Ed25519KeyPair) -> Self {
95+
pub(crate) fn from_signing_key(
96+
base_path: &Path,
97+
signing_key: signature::Ed25519KeyPair,
98+
) -> anyhow::Result<Self> {
9299
let public_key = signing_key.public_key();
93100
let mut hasher = Blake2b512::new();
94101
hasher.update(public_key.as_ref());
95102
let hash = hasher.finalize();
96103

97-
Self {
104+
Ok(Self {
98105
version: Version::V1,
99106
signed_at: chrono::Utc::now().to_rfc3339(),
100107
signed_with: format!("tensor-man v{}", env!("CARGO_PKG_VERSION")),
@@ -108,10 +115,14 @@ impl Manifest {
108115
signature: String::new(),
109116
signing_key: Some(signing_key),
110117
verifying_key: None,
111-
}
118+
base_path: base_path.canonicalize()?,
119+
})
112120
}
113121

114-
pub(crate) fn from_public_key(public_key_bytes: Vec<u8>) -> anyhow::Result<Self> {
122+
pub(crate) fn from_public_key(
123+
base_path: &Path,
124+
public_key_bytes: Vec<u8>,
125+
) -> anyhow::Result<Self> {
115126
let public_key = UnparsedPublicKey::new(&ED25519, public_key_bytes);
116127
let mut hasher = Blake2b512::new();
117128
hasher.update(public_key.as_ref());
@@ -131,12 +142,16 @@ impl Manifest {
131142
signature: String::new(),
132143
signing_key: None,
133144
verifying_key: Some(public_key),
145+
base_path: base_path.canonicalize()?,
134146
})
135147
}
136148

137-
pub(crate) fn from_public_key_path(public_key: &Path) -> anyhow::Result<Self> {
149+
pub(crate) fn from_public_key_path(
150+
base_path: &Path,
151+
public_key: &Path,
152+
) -> anyhow::Result<Self> {
138153
let public_key_bytes = std::fs::read(public_key)?;
139-
Self::from_public_key(public_key_bytes)
154+
Self::from_public_key(base_path, public_key_bytes)
140155
}
141156

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

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

163+
let path = path.canonicalize()?;
164+
148165
let mut hasher = Blake2b512::new();
149-
let mut file = std::fs::File::open(path)?;
166+
let mut file = std::fs::File::open(&path)?;
150167
let _ = std::io::copy(&mut file, &mut hasher)?;
151168
let hash_bytes = hasher.finalize();
152169
let hash = hex::encode(hash_bytes);
@@ -159,8 +176,20 @@ impl Manifest {
159176
start.elapsed()
160177
); */
161178

179+
if let Err(e) = path.strip_prefix(&self.base_path) {
180+
panic!(
181+
"base_path={} path={} error={}",
182+
self.base_path.display(),
183+
path.display(),
184+
e
185+
);
186+
}
187+
162188
self.checksums.insert(
163-
path.file_name().unwrap().to_string_lossy().to_string(),
189+
path.strip_prefix(&self.base_path)
190+
.unwrap()
191+
.to_string_lossy()
192+
.to_string(),
164193
hash,
165194
);
166195
Ok(())
@@ -278,10 +307,13 @@ mod tests {
278307
#[test]
279308
fn test_will_create_a_signature() {
280309
let keypair = create_test_keypair();
281-
let mut manifest = Manifest::from_signing_key(keypair);
282310

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

313+
let base_path = temp_file.path().parent().unwrap();
314+
315+
let mut manifest = Manifest::from_signing_key(&base_path, keypair).unwrap();
316+
285317
manifest.compute_checksum(&temp_file.path()).unwrap();
286318
let signature = manifest.create_signature().unwrap();
287319

@@ -308,16 +340,16 @@ mod tests {
308340
fn test_will_verify_correct_signature() {
309341
let keypair = create_test_keypair();
310342
let pub_key = keypair.public_key().as_ref().to_vec();
311-
312-
let mut ref_manifest = Manifest::from_signing_key(keypair);
313-
314343
let temp_file = create_temp_file_with_content("test").unwrap();
344+
let base_path = temp_file.path().parent().unwrap();
345+
346+
let mut ref_manifest = Manifest::from_signing_key(&base_path, keypair).unwrap();
315347

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

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

320-
let mut manifest = Manifest::from_public_key(pub_key).unwrap();
352+
let mut manifest = Manifest::from_public_key(&base_path, pub_key).unwrap();
321353

322354
manifest.verify(&mut paths, &ref_manifest).unwrap();
323355
}
@@ -327,16 +359,17 @@ mod tests {
327359
let keypair = create_test_keypair();
328360
let other_keypair = create_test_keypair();
329361
let pub_key = other_keypair.public_key().as_ref().to_vec();
362+
let temp_file = create_temp_file_with_content("test").unwrap();
363+
let base_path = temp_file.path().parent().unwrap();
330364

331-
let mut ref_manifest = Manifest::from_signing_key(keypair);
365+
let mut ref_manifest = Manifest::from_signing_key(&base_path, keypair).unwrap();
332366

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

336369
ref_manifest.compute_checksum(&temp_file.path()).unwrap();
337370
ref_manifest.create_signature().unwrap();
338371

339-
let mut manifest = Manifest::from_public_key(pub_key).unwrap();
372+
let mut manifest = Manifest::from_public_key(&base_path, pub_key).unwrap();
340373

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

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

351-
let mut ref_manifest = Manifest::from_signing_key(keypair);
352-
353384
let temp_file = create_temp_file_with_content("test").unwrap();
385+
let base_path = temp_file.path().parent().unwrap();
386+
387+
let mut ref_manifest = Manifest::from_signing_key(&base_path, keypair).unwrap();
388+
354389
let mut paths = vec![temp_file.path().to_path_buf()];
355390

356391
ref_manifest.compute_checksum(&temp_file.path()).unwrap();
357392
ref_manifest.create_signature().unwrap();
358393

359-
let mut manifest = Manifest::from_public_key(pub_key).unwrap();
394+
let mut manifest = Manifest::from_public_key(&base_path, pub_key).unwrap();
360395

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

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

373-
let mut ref_manifest = Manifest::from_signing_key(keypair);
374-
375408
let temp_file = create_temp_file_with_content("test").unwrap();
409+
let base_path = temp_file.path().parent().unwrap();
410+
411+
let mut ref_manifest = Manifest::from_signing_key(&base_path, keypair).unwrap();
412+
376413
let mut paths = vec![temp_file.path().to_path_buf()];
377414

378415
ref_manifest.compute_checksum(&temp_file.path()).unwrap();
379416
ref_manifest.create_signature().unwrap();
380417

381-
let mut manifest = Manifest::from_public_key(pub_key).unwrap();
418+
let mut manifest = Manifest::from_public_key(&base_path, pub_key).unwrap();
382419

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

394-
let mut ref_manifest = Manifest::from_signing_key(keypair);
395-
396431
let temp_file = create_temp_file_with_content("test").unwrap();
432+
let base_path = temp_file.path().parent().unwrap();
433+
434+
let mut ref_manifest = Manifest::from_signing_key(&base_path, keypair).unwrap();
435+
397436
let mut paths = vec![temp_file.path().to_path_buf()];
398437

399438
ref_manifest.compute_checksum(&temp_file.path()).unwrap();
400439
ref_manifest.create_signature().unwrap();
401440

402-
let mut manifest = Manifest::from_public_key(pub_key).unwrap();
441+
let mut manifest = Manifest::from_public_key(&base_path, pub_key).unwrap();
403442

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

419-
let mut ref_manifest = Manifest::from_signing_key(keypair);
420-
421458
let temp_file = create_temp_file_with_content("test").unwrap();
459+
let base_path = temp_file.path().parent().unwrap();
460+
461+
let mut ref_manifest = Manifest::from_signing_key(&base_path, keypair).unwrap();
462+
422463
ref_manifest.compute_checksum(&temp_file.path()).unwrap();
423464
// Deliberately skip creating signature
424465

425-
let mut manifest = Manifest::from_public_key(pub_key).unwrap();
466+
let mut manifest = Manifest::from_public_key(&base_path, pub_key).unwrap();
426467
manifest.compute_checksum(&temp_file.path()).unwrap();
427468

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

430471
assert!(manifest.verify(&mut paths, &ref_manifest).is_err());
431472
}
473+
474+
#[test]
475+
fn test_inner_folder_name_preserved() {
476+
let keypair = create_test_keypair();
477+
478+
// Create a temporary directory with a nested file structure
479+
let temp_dir = tempfile::tempdir().unwrap();
480+
let inner_dir = temp_dir.path().join("inner");
481+
std::fs::create_dir(&inner_dir).unwrap();
482+
483+
let test_file = inner_dir.join("test.txt");
484+
std::fs::write(&test_file, "test content").unwrap();
485+
486+
let base_path = temp_dir.path();
487+
488+
let mut manifest = Manifest::from_signing_key(&base_path, keypair).unwrap();
489+
490+
manifest.compute_checksum(&test_file).unwrap();
491+
492+
// Verify the checksum key preserves the inner folder name
493+
assert!(manifest.checksums.contains_key("inner/test.txt"));
494+
}
432495
}

0 commit comments

Comments
 (0)