use crate::{
error::FsError,
private::{KEY_BYTE_SIZE, PrivateRefSerializable, TemporalKey},
};
use anyhow::Result;
use serde::{Deserialize, Serialize, de::Error as DeError, ser::Error as SerError};
use std::fmt::Debug;
use wnfs_common::{Cid, HashOutput};
#[derive(Clone, PartialEq, Eq)]
pub struct PrivateRef {
pub label: HashOutput,
pub temporal_key: TemporalKey,
pub content_cid: Cid,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) struct RevisionRef {
pub label: HashOutput,
pub temporal_key: TemporalKey,
}
impl PrivateRef {
pub(crate) fn with_temporal_key(
label: HashOutput,
temporal_key: TemporalKey,
content_cid: Cid,
) -> Self {
Self {
label,
temporal_key,
content_cid,
}
}
pub(crate) fn to_serializable(
&self,
parent_temporal_key: &TemporalKey,
) -> Result<PrivateRefSerializable> {
let snapshot_key = self.temporal_key.derive_snapshot_key();
let temporal_key_wrapped = parent_temporal_key.key_wrap_encrypt(&self.temporal_key.0)?;
Ok(PrivateRefSerializable {
label: self.label,
snapshot_key,
temporal_key: temporal_key_wrapped,
content_cid: self.content_cid,
})
}
pub(crate) fn from_serializable(
private_ref: PrivateRefSerializable,
parent_temporal_key: &TemporalKey,
) -> Result<Self> {
let temporal_key_decrypted =
parent_temporal_key.key_wrap_decrypt(&private_ref.temporal_key)?;
let temporal_key_raw: [u8; KEY_BYTE_SIZE] =
temporal_key_decrypted.try_into().map_err(|e: Vec<u8>| {
FsError::InvalidDeserialization(format!(
"Expected 32 bytes for ratchet key, but got {}",
e.len()
))
})?;
Ok(Self {
label: private_ref.label,
temporal_key: TemporalKey(temporal_key_raw),
content_cid: private_ref.content_cid,
})
}
#[allow(unused)]
pub(crate) fn serialize<S>(
&self,
serializer: S,
temporal_key: &TemporalKey,
) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.to_serializable(temporal_key)
.map_err(SerError::custom)?
.serialize(serializer)
}
#[allow(unused)]
pub(crate) fn deserialize<'de, D>(
deserializer: D,
temporal_key: &TemporalKey,
) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let private_ref = PrivateRefSerializable::deserialize(deserializer)?;
PrivateRef::from_serializable(private_ref, temporal_key).map_err(DeError::custom)
}
}
impl Debug for PrivateRef {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut rev_name_hash_str = String::from("0x");
for byte in self.label {
rev_name_hash_str.push_str(&format!("{byte:02X}"));
}
f.debug_struct("PrivateRef")
.field("label", &rev_name_hash_str)
.field("temporal_key", &hex::encode(self.temporal_key.0))
.field("content_cid", &format!("{}", self.content_cid))
.finish()
}
}
impl RevisionRef {
pub(crate) fn into_private_ref(self, content_cid: Cid) -> PrivateRef {
PrivateRef {
label: self.label,
temporal_key: self.temporal_key,
content_cid,
}
}
}