use std::fmt::{self, Debug}; #[cfg(any(test, feature = "test-impl"))] use hex::FromHex; use crate::{Challenge, Ciphersuite, Element, Error, Group, Signature}; #[cfg(feature = "serde")] use crate::ElementSerialization; /// A valid verifying key for Schnorr signatures over a FROST [`Ciphersuite::Group`]. #[derive(Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(try_from = "ElementSerialization"))] #[cfg_attr(feature = "serde", serde(into = "ElementSerialization"))] pub struct VerifyingKey where C: Ciphersuite, { pub(crate) element: Element, } impl VerifyingKey where C: Ciphersuite, { // pub(crate) fn from(scalar: &<::Field as Field>::Scalar) -> Self { // let element = ::generator() * *scalar; // VerifyingKey { element } // } /// Create a new VerifyingKey from the given element. #[cfg(feature = "internals")] pub fn new(element: ::Element) -> Self { Self { element } } /// Return the underlying element. #[cfg(feature = "internals")] pub fn to_element(self) -> ::Element { self.element } /// Deserialize from bytes pub fn from_bytes( bytes: ::Serialization, ) -> Result, Error> { ::deserialize(&bytes) .map(|element| VerifyingKey { element }) .map_err(|e| e.into()) } /// Serialize `VerifyingKey` to bytes pub fn to_bytes(&self) -> ::Serialization { ::serialize(&self.element) } /// Verify a purported `signature` with a pre-hashed [`Challenge`] made by this verification /// key. pub(crate) fn verify_prehashed( &self, challenge: Challenge, signature: &Signature, ) -> Result<(), Error> { // Verify check is h * ( - z * B + R + c * A) == 0 // h * ( z * B - c * A - R) == 0 // // where h is the cofactor let zB = C::Group::generator() * signature.z; let cA = self.element * challenge.0; let check = (zB - cA - signature.R) * C::Group::cofactor(); if check == C::Group::identity() { Ok(()) } else { Err(Error::InvalidSignature) } } /// Verify a purported `signature` over `msg` made by this verification key. pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), Error> { C::verify_signature(msg, signature, self) } } impl Debug for VerifyingKey where C: Ciphersuite, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("VerifyingKey") .field(&hex::encode(self.to_bytes())) .finish() } } #[cfg(any(test, feature = "test-impl"))] impl FromHex for VerifyingKey where C: Ciphersuite, { type Error = &'static str; fn from_hex>(hex: T) -> Result { let v: Vec = FromHex::from_hex(hex).map_err(|_| "invalid hex")?; match v.try_into() { Ok(bytes) => Self::from_bytes(bytes).map_err(|_| "malformed verifying key encoding"), Err(_) => Err("malformed verifying key encoding"), } } } #[cfg(feature = "serde")] impl TryFrom> for VerifyingKey where C: Ciphersuite, { type Error = Error; fn try_from(value: ElementSerialization) -> Result { Self::from_bytes(value.0) } } #[cfg(feature = "serde")] impl From> for ElementSerialization where C: Ciphersuite, { fn from(value: VerifyingKey) -> Self { Self(value.to_bytes()) } } // impl From> for ::ElementSerialization { // fn from(pk: VerifyingKey) -> ::ElementSerialization { // pk.bytes.bytes // } // } // impl TryFrom<::ElementSerialization> for VerifyingKey { // type Error = Error; // fn try_from(bytes: [u8; 32]) -> Result { // VerifyingKeyBytes::from(bytes).try_into() // } // }