feat: libpaket: use secrecy on packstation credentials

This commit is contained in:
jane400 2024-10-02 17:45:00 +02:00 committed by jane400
parent afcfe0c9ef
commit d7e905f7eb
2 changed files with 43 additions and 30 deletions

View file

@ -1,41 +1,53 @@
use base64::{engine::general_purpose, Engine as _}; use base64::{engine::general_purpose, Engine as _};
use rand::prelude::*;
use uuid::Uuid;
use ed25519_dalek::SigningKey;
use ed25519_dalek::Signer; 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 struct CustomerKeySeed {
pub postnumber: String, pub postnumber: String,
pub seed: Seed, pub seed: SecretBox<Seed>,
pub uuid: Uuid, pub uuid: Uuid,
pub device_id: Option<String>, pub device_id: Option<String>,
} }
pub struct Seed { impl Zeroize for CustomerKeySeed {
bytes: Vec<u8>, fn zeroize(&mut self) {
self.postnumber.zeroize();
self.seed.zeroize();
self.uuid.into_bytes().zeroize();
self.device_id.zeroize();
}
}
pub struct Seed(Vec<u8>);
impl Zeroize for Seed {
fn zeroize(&mut self) {
self.0.zeroize();
}
}
impl From<Vec<u8>> for Seed {
fn from(value: Vec<u8>) -> Self {
assert_eq!(value.len(), 32);
Seed(value)
}
} }
impl Seed { impl Seed {
pub(self) fn from_bytes(bytes: Vec<u8>) -> Self {
assert_eq!(bytes.len(), 32);
Seed {
bytes: bytes
}
}
pub fn random() -> Self { pub fn random() -> Self {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
let mut bytes: Vec<u8> = vec![0; 32]; let mut bytes: Vec<u8> = vec![0; 32];
rng.fill_bytes(bytes.as_mut_slice()); rng.fill_bytes(bytes.as_mut_slice());
Seed (bytes)
Seed { bytes: bytes }
} }
pub fn as_bytes(&self) -> &[u8; 32] { 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 { pub fn new(postnumber: String) -> Self {
CustomerKeySeed { CustomerKeySeed {
postnumber, postnumber,
seed: Seed::random(), seed: SecretBox::new(Box::new(Seed::random())),
uuid: uuid::Uuid::new_v4(), uuid: uuid::Uuid::new_v4(),
device_id: None, device_id: None,
} }
@ -52,7 +64,7 @@ impl CustomerKeySeed {
pub fn from(postnumber: &String, seed: Vec<u8>, uuid: &Uuid, device_id: String) -> Self { pub fn from(postnumber: &String, seed: Vec<u8>, uuid: &Uuid, device_id: String) -> Self {
CustomerKeySeed { CustomerKeySeed {
postnumber: postnumber.clone(), postnumber: postnumber.clone(),
seed: Seed::from_bytes(seed), seed: SecretBox::new(Box::new(Seed::from(seed))),
uuid: uuid.clone(), uuid: uuid.clone(),
device_id: Some(device_id), device_id: Some(device_id),
} }
@ -65,17 +77,15 @@ impl CustomerKeySeed {
} }
pub(crate) fn sign(&self, message: &[u8]) -> String { 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 signature = signing_key.sign(message);
let sig_str = general_purpose::STANDARD.encode(signature.to_bytes()); let sig_str = general_purpose::STANDARD.encode(signature.to_bytes());
format!("{}.{}", self.uuid.to_string(), sig_str) format!("{}.{}", self.uuid.to_string(), sig_str)
} }
pub(crate) fn get_public_key(&self) -> String { 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_bytes = signing_key.verifying_key().to_bytes();
let public_str = general_purpose::STANDARD.encode(public_bytes); let public_str = general_purpose::STANDARD.encode(public_bytes);

View file

@ -4,8 +4,11 @@ use sha2::Sha256;
use crate::{LibraryResult, LibraryError}; use crate::{LibraryResult, LibraryError};
pub struct RegToken { pub struct RegToken(Vec<u8>);
token: Vec<u8>, impl secrecy::zeroize::Zeroize for RegToken {
fn zeroize(&mut self) {
self.0.zeroize();
}
} }
impl RegToken { impl RegToken {
@ -32,15 +35,15 @@ impl RegToken {
token.extend(vec![0; 32 - token.len()].iter()) token.extend(vec![0; 32 - token.len()].iter())
} }
Ok(RegToken { token }) Ok(RegToken(token))
} }
pub fn customer_password(&self) -> String { 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<Sha256> { pub fn hmac(&self) -> SimpleHmac<Sha256> {
let mac = SimpleHmac::<Sha256>::new_from_slice(&self.token[0..32]) let mac = SimpleHmac::<Sha256>::new_from_slice(&self.0[0..32])
.expect("HMAC can take key of any size"); .expect("HMAC can take key of any size");
mac mac