use crate::error::DatError;
use ecdsa::signature::Verifier;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SignAlgorithm {
P256,
P384,
P521,
}
pub enum SignKey {
P256(p256::ecdsa::SigningKey),
P384(p384::ecdsa::SigningKey),
P521(p521::ecdsa::SigningKey),
}
pub enum VerifyKey {
P256(p256::ecdsa::VerifyingKey),
P384(p384::ecdsa::VerifyingKey),
P521(p521::ecdsa::VerifyingKey),
}
impl SignAlgorithm {
pub fn to_str(&self) -> &'static str {
match self {
SignAlgorithm::P256 => "P256",
SignAlgorithm::P384 => "P384",
SignAlgorithm::P521 => "P521",
}
}
pub fn from_str(s: &str) -> Result<SignAlgorithm, DatError> {
match s {
"P256" => Ok(SignAlgorithm::P256),
"P384" => Ok(SignAlgorithm::P384),
"P521" => Ok(SignAlgorithm::P521),
_ => Err(DatError::SignError(format!("UnknownSignAlgorithm {}", s))),
}
}
}
impl SignKey {
pub fn generate(alg: SignAlgorithm) -> Self {
match alg {
SignAlgorithm::P256 => SignKey::P256(<p256::ecdsa::SigningKey as p256::elliptic_curve::Generate>::generate()),
SignAlgorithm::P384 => SignKey::P384(<p384::ecdsa::SigningKey as p384::elliptic_curve::Generate>::generate()),
SignAlgorithm::P521 => SignKey::P521(<p521::ecdsa::SigningKey as p521::elliptic_curve::Generate>::generate()),
}
}
pub fn from_bytes(alg: SignAlgorithm, data: &[u8]) -> Result<SignKey, DatError> {
Ok(match alg {
SignAlgorithm::P256 => p256::ecdsa::SigningKey::from_slice(data).map(SignKey::P256),
SignAlgorithm::P384 => p384::ecdsa::SigningKey::from_slice(data).map(SignKey::P384),
SignAlgorithm::P521 => p521::ecdsa::SigningKey::from_slice(data).map(SignKey::P521),
}?)
}
pub fn to_bytes(&self) -> Box<[u8]> {
match self {
SignKey::P256(sk) => Box::from(sk.to_bytes().as_slice()),
SignKey::P384(sk) => Box::from(sk.to_bytes().as_slice()),
SignKey::P521(sk) => Box::from(sk.to_bytes().as_slice()),
}
}
pub fn to_verify_key(&self) -> VerifyKey {
match self {
SignKey::P256(key) => VerifyKey::P256(*key.verifying_key()),
SignKey::P384(key) => VerifyKey::P384(*key.verifying_key()),
SignKey::P521(key) => VerifyKey::P521(*key.verifying_key()),
}
}
pub fn sign(&self, data: &[u8]) -> Box<[u8]> {
match self {
SignKey::P256(key) => Box::from(&*ecdsa::signature::Signer::<p256::ecdsa::Signature>::sign(key, data).to_bytes()),
SignKey::P384(key) => Box::from(&*ecdsa::signature::Signer::<p384::ecdsa::Signature>::sign(key, data).to_bytes()),
SignKey::P521(key) => Box::from(&*ecdsa::signature::Signer::<p521::ecdsa::Signature>::sign(key, data).to_bytes()),
}
}
}
impl VerifyKey {
pub fn to_alg(&self) -> SignAlgorithm {
match self {
VerifyKey::P256(_) => SignAlgorithm::P256,
VerifyKey::P384(_) => SignAlgorithm::P384,
VerifyKey::P521(_) => SignAlgorithm::P521,
}
}
pub fn from_bytes(alg: SignAlgorithm, data: &[u8]) -> Result<VerifyKey, DatError> {
Ok(match alg {
SignAlgorithm::P256 => p256::ecdsa::VerifyingKey::from_sec1_bytes(data).map(VerifyKey::P256),
SignAlgorithm::P384 => p384::ecdsa::VerifyingKey::from_sec1_bytes(data).map(VerifyKey::P384),
SignAlgorithm::P521 => p521::ecdsa::VerifyingKey::from_sec1_bytes(data).map(VerifyKey::P521),
}?)
}
pub fn to_bytes(&self) -> Box<[u8]> {
match self {
VerifyKey::P256(vk) => vk.to_sec1_bytes(),
VerifyKey::P384(vk) => vk.to_sec1_bytes(),
VerifyKey::P521(vk) => vk.to_sec1_bytes(),
}
}
pub fn verify(&self, body: &[u8], sign: &[u8]) -> Result<(), DatError> {
Ok(match self {
VerifyKey::P256(key) => key.verify(body, &ecdsa::Signature::from_slice(sign)?),
VerifyKey::P384(key) => key.verify(body, &ecdsa::Signature::from_slice(sign)?),
VerifyKey::P521(key) => key.verify(body, &ecdsa::Signature::from_slice(sign)?),
}?)
}
}