trustime 0.1.0

A client implementation of the Trustime trusted timestamp service protocol
Documentation
use std::{fmt::Display, time::Duration};
use base64::{prelude::BASE64_STANDARD, Engine};
use p256::ecdsa::{self, signature::Verifier, Signature, VerifyingKey};
use serde::Deserialize;

#[derive(Debug)]
pub enum Error {
    RequestError(reqwest::Error),
    InvalidSignature(Box<dyn std::error::Error + Send + Sync>),
}

impl Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Error::RequestError(error) => write!(f, "Request error: {}", error),
            Error::InvalidSignature(error) => write!(f, "Invalid signature: {}", error),
        }
    }
}

impl From<reqwest::Error> for Error {
    fn from(value: reqwest::Error) -> Self {
        Self::RequestError(value)
    }
}

impl From<ecdsa::Error> for Error {
    fn from(value: ecdsa::Error) -> Self {
        Self::InvalidSignature(Box::new(value))
    }
}

impl From<base64::DecodeError> for Error {
    fn from(value: base64::DecodeError) -> Self {
        Self::InvalidSignature(Box::new(value))
    }
}

impl std::error::Error for Error {}

#[derive(Deserialize)]
pub(crate) struct RawTime {
    timestamp: u64,
    signature: String,
}

impl RawTime {
    pub(crate) fn digest(&self, nonce: &str, verifying_key: &VerifyingKey) -> Result<Duration, Error> {
        let msg = self.timestamp.to_string() + nonce;
        verifying_key.verify(
            msg.as_bytes(),
            &Signature::from_slice(
                &BASE64_STANDARD.decode(&self.signature)?
            )?
        )?;
        Ok(Duration::from_secs(self.timestamp))
    }
}