frost_core/
verifying_key.rs1use core::fmt::{self, Debug};
2
3use alloc::{string::ToString, vec::Vec};
4
5#[cfg(any(test, feature = "test-impl"))]
6use hex::FromHex;
7
8use crate::{serialization::SerializableElement, Challenge, Ciphersuite, Error, Group, Signature};
9
10#[derive(Copy, Clone, PartialEq, Eq)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13#[cfg_attr(feature = "serde", serde(bound = "C: Ciphersuite"))]
14#[cfg_attr(feature = "serde", serde(transparent))]
15pub struct VerifyingKey<C>
16where
17 C: Ciphersuite,
18{
19 pub(crate) element: SerializableElement<C>,
20}
21
22impl<C> VerifyingKey<C>
23where
24 C: Ciphersuite,
25{
26 #[cfg_attr(feature = "internals", visibility::make(pub))]
28 #[cfg_attr(docsrs, doc(cfg(feature = "internals")))]
29 pub(crate) fn new(element: <C::Group as Group>::Element) -> Self {
30 Self {
31 element: SerializableElement(element),
32 }
33 }
34
35 #[cfg_attr(feature = "internals", visibility::make(pub))]
37 #[cfg_attr(docsrs, doc(cfg(feature = "internals")))]
38 pub(crate) fn to_element(self) -> <C::Group as Group>::Element {
39 self.element.0
40 }
41
42 pub fn deserialize(bytes: &[u8]) -> Result<VerifyingKey<C>, Error<C>> {
44 Ok(Self::new(SerializableElement::deserialize(bytes)?.0))
45 }
46
47 pub fn serialize(&self) -> Result<Vec<u8>, Error<C>> {
49 self.element.serialize()
50 }
51
52 #[cfg_attr(feature = "internals", visibility::make(pub))]
55 #[cfg_attr(docsrs, doc(cfg(feature = "internals")))]
56 pub(crate) fn verify_prehashed(
57 &self,
58 challenge: Challenge<C>,
59 signature: &Signature<C>,
60 ) -> Result<(), Error<C>> {
61 let zB = C::Group::generator() * signature.z;
66 let cA = self.element.0 * challenge.0;
67 let check = (zB - cA - signature.R) * C::Group::cofactor();
68
69 if check == C::Group::identity() {
70 Ok(())
71 } else {
72 Err(Error::InvalidSignature)
73 }
74 }
75
76 pub fn verify(&self, msg: &[u8], signature: &Signature<C>) -> Result<(), Error<C>> {
78 C::verify_signature(msg, signature, self)
79 }
80
81 #[cfg_attr(feature = "internals", visibility::make(pub))]
83 pub(crate) fn from_commitment(
84 commitment: &crate::keys::VerifiableSecretSharingCommitment<C>,
85 ) -> Result<VerifyingKey<C>, Error<C>> {
86 Ok(VerifyingKey::new(
87 commitment
88 .coefficients()
89 .first()
90 .ok_or(Error::IncorrectCommitment)?
91 .value(),
92 ))
93 }
94}
95
96impl<C> Debug for VerifyingKey<C>
97where
98 C: Ciphersuite,
99{
100 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101 f.debug_tuple("VerifyingKey")
102 .field(
103 &self
104 .serialize()
105 .map(hex::encode)
106 .unwrap_or("<invalid>".to_string()),
107 )
108 .finish()
109 }
110}
111
112#[cfg(any(test, feature = "test-impl"))]
113impl<C> FromHex for VerifyingKey<C>
114where
115 C: Ciphersuite,
116{
117 type Error = &'static str;
118
119 fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
120 let v: Vec<u8> = FromHex::from_hex(hex).map_err(|_| "invalid hex")?;
121 Self::deserialize(&v).map_err(|_| "malformed verifying key encoding")
122 }
123}