use {
crate::{
Digest,
PeerId,
groups::{GroupId, Groups},
network::link::Link,
tickets::TicketValidator,
},
core::fmt,
serde::{Deserialize, Serialize},
};
pub type Secret = Digest;
pub type SecretProof = Digest;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct GroupKey {
secret: Secret,
}
impl From<Secret> for GroupKey {
fn from(secret: Secret) -> Self {
Self { secret }
}
}
impl From<&Secret> for GroupKey {
fn from(secret: &Secret) -> Self {
Self { secret: *secret }
}
}
impl<T: TicketValidator + ?Sized> From<&T> for GroupKey {
fn from(validator: &T) -> Self {
Self {
secret: validator.signature(),
}
}
}
impl GroupKey {
pub const fn new(secret: Secret) -> Self {
Self { secret }
}
pub fn from_secret(secret: impl Into<Secret>) -> Self {
let secret = secret.into();
Self { secret }
}
pub fn random() -> Self {
Self {
secret: Secret::random(),
}
}
pub const fn secret(&self) -> &Secret {
&self.secret
}
pub fn validate_proof(
&self,
link: &Link<Groups>,
proof: SecretProof,
group_id: GroupId,
) -> bool {
self.generate_proof(link, link.remote_id(), group_id) == proof
}
pub fn generate_proof(
&self,
link: &Link<Groups>,
peer_id: PeerId,
group_id: GroupId,
) -> SecretProof {
self
.secret()
.derive(link.shared_random(group_id))
.derive(peer_id.as_bytes())
}
}
impl fmt::Display for GroupKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let head = hex::encode(&self.secret().as_bytes()[..1]);
let tail = hex::encode(&self.secret().as_bytes()[31..]);
write!(f, "{head}****{tail}")
}
}