From d7e905f7ebac34ace015764f1dc9037a508b131e Mon Sep 17 00:00:00 2001 From: jane400 Date: Wed, 2 Oct 2024 17:45:00 +0200 Subject: [PATCH] feat: libpaket: use secrecy on packstation credentials --- libpaket/src/locker/crypto.rs | 60 +++++++++++++++++++-------------- libpaket/src/locker/regtoken.rs | 13 ++++--- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/libpaket/src/locker/crypto.rs b/libpaket/src/locker/crypto.rs index 85f8e94..384491d 100644 --- a/libpaket/src/locker/crypto.rs +++ b/libpaket/src/locker/crypto.rs @@ -1,41 +1,53 @@ use base64::{engine::general_purpose, Engine as _}; -use rand::prelude::*; -use uuid::Uuid; -use ed25519_dalek::SigningKey; use ed25519_dalek::Signer; +use ed25519_dalek::SigningKey; +use rand::prelude::*; +use secrecy::zeroize::Zeroize; +use secrecy::ExposeSecret; +use secrecy::SecretBox; +use uuid::Uuid; - +#[derive(Debug)] pub struct CustomerKeySeed { pub postnumber: String, - pub seed: Seed, + pub seed: SecretBox, pub uuid: Uuid, pub device_id: Option, } -pub struct Seed { - bytes: Vec, +impl Zeroize for CustomerKeySeed { + fn zeroize(&mut self) { + self.postnumber.zeroize(); + self.seed.zeroize(); + self.uuid.into_bytes().zeroize(); + self.device_id.zeroize(); + } +} + +pub struct Seed(Vec); +impl Zeroize for Seed { + fn zeroize(&mut self) { + self.0.zeroize(); + } +} + +impl From> for Seed { + fn from(value: Vec) -> Self { + assert_eq!(value.len(), 32); + Seed(value) + } } impl Seed { - pub(self) fn from_bytes(bytes: Vec) -> Self { - assert_eq!(bytes.len(), 32); - Seed { - bytes: bytes - } - } - pub fn random() -> Self { let mut rng = rand::thread_rng(); - let mut bytes: Vec = vec![0; 32]; - rng.fill_bytes(bytes.as_mut_slice()); - - Seed { bytes: bytes } + Seed (bytes) } pub fn as_bytes(&self) -> &[u8; 32] { - (&self.bytes[..]).try_into().unwrap() + (&self.0[..]).try_into().unwrap() } } @@ -43,7 +55,7 @@ impl CustomerKeySeed { pub fn new(postnumber: String) -> Self { CustomerKeySeed { postnumber, - seed: Seed::random(), + seed: SecretBox::new(Box::new(Seed::random())), uuid: uuid::Uuid::new_v4(), device_id: None, } @@ -52,7 +64,7 @@ impl CustomerKeySeed { pub fn from(postnumber: &String, seed: Vec, uuid: &Uuid, device_id: String) -> Self { CustomerKeySeed { postnumber: postnumber.clone(), - seed: Seed::from_bytes(seed), + seed: SecretBox::new(Box::new(Seed::from(seed))), uuid: uuid.clone(), device_id: Some(device_id), } @@ -65,17 +77,15 @@ impl CustomerKeySeed { } pub(crate) fn sign(&self, message: &[u8]) -> String { - let signing_key = SigningKey::from_bytes(self.seed.as_bytes()); - + let signing_key = SigningKey::from_bytes(self.seed.expose_secret().as_bytes()); let signature = signing_key.sign(message); - let sig_str = general_purpose::STANDARD.encode(signature.to_bytes()); format!("{}.{}", self.uuid.to_string(), sig_str) } pub(crate) fn get_public_key(&self) -> String { - let signing_key = SigningKey::from_bytes(self.seed.as_bytes()); + let signing_key = SigningKey::from_bytes(self.seed.expose_secret().as_bytes()); let public_bytes = signing_key.verifying_key().to_bytes(); let public_str = general_purpose::STANDARD.encode(public_bytes); diff --git a/libpaket/src/locker/regtoken.rs b/libpaket/src/locker/regtoken.rs index a79e25c..dc5afe3 100644 --- a/libpaket/src/locker/regtoken.rs +++ b/libpaket/src/locker/regtoken.rs @@ -4,8 +4,11 @@ use sha2::Sha256; use crate::{LibraryResult, LibraryError}; -pub struct RegToken { - token: Vec, +pub struct RegToken(Vec); +impl secrecy::zeroize::Zeroize for RegToken { + fn zeroize(&mut self) { + self.0.zeroize(); + } } impl RegToken { @@ -32,15 +35,15 @@ impl RegToken { token.extend(vec![0; 32 - token.len()].iter()) } - Ok(RegToken { token }) + Ok(RegToken(token)) } pub fn customer_password(&self) -> String { - general_purpose::STANDARD.encode(&self.token[32..]) + general_purpose::STANDARD.encode(&self.0[32..]) } pub fn hmac(&self) -> SimpleHmac { - let mac = SimpleHmac::::new_from_slice(&self.token[0..32]) + let mac = SimpleHmac::::new_from_slice(&self.0[0..32]) .expect("HMAC can take key of any size"); mac