From ead1c7ebad455c4d7f319457c3205d528234dbde Mon Sep 17 00:00:00 2001 From: Xiretza Date: Thu, 15 Feb 2024 20:58:41 +0000 Subject: [PATCH] Enforce minimum length for padlock generation secret --- src/secrets.rs | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/secrets.rs b/src/secrets.rs index a02ce92..13a0fd8 100644 --- a/src/secrets.rs +++ b/src/secrets.rs @@ -1,8 +1,10 @@ -use std::{convert::Infallible, fmt::Debug}; +use std::fmt::Debug; use hex::FromHex; +use rand::{thread_rng, Rng}; use secrecy::{ExposeSecret, SecretString, SecretVec}; use serde::{Deserialize, Serialize}; +use thiserror::Error; #[derive(Debug, Clone, Deserialize)] pub struct Password(pub SecretString); @@ -52,8 +54,18 @@ impl From for ServerPadlock { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ServerHash(pub String); -#[derive(Deserialize)] pub struct PadlockGenerationSecret(pub SecretVec); + +impl PadlockGenerationSecret { + /// Entirely arbitrary + const MIN_LENGTH_BYTES: usize = 32; + + fn get_random_secret() -> Vec { + let mut rng = thread_rng(); + (0..Self::MIN_LENGTH_BYTES).map(|_| rng.gen()).collect() + } +} + impl Debug for PadlockGenerationSecret { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("PadlockGenerationSecret") @@ -67,10 +79,22 @@ impl Clone for PadlockGenerationSecret { } } +#[derive(Debug, Clone, Error)] +#[error( + "Padlock secret too short, must be at least {} bytes - here's a fresh secret for you: {}", + PadlockGenerationSecret::MIN_LENGTH_BYTES, + hex::encode(PadlockGenerationSecret::get_random_secret()) +)] +pub struct PadlockSecretTooShort; impl FromHex for PadlockGenerationSecret { - type Error = Infallible; + type Error = PadlockSecretTooShort; fn from_hex>(hex: T) -> Result { - Ok(Self(hex.as_ref().to_vec().into())) + let hex = hex.as_ref(); + if hex.len() < Self::MIN_LENGTH_BYTES { + Err(PadlockSecretTooShort) + } else { + Ok(Self(hex.to_vec().into())) + } } }