use std::{fmt, str::FromStr};
use k256::ecdsa::{recoverable::Signature, signature::Signer, SigningKey};
use rand::RngCore;
use super::{error::Error, public::PublicKey};
#[derive(Clone, PartialEq, Eq)]
pub struct PrivateKey(SigningKey);
impl PrivateKey {
pub fn new() -> PrivateKey {
let mut bytes = [0u8; 32];
rand::thread_rng().fill_bytes(&mut bytes);
PrivateKey(SigningKey::from_bytes(&bytes).unwrap())
}
pub fn from_slice(bytes: &[u8]) -> Result<PrivateKey, Error> {
let key = SigningKey::from_bytes(bytes).map_err(|_| Error::InvalidPrivateKey)?;
Ok(PrivateKey(key))
}
pub fn to_bytes(&self) -> [u8; 32] {
let mut bytes = [0u8; 32];
bytes.copy_from_slice(self.0.to_bytes().as_ref());
bytes
}
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 public(&self) -> PublicKey {
PublicKey::from_private(self)
}
pub fn sign(&self, msg: &[u8]) -> Signature {
self.0.sign(msg)
}
}
impl Default for PrivateKey {
fn default() -> PrivateKey {
PrivateKey::new()
}
}
impl fmt::Display for PrivateKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:x}", self)
}
}
impl fmt::Debug for PrivateKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "PrivateKey \"{:x}\"", self)
}
}
impl fmt::UpperHex for PrivateKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", hex::encode_upper(self.to_bytes()))?;
Ok(())
}
}
impl fmt::LowerHex for PrivateKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", hex::encode(self.to_bytes()))?;
Ok(())
}
}
impl fmt::Binary for PrivateKey {
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 PrivateKey {
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 PrivateKey {
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)?;
PrivateKey::from_slice(&bytes)
}
}