dat 2.0.0

DAT - Distributed Access Token
Documentation
use crate::error::DatError;
use crate::dat_signature_algorithm::DatSignatureAlgorithm;
use ecdsa::signature::Verifier;
use strum_macros::{Display, EnumString};

#[repr(u8)]
#[derive(Debug, Display, EnumString, Clone, Copy, Eq, PartialEq)]
pub enum DatSignatureKeyOutOption {
    FULL,
    SIGNING,
    VERIFYING,
}

pub enum DatSignatureKey {
    P256(Option<p256::ecdsa::SigningKey>, p256::ecdsa::VerifyingKey),
    P384(Option<p384::ecdsa::SigningKey>, p384::ecdsa::VerifyingKey),
    P521(Option<p521::ecdsa::SigningKey>, p521::ecdsa::VerifyingKey),
}

impl DatSignatureKey {
    pub fn generate(algorithm: DatSignatureAlgorithm) -> Self {
        match algorithm {
            DatSignatureAlgorithm::P256 => {
                let signing_key = <p256::ecdsa::SigningKey as p256::elliptic_curve::Generate>::generate();
                let verifying_key = *signing_key.verifying_key();
                DatSignatureKey::P256(Some(signing_key), verifying_key)
            },
            DatSignatureAlgorithm::P384 => {
                let signing_key = <p384::ecdsa::SigningKey as p384::elliptic_curve::Generate>::generate();
                let verifying_key = *signing_key.verifying_key();
                DatSignatureKey::P384(Some(signing_key), verifying_key)
            },
            DatSignatureAlgorithm::P521 => {
                let signing_key = <p521::ecdsa::SigningKey as p521::elliptic_curve::Generate>::generate();
                let verifying_key = *signing_key.verifying_key();
                DatSignatureKey::P521(Some(signing_key), verifying_key)
            },
        }
    }

    pub fn from_bytes(algorithm: DatSignatureAlgorithm, signing_key: &[u8], verifying_key: &[u8]) -> Result<DatSignatureKey, DatError> {
        match algorithm {
            DatSignatureAlgorithm::P256 => {

                let signing_key = if signing_key.is_empty() {
                    None
                } else {
                    Some(p256::ecdsa::SigningKey::from_slice(signing_key).map_err(|_| DatError::ParseDatSigningKeyError)?)
                };

                let verifying_key = if verifying_key.is_empty() {
                    *signing_key.as_ref().ok_or_else(|| DatError::ParseDatVerifyingKeyError)?.verifying_key()
                } else {
                    p256::ecdsa::VerifyingKey::from_sec1_bytes(verifying_key).map_err(|_| DatError::ParseDatVerifyingKeyError)?
                };

                Ok(DatSignatureKey::P256(signing_key, verifying_key))
            },
            DatSignatureAlgorithm::P384 => {

                let signing_key = if signing_key.is_empty() {
                    None
                } else {
                    Some(p384::ecdsa::SigningKey::from_slice(signing_key).map_err(|_| DatError::ParseDatSigningKeyError)?)
                };

                let verifying_key = if verifying_key.is_empty() {
                    *signing_key.as_ref().ok_or_else(|| DatError::ParseDatVerifyingKeyError)?.verifying_key()
                } else {
                    p384::ecdsa::VerifyingKey::from_sec1_bytes(verifying_key).map_err(|_| DatError::ParseDatVerifyingKeyError)?
                };

                Ok(DatSignatureKey::P384(signing_key, verifying_key))
            },
            DatSignatureAlgorithm::P521 => {

                let signing_key = if signing_key.is_empty() {
                    None
                } else {
                    Some(p521::ecdsa::SigningKey::from_slice(signing_key).map_err(|_| DatError::ParseDatSigningKeyError)?)
                };

                let verifying_key = if verifying_key.is_empty() {
                    *signing_key.as_ref().ok_or_else(|| DatError::ParseDatVerifyingKeyError)?.verifying_key()
                } else {
                    p521::ecdsa::VerifyingKey::from_sec1_bytes(verifying_key).map_err(|_| DatError::ParseDatVerifyingKeyError)?
                };

                Ok(DatSignatureKey::P521(signing_key, verifying_key))
            },
        }
    }

    pub fn algorithm(&self) -> DatSignatureAlgorithm {
        match self {
            DatSignatureKey::P256(_, _) => DatSignatureAlgorithm::P256,
            DatSignatureKey::P384(_, _) => DatSignatureAlgorithm::P384,
            DatSignatureKey::P521(_, _) => DatSignatureAlgorithm::P521,
        }
    }

    pub fn signature_size(&self) -> usize {
        match self {
            DatSignatureKey::P256(_, _) => 64,
            DatSignatureKey::P384(_, _) => 96,
            DatSignatureKey::P521(_, _) => 132,
        }
    }

    pub fn to_bytes(&self) -> (Box<[u8]>, Box<[u8]>) {
        match self {
            DatSignatureKey::P256(s, v) => {
                (s.as_ref().map(|e| Box::from(e.to_bytes().as_slice())).unwrap_or(Box::from([])), v.to_sec1_bytes())
            },
            DatSignatureKey::P384(s, v) => {
                (s.as_ref().map(|e| Box::from(e.to_bytes().as_slice())).unwrap_or(Box::from([])), v.to_sec1_bytes())
            },
            DatSignatureKey::P521(s, v) => {
                (s.as_ref().map(|e| Box::from(e.to_bytes().as_slice())).unwrap_or(Box::from([])), v.to_sec1_bytes())
            },
        }
    }

    pub fn sign(&self, data: &[u8]) -> Result<Box<[u8]>, DatError> {
        match self {
            DatSignatureKey::P256(s, _) => {
                Ok(Box::from(&*ecdsa::signature::Signer::<p256::ecdsa::Signature>::sign(s.as_ref().ok_or_else(|| DatError::VerifyOnlyKey)?, data).to_bytes()))
            },
            DatSignatureKey::P384(s, _) => {
                Ok(Box::from(&*ecdsa::signature::Signer::<p384::ecdsa::Signature>::sign(s.as_ref().ok_or_else(|| DatError::VerifyOnlyKey)?, data).to_bytes()))
            },
            DatSignatureKey::P521(s, _) => {
                Ok(Box::from(&*ecdsa::signature::Signer::<p521::ecdsa::Signature>::sign(s.as_ref().ok_or_else(|| DatError::VerifyOnlyKey)?, data).to_bytes()))
            },
        }
    }

    pub fn verify(&self, body: &[u8], sign: &[u8]) -> Result<(), DatError> {
        match self {
            DatSignatureKey::P256(_, v) => v.verify(body, &ecdsa::Signature::from_slice(sign).map_err(|_| DatError::InvalidDat)?),
            DatSignatureKey::P384(_, v) => v.verify(body, &ecdsa::Signature::from_slice(sign).map_err(|_| DatError::InvalidDat)?),
            DatSignatureKey::P521(_, v) => v.verify(body, &ecdsa::Signature::from_slice(sign).map_err(|_| DatError::InvalidDat)?),
        }.map_err(|_| DatError::InvalidDat)
    }

    pub fn has_signing_key(&self) -> bool {
        match self {
            DatSignatureKey::P256(s, _) => s.is_some(),
            DatSignatureKey::P384(s, _) => s.is_some(),
            DatSignatureKey::P521(s, _) => s.is_some(),
        }
    }
}

impl Clone for DatSignatureKey {
    fn clone(&self) -> Self {
        let (k, v) = self.to_bytes();
        DatSignatureKey::from_bytes(self.algorithm(), &*k, &*v).unwrap()
    }
}