use serde::{Deserialize, Serialize};
use zeroize::{Zeroize, ZeroizeOnDrop};
use crate::operation::Operation;
use crate::primitives::Authenticator;
#[derive(Clone, Serialize, Deserialize, Zeroize, ZeroizeOnDrop)]
#[serde(transparent)]
pub struct WrappingKey(#[serde(with = "crate::wire::b64bytes")] pub Vec<u8>);
impl core::fmt::Debug for WrappingKey {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "WrappingKey(<{} bytes redacted>)", self.0.len())
}
}
impl WrappingKey {
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
pub fn from_bytes(bytes: impl Into<Vec<u8>>) -> Self {
Self(bytes.into())
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct GrantOpt {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wrapping_key_next: Option<WrappingKey>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Grant<A: Authenticator> {
pub o: Operation,
#[serde(with = "serde_bytes")]
pub r: Vec<u8>,
#[serde(with = "serde_bytes")]
pub credential_id: Vec<u8>,
pub wrapping_key: WrappingKey,
pub assertion: A::Assertion,
#[serde(default)]
pub opt: GrantOpt,
}
#[derive(Debug)]
pub struct RedeemedGrant {
pub o: Operation,
pub credential_id: Vec<u8>,
pub wrapping_key: WrappingKey,
pub opt: GrantOpt,
}
impl<A: Authenticator> Clone for Grant<A>
where
A::Assertion: Clone,
{
fn clone(&self) -> Self {
Self {
o: self.o.clone(),
r: self.r.clone(),
credential_id: self.credential_id.clone(),
wrapping_key: self.wrapping_key.clone(),
assertion: self.assertion.clone(),
opt: self.opt.clone(),
}
}
}
mod serde_bytes {
use serde::{Deserialize, Deserializer, Serialize, Serializer};
pub fn serialize<S: Serializer>(v: &[u8], s: S) -> Result<S::Ok, S::Error> {
use base64::Engine;
let b64 = base64::engine::general_purpose::STANDARD.encode(v);
b64.serialize(s)
}
pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<u8>, D::Error> {
use base64::Engine;
let s = String::deserialize(d)?;
base64::engine::general_purpose::STANDARD
.decode(s)
.map_err(serde::de::Error::custom)
}
}