dat 1.1.0

DAT - Data Access Token
Documentation
use crate::error::DatError;
use crate::signature_algorithm::SignatureAlgorithm;
use ecdsa::signature::Verifier;

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum SignatureKeyOutOption {
    FULL,
    SIGNING,
    VERIFYING,
}

pub enum SignatureKey {
    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 SignatureKey {
    pub fn generate(algorithm: SignatureAlgorithm) -> Self {
        match algorithm {
            SignatureAlgorithm::P256 => {
                let signing_key = <p256::ecdsa::SigningKey as p256::elliptic_curve::Generate>::generate();
                let verifying_key = *signing_key.verifying_key();
                SignatureKey::P256(Some(signing_key), verifying_key)
            },
            SignatureAlgorithm::P384 => {
                let signing_key = <p384::ecdsa::SigningKey as p384::elliptic_curve::Generate>::generate();
                let verifying_key = *signing_key.verifying_key();
                SignatureKey::P384(Some(signing_key), verifying_key)
            },
            SignatureAlgorithm::P521 => {
                let signing_key = <p521::ecdsa::SigningKey as p521::elliptic_curve::Generate>::generate();
                let verifying_key = *signing_key.verifying_key();
                SignatureKey::P521(Some(signing_key), verifying_key)
            },
        }
    }

    pub fn from_bytes(algorithm: SignatureAlgorithm, signing_key: &[u8], verifying_key: &[u8]) -> Result<SignatureKey, DatError> {
        match algorithm {
            SignatureAlgorithm::P256 => {
                let signing_key = if signing_key.is_empty() { None } else { Some(p256::ecdsa::SigningKey::from_slice(signing_key).unwrap()) };
                let verifying_key = if verifying_key.is_empty() {
                    *signing_key.as_ref().unwrap().verifying_key()
                } else {
                    p256::ecdsa::VerifyingKey::from_sec1_bytes(verifying_key).unwrap()
                };
                Ok(SignatureKey::P256(signing_key, verifying_key))
            },
            SignatureAlgorithm::P384 => {
                let signing_key = if signing_key.is_empty() { None } else { Some(p384::ecdsa::SigningKey::from_slice(signing_key).unwrap()) };
                let verifying_key = if verifying_key.is_empty() {
                    *signing_key.as_ref().unwrap().verifying_key()
                } else {
                    p384::ecdsa::VerifyingKey::from_sec1_bytes(verifying_key).unwrap()
                };
                Ok(SignatureKey::P384(signing_key, verifying_key))
            },
            SignatureAlgorithm::P521 => {
                let signing_key = if signing_key.is_empty() { None } else { Some(p521::ecdsa::SigningKey::from_slice(signing_key).unwrap()) };
                let verifying_key = if verifying_key.is_empty() {
                    *signing_key.as_ref().unwrap().verifying_key()
                } else {
                    p521::ecdsa::VerifyingKey::from_sec1_bytes(verifying_key).unwrap()
                };
                Ok(SignatureKey::P521(signing_key, verifying_key))
            },
        }
    }

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

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

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

    pub fn sign(&self, data: &[u8]) -> Box<[u8]> {
        match self {
            SignatureKey::P256(s, _) => {
                Box::from(&*ecdsa::signature::Signer::<p256::ecdsa::Signature>::sign(s.as_ref().unwrap(), data).to_bytes())
            },
            SignatureKey::P384(s, _) => {
                Box::from(&*ecdsa::signature::Signer::<p384::ecdsa::Signature>::sign(s.as_ref().unwrap(), data).to_bytes())
            },
            SignatureKey::P521(s, _) => {
                Box::from(&*ecdsa::signature::Signer::<p521::ecdsa::Signature>::sign(s.as_ref().unwrap(), data).to_bytes())
            },
        }
    }

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

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