use std::fmt::{self, Debug}; use hex::FromHex; use crate::{Ciphersuite, Error, Group, Signature}; /// A valid verifying key for Schnorr signatures over a FROST [`Ciphersuite::Group`]. #[derive(Copy, Clone, PartialEq)] 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 } // } /// Deserialize from bytes pub fn from_bytes(bytes: ::Serialization) -> Result, Error> { ::deserialize(&bytes).map(|element| VerifyingKey { element }) } /// Serialize `VerifyingKey` to bytes pub fn to_bytes(&self) -> ::Serialization { ::serialize(&self.element) } /// Verify a purported `signature` over `msg` made by this verification key. pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), Error> { let c = crate::challenge::(&signature.R, &self.element, msg); // 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 * c.0; let check = (zB - cA - signature.R) * C::Group::cofactor(); if check == C::Group::identity() { Ok(()) } else { Err(Error::InvalidSignature) } } } 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() } } impl FromHex for VerifyingKey where C: Ciphersuite, { type Error = &'static str; fn from_hex>(hex: T) -> Result { match FromHex::from_hex(hex) { Ok(bytes) => Self::from_bytes(bytes).map_err(|_| "malformed verifying key encoding"), Err(_) => Err("invalid hex"), } } } // 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() // } // }