From eabc93bd84bd69b27e0172caf9dd0dd231942f9f Mon Sep 17 00:00:00 2001 From: adlee-was-taken Date: Thu, 25 Jun 2026 21:15:11 -0400 Subject: [PATCH] fix(core): zeroize keyfile decode intermediate + clearer errors + error-arm tests --- crates/relicario-core/src/keyfile.rs | 32 ++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/crates/relicario-core/src/keyfile.rs b/crates/relicario-core/src/keyfile.rs index c8a0509..c84cf73 100644 --- a/crates/relicario-core/src/keyfile.rs +++ b/crates/relicario-core/src/keyfile.rs @@ -40,15 +40,21 @@ pub fn keyfile_decode(bytes: &[u8]) -> Result> { if lines.next() != Some(HEADER) { return Err(RelicarioError::Format("bad key-file header".into())); } - let b64 = lines.next().unwrap_or("").trim(); - let decoded = STANDARD - .decode(b64) - .map_err(|_| RelicarioError::Format("key-file body not base64".into()))?; - let arr: [u8; 32] = decoded - .as_slice() - .try_into() - .map_err(|_| RelicarioError::Format("key-file secret must be 32 bytes".into()))?; - Ok(Zeroizing::new(arr)) + let b64 = match lines.next() { + Some(line) => line.trim(), + None => return Err(RelicarioError::Format("key-file missing body line".into())), + }; + let decoded: Zeroizing> = Zeroizing::new( + STANDARD + .decode(b64) + .map_err(|_| RelicarioError::Format("key-file body not base64".into()))?, + ); + if decoded.len() != 32 { + return Err(RelicarioError::Format("key-file secret must be 32 bytes".into())); + } + let mut arr = Zeroizing::new([0u8; 32]); + arr.copy_from_slice(&decoded); + Ok(arr) } #[cfg(test)] @@ -70,4 +76,12 @@ mod tests { fn rejects_wrong_length() { assert!(keyfile_decode(b"relicario-keyfile-v1\nAAAA\n").is_err()); // decodes to <32 bytes } + #[test] + fn rejects_non_utf8() { + assert!(keyfile_decode(b"\xff\xfe\nAAAA\n").is_err()); + } + #[test] + fn rejects_missing_body() { + assert!(keyfile_decode(b"relicario-keyfile-v1\n").is_err()); + } }