ironfish_reddsa/
verification_key.rs1use core::{
12 convert::{TryFrom, TryInto},
13 fmt,
14 hash::Hash,
15 marker::PhantomData,
16};
17
18use group::{cofactor::CofactorGroup, ff::PrimeField, GroupEncoding};
19
20use crate::{hex_if_possible, Error, Randomizer, SigType, Signature, SpendAuth};
21
22#[derive(Copy, Clone, Hash, PartialEq, Eq)]
29#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
30pub struct VerificationKeyBytes<T: SigType> {
31 pub(crate) bytes: [u8; 32],
32 pub(crate) _marker: PhantomData<T>,
33}
34
35impl<T: SigType> fmt::Debug for VerificationKeyBytes<T> {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 f.debug_struct("VerificationKeyBytes")
38 .field("bytes", &hex_if_possible(&self.bytes))
39 .finish()
40 }
41}
42
43impl<T: SigType> From<[u8; 32]> for VerificationKeyBytes<T> {
44 fn from(bytes: [u8; 32]) -> VerificationKeyBytes<T> {
45 VerificationKeyBytes {
46 bytes,
47 _marker: PhantomData,
48 }
49 }
50}
51
52impl<T: SigType> From<VerificationKeyBytes<T>> for [u8; 32] {
53 fn from(refined: VerificationKeyBytes<T>) -> [u8; 32] {
54 refined.bytes
55 }
56}
57
58#[derive(PartialEq, Copy, Clone, Debug)]
72#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
73#[cfg_attr(feature = "serde", serde(try_from = "VerificationKeyBytes<T>"))]
74#[cfg_attr(feature = "serde", serde(into = "VerificationKeyBytes<T>"))]
75#[cfg_attr(feature = "serde", serde(bound = "T: SigType"))]
76pub struct VerificationKey<T: SigType> {
77 pub(crate) point: T::Point,
78 pub(crate) bytes: VerificationKeyBytes<T>,
79}
80
81impl<T: SigType> From<VerificationKey<T>> for VerificationKeyBytes<T> {
82 fn from(pk: VerificationKey<T>) -> VerificationKeyBytes<T> {
83 pk.bytes
84 }
85}
86
87impl<T: SigType> From<VerificationKey<T>> for [u8; 32] {
88 fn from(pk: VerificationKey<T>) -> [u8; 32] {
89 pk.bytes.bytes
90 }
91}
92
93impl<T: SigType> TryFrom<VerificationKeyBytes<T>> for VerificationKey<T> {
94 type Error = Error;
95
96 fn try_from(bytes: VerificationKeyBytes<T>) -> Result<Self, Self::Error> {
97 let mut repr = <T::Point as GroupEncoding>::Repr::default();
101 repr.as_mut().copy_from_slice(&bytes.bytes);
102 let maybe_point = T::Point::from_bytes(&repr);
103 if maybe_point.is_some().into() {
104 let point = maybe_point.unwrap();
105 Ok(VerificationKey { point, bytes })
112 } else {
113 Err(Error::MalformedVerificationKey)
114 }
115 }
116}
117
118impl<T: SigType> TryFrom<[u8; 32]> for VerificationKey<T> {
119 type Error = Error;
120
121 fn try_from(bytes: [u8; 32]) -> Result<Self, Self::Error> {
122 VerificationKeyBytes::from(bytes).try_into()
123 }
124}
125
126impl<T: SpendAuth> VerificationKey<T> {
127 pub fn randomize(&self, randomizer: &Randomizer<T>) -> VerificationKey<T> {
131 let point = self.point + (T::basepoint() * randomizer);
132 let bytes = VerificationKeyBytes {
133 bytes: point.to_bytes().as_ref().try_into().unwrap(),
134 _marker: PhantomData,
135 };
136 VerificationKey { bytes, point }
137 }
138}
139
140impl<T: SigType> VerificationKey<T> {
141 pub(crate) fn from(s: &T::Scalar) -> VerificationKey<T> {
142 let point = T::basepoint() * s;
143 let bytes = VerificationKeyBytes {
144 bytes: point.to_bytes().as_ref().try_into().unwrap(),
145 _marker: PhantomData,
146 };
147 VerificationKey { bytes, point }
148 }
149
150 pub fn verify(&self, msg: &[u8], signature: &Signature<T>) -> Result<(), Error> {
153 use crate::HStar;
154 let c = HStar::<T>::default()
155 .update(&signature.r_bytes[..])
156 .update(&self.bytes.bytes[..]) .update(msg)
158 .finalize();
159 self.verify_prehashed(signature, c)
160 }
161
162 #[allow(non_snake_case)]
164 pub(crate) fn verify_prehashed(
165 &self,
166 signature: &Signature<T>,
167 c: T::Scalar,
168 ) -> Result<(), Error> {
169 let r = {
170 let mut repr = <T::Point as GroupEncoding>::Repr::default();
173 repr.as_mut().copy_from_slice(&signature.r_bytes);
174 let maybe_point = T::Point::from_bytes(&repr);
175 if maybe_point.is_some().into() {
176 maybe_point.unwrap()
177 } else {
178 return Err(Error::InvalidSignature);
179 }
180 };
181
182 let s = {
183 let mut repr = <T::Scalar as PrimeField>::Repr::default();
185 repr.as_mut().copy_from_slice(&signature.s_bytes);
186 let maybe_scalar = T::Scalar::from_repr(repr);
187 if maybe_scalar.is_some().into() {
188 maybe_scalar.unwrap()
189 } else {
190 return Err(Error::InvalidSignature);
191 }
192 };
193
194 let sB = T::basepoint() * s;
198 let cA = self.point * c;
199 let check = sB - cA - r;
200
201 if check.is_small_order().into() {
202 Ok(())
203 } else {
204 Err(Error::InvalidSignature)
205 }
206 }
207}