use serde::{Deserialize, Serialize};
use crate::{
data::Metadata, AuthKeyPair, DigitalSignature, Hash, KeyPairAlgorithm, PublicKey, SigningError,
VerificationError,
};
pub use record_derive::Record;
pub trait Record: Sized {
fn sign(&self, keypair: &AuthKeyPair) -> Result<DigitalSignature, SigningError>;
fn verify(
&self,
signature: &DigitalSignature,
pubkey: &PublicKey,
) -> Result<(), VerificationError>;
fn record(
self,
keypair: AuthKeyPair,
metadata: Metadata,
) -> Result<SignedRecord<Self>, SigningError>;
fn hash(&self) -> Hash;
}
macro_rules! impl_record_for {
($type:ty) => {
impl Record for $type {
fn sign(
&self,
key: &crate::AuthKeyPair,
) -> Result<crate::DigitalSignature, crate::SigningError> {
let msg = crate::serialize(self)?;
let signature = crate::sign_msg(&msg, key)?;
Ok(signature)
}
fn verify(
&self,
signature: &crate::DigitalSignature,
key: &crate::PublicKey,
) -> Result<(), crate::VerificationError> {
let msg =
crate::serialize(self).map_err(|_| crate::VerificationError::SerdeError)?;
key.verify(&msg, signature)
}
fn record(
self,
keypair: crate::AuthKeyPair,
metadata: crate::data::Metadata,
) -> Result<crate::record::SignedRecord<Self>, crate::SigningError> {
let signature = self.sign(&keypair)?;
let hash = self.hash();
Ok(crate::record::SignedRecord::new(
self,
signature,
keypair.into_public_key(),
hash,
metadata,
))
}
fn hash(&self) -> crate::Hash {
crate::hash(self)
}
}
};
}
impl_record_for!(String);
impl_record_for!(bool);
impl_record_for!(i64);
impl_record_for!(Box<[u8]>);
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct SignedRecord<R> {
signer: PublicKey,
signature: DigitalSignature,
hash: Hash,
record: R,
metadata: Metadata,
}
impl<R> SignedRecord<R> {
pub fn new(
record: R,
signature: DigitalSignature,
signer: PublicKey,
hash: Hash,
metadata: Metadata,
) -> Self {
Self {
record,
signature,
hash,
signer,
metadata,
}
}
pub fn signature(&self) -> &DigitalSignature {
&self.signature
}
pub fn record(&self) -> &R {
&self.record
}
pub fn signer(&self) -> &PublicKey {
&self.signer
}
pub fn keypair_algorithm(&self) -> KeyPairAlgorithm {
self.signer.algorithm()
}
pub fn hash(&self) -> &Hash {
&self.hash
}
pub fn metadata(&self) -> &Metadata {
&self.metadata
}
}
impl<R: Record + Serialize> SignedRecord<R> {
pub fn verify(&self) -> Result<(), VerificationError> {
self.record.verify(self.signature(), self.signer())
}
}