use std::fmt::Display;
use crate::error::DatError;
use crate::signature_algorithm::SignatureAlgorithm;
use ecdsa::signature::Verifier;
#[repr(u8)]
#[derive(Clone, Copy, PartialEq)]
pub enum SignatureKeyOutOption {
FULL,
SIGNING,
VERIFYING,
}
impl SignatureKeyOutOption {
pub fn to_str(&self) -> &'static str {
match self {
SignatureKeyOutOption::FULL => "FULL",
SignatureKeyOutOption::SIGNING => "SIGNING",
SignatureKeyOutOption::VERIFYING => "VERIFYING",
}
}
}
impl Display for SignatureKeyOutOption {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.to_str())
}
}
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().map(|e| Box::from(e.to_bytes().as_slice())).unwrap_or(Box::from([])), v.to_sec1_bytes())
},
SignatureKey::P384(s, v) => {
(s.as_ref().map(|e| Box::from(e.to_bytes().as_slice())).unwrap_or(Box::from([])), v.to_sec1_bytes())
},
SignatureKey::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]) -> 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)
}
pub fn signable(&self) -> bool {
match self {
SignatureKey::P256(s, _) => s.is_some(),
SignatureKey::P384(s, _) => s.is_some(),
SignatureKey::P521(s, _) => s.is_some(),
}
}
}
impl Clone for SignatureKey {
fn clone(&self) -> Self {
let (k, v) = self.to_bytes();
SignatureKey::from_bytes(self.algorithm(), &*k, &*v).unwrap()
}
}