use crate::{asymmetric, ecdsa::algorithm::CurveAlgorithm, ed25519};
use ::ecdsa::{
elliptic_curve::{
sec1::{self, UncompressedPointSize, UntaggedPointSize},
weierstrass::{point, Curve},
},
generic_array::{
typenum::{Unsigned, U1},
ArrayLength, GenericArray,
},
};
use serde::{Deserialize, Serialize};
use std::ops::Add;
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct PublicKey {
pub algorithm: asymmetric::Algorithm,
pub bytes: Vec<u8>,
}
#[allow(clippy::len_without_is_empty)]
impl PublicKey {
pub fn into_vec(self) -> Vec<u8> {
self.into()
}
pub fn len(&self) -> usize {
self.bytes.len()
}
pub fn as_slice(&self) -> &[u8] {
self.as_ref()
}
pub fn ecdsa<C>(&self) -> Option<sec1::EncodedPoint<C>>
where
C: Curve + CurveAlgorithm + point::Compression,
UntaggedPointSize<C>: Add<U1> + ArrayLength<u8>,
UncompressedPointSize<C>: ArrayLength<u8>,
{
if self.algorithm != C::asymmetric_algorithm()
|| self.bytes.len() != C::FieldSize::to_usize() * 2
{
return None;
}
let mut bytes = GenericArray::default();
bytes.copy_from_slice(&self.bytes);
let result = sec1::EncodedPoint::from_untagged_bytes(&bytes);
if C::COMPRESS_POINTS {
Some(result.compress())
} else {
Some(result)
}
}
pub fn ed25519(&self) -> Option<ed25519::PublicKey> {
if self.algorithm == asymmetric::Algorithm::Ed25519 {
ed25519::PublicKey::from_bytes(&self.bytes)
} else {
None
}
}
}
impl AsRef<[u8]> for PublicKey {
fn as_ref(&self) -> &[u8] {
self.bytes.as_ref()
}
}
impl Into<Vec<u8>> for PublicKey {
fn into(self) -> Vec<u8> {
self.bytes
}
}