use crate::keys::SecretKey;
use crate::SchnorrError;
use mohan::{
dalek::{
constants,
ristretto::{CompressedRistretto, RistrettoPoint},
scalar::Scalar,
},
ser,
tools::RistrettoBoth,
};
use std::fmt::Debug;
pub const PUBLIC_KEY_LENGTH: usize = 32;
#[derive(Copy, Clone, Default)]
pub struct PublicKey(pub(crate) RistrettoBoth);
impl Debug for PublicKey {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "PublicKey( CompressedRistretto( {:?} ))", self.0)
}
}
impl ::zeroize::Zeroize for PublicKey {
fn zeroize(&mut self) {
self.0.zeroize()
}
}
impl PublicKey {
pub fn as_compressed(&self) -> &CompressedRistretto {
&self.0.as_compressed()
}
pub fn into_compressed(self) -> CompressedRistretto {
self.0.into_compressed()
}
pub fn as_point(&self) -> &RistrettoPoint {
&self.0.as_point()
}
pub fn into_point(self) -> RistrettoPoint {
self.0.into_point()
}
pub fn from_compressed(compressed: CompressedRistretto) -> Result<PublicKey, SchnorrError> {
match RistrettoBoth::from_compressed(compressed) {
None => Err(SchnorrError::PointDecompressionError),
Some(kosher) => Ok(PublicKey(kosher)),
}
}
pub fn from_point(point: RistrettoPoint) -> PublicKey {
PublicKey(RistrettoBoth::from_point(point))
}
#[inline]
pub fn to_bytes(&self) -> [u8; PUBLIC_KEY_LENGTH] {
self.0.to_bytes()
}
#[inline]
pub fn as_bytes<'a>(&'a self) -> &'a [u8; PUBLIC_KEY_LENGTH] {
&self.0.as_compressed().0
}
#[inline]
pub fn from_bytes(bytes: &[u8]) -> Result<PublicKey, SchnorrError> {
match RistrettoBoth::from_bytes(bytes) {
Some(pk) => Ok(PublicKey(pk)),
None => Err(SchnorrError::SerError),
}
}
pub fn from_secret(secret_key: &SecretKey) -> PublicKey {
Self::from_secret_uncompressed(secret_key.as_scalar())
}
pub(crate) fn from_secret_uncompressed(privkey: &Scalar) -> PublicKey {
PublicKey(RistrettoBoth::from_point(
privkey * &constants::RISTRETTO_BASEPOINT_TABLE,
))
}
}
impl From<SecretKey> for PublicKey {
fn from(source: SecretKey) -> PublicKey {
PublicKey::from_secret(&source)
}
}
impl PartialEq for PublicKey {
fn eq(&self, other: &PublicKey) -> bool {
self.as_point() == other.as_point()
}
}
impl Eq for PublicKey {}
impl PartialOrd for PublicKey {
fn partial_cmp(&self, other: &PublicKey) -> Option<std::cmp::Ordering> {
self.partial_cmp(&other)
}
}
impl Ord for PublicKey {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.cmp(&other)
}
}
impl ser::Writeable for PublicKey {
fn write<W: ser::Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
self.0.write(writer)?;
Ok(())
}
}
impl ser::Readable for PublicKey {
fn read(reader: &mut dyn ser::Reader) -> Result<PublicKey, ser::Error> {
Ok(PublicKey(RistrettoBoth::read(reader)?))
}
}