use std::{fmt, str::FromStr};
use k256::{
ecdsa::{recoverable::Signature, SigningKey, VerifyingKey},
elliptic_curve::sec1::ToEncodedPoint,
};
use super::{error::Error, PrivateKey};
#[derive(Clone, PartialEq, Eq)]
pub struct PublicKey(VerifyingKey);
impl PublicKey {
pub fn from_slice(bytes: &[u8]) -> Result<PublicKey, Error> {
let key = VerifyingKey::from_sec1_bytes(bytes).map_err(|_| Error::InvalidPublicKey)?;
Ok(PublicKey(key))
}
pub fn from_private(private_key: &PrivateKey) -> PublicKey {
let bytes = private_key.to_bytes();
let sk = SigningKey::from_bytes(&bytes).unwrap();
PublicKey(VerifyingKey::from(&sk))
}
pub fn to_bytes(&self) -> [u8; 33] {
let mut bytes = [0u8; 33];
bytes.copy_from_slice(&self.0.to_bytes());
bytes
}
pub fn to_bytes_uncompressed(&self) -> Vec<u8> {
let encode_point = self.0.to_encoded_point(false);
encode_point.as_bytes().to_vec()
}
pub fn as_bytes(&self) -> Vec<u8> {
self.to_bytes().to_vec()
}
pub fn as_str(&self) -> &'static str {
let string = format!("{:x}", self);
Box::leak(string.into_boxed_str())
}
pub fn verify(&self, msg: &[u8], signature: &Signature) -> bool {
let rec = signature.recover_verifying_key(msg).unwrap();
self.0 == rec
}
}
impl fmt::Display for PublicKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:x}", self)
}
}
impl fmt::Debug for PublicKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "PublicKey \"{:x}\"", self)
}
}
impl fmt::UpperHex for PublicKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", hex::encode_upper(self.to_bytes()))?;
Ok(())
}
}
impl fmt::LowerHex for PublicKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", hex::encode(self.to_bytes()))?;
Ok(())
}
}
impl fmt::Binary for PublicKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let bytes = self.to_bytes();
for byte in bytes.iter() {
write!(f, "{:08b}", byte)?;
}
Ok(())
}
}
impl fmt::Octal for PublicKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let bytes = self.to_bytes();
for byte in bytes.iter() {
write!(f, "{:03o}", byte)?;
}
Ok(())
}
}
impl FromStr for PublicKey {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.trim_start_matches("0x");
let bytes = hex::decode(s).map_err(|_| Error::InvalidHexString)?;
PublicKey::from_slice(&bytes)
}
}