use plist::Data;
use rand::RngExt;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use sha2::{Digest, Sha256};
use uuid::Uuid;
fn bin_serialize<S>(x: &[u8], s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
s.serialize_bytes(x)
}
fn bin_serialize_opt<S>(x: &Option<Vec<u8>>, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
x.clone().map(Data::new).serialize(s)
}
fn bin_deserialize_opt<'de, D>(d: D) -> Result<Option<Vec<u8>>, D::Error>
where
D: Deserializer<'de>,
{
let s: Option<Data> = Deserialize::deserialize(d)?;
Ok(s.map(|i| i.into()))
}
fn bin_deserialize_16<'de, D>(d: D) -> Result<[u8; 16], D::Error>
where
D: Deserializer<'de>,
{
let s: Data = Deserialize::deserialize(d)?;
let s: Vec<u8> = s.into();
Ok(s.try_into().unwrap())
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct AnisetteState {
#[serde(
serialize_with = "bin_serialize",
deserialize_with = "bin_deserialize_16"
)]
pub keychain_identifier: [u8; 16],
#[serde(
serialize_with = "bin_serialize_opt",
deserialize_with = "bin_deserialize_opt"
)]
pub adi_pb: Option<Vec<u8>>,
}
impl Default for AnisetteState {
fn default() -> Self {
AnisetteState {
keychain_identifier: rand::rng().random::<[u8; 16]>(),
adi_pb: None,
}
}
}
impl AnisetteState {
pub fn new() -> AnisetteState {
AnisetteState::default()
}
pub fn is_provisioned(&self) -> bool {
self.adi_pb.is_some()
}
pub fn get_md_lu(&self) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update(self.keychain_identifier);
hasher.finalize().into()
}
pub fn get_device_id(&self) -> String {
Uuid::from_bytes(self.keychain_identifier).to_string()
}
}