decaf377_rdsa/
verification_key.rs1use core::{
2 cmp::{self, Ord},
3 hash::{Hash, Hasher},
4 marker::PhantomData,
5};
6
7use decaf377::Fr;
8
9use crate::{domain::Sealed, Domain, Error, Signature, SpendAuth};
10
11#[derive(Copy, Clone)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19pub struct VerificationKeyBytes<D: Domain> {
20 pub(crate) bytes: [u8; 32],
21 pub(crate) _marker: PhantomData<D>,
22}
23
24impl<D: Domain> AsRef<[u8; 32]> for VerificationKeyBytes<D> {
25 fn as_ref(&self) -> &[u8; 32] {
26 &self.bytes
27 }
28}
29
30impl<D: Domain> From<[u8; 32]> for VerificationKeyBytes<D> {
31 fn from(bytes: [u8; 32]) -> VerificationKeyBytes<D> {
32 VerificationKeyBytes {
33 bytes,
34 _marker: PhantomData,
35 }
36 }
37}
38
39impl<D: Domain> From<VerificationKeyBytes<D>> for [u8; 32] {
40 fn from(refined: VerificationKeyBytes<D>) -> [u8; 32] {
41 refined.bytes
42 }
43}
44
45impl<D: Domain> Hash for VerificationKeyBytes<D> {
46 fn hash<H: Hasher>(&self, state: &mut H) {
47 self.bytes.hash(state);
48 self._marker.hash(state);
49 }
50}
51
52impl<D: Domain> PartialOrd for VerificationKeyBytes<D> {
53 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
54 self.bytes.partial_cmp(&other.bytes)
55 }
56}
57
58impl<D: Domain> Ord for VerificationKeyBytes<D> {
59 fn cmp(&self, other: &Self) -> cmp::Ordering {
60 self.bytes.cmp(&other.bytes)
61 }
62}
63
64#[derive(Copy, Clone)]
70#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
71#[cfg_attr(feature = "serde", serde(try_from = "VerificationKeyBytes<D>"))]
72#[cfg_attr(feature = "serde", serde(into = "VerificationKeyBytes<D>"))]
73#[cfg_attr(feature = "serde", serde(bound = "D: Domain"))]
74pub struct VerificationKey<D: Domain> {
75 pub(crate) point: decaf377::Element,
76 pub(crate) bytes: VerificationKeyBytes<D>,
77}
78
79impl<D: Domain> Hash for VerificationKey<D> {
80 fn hash<H: Hasher>(&self, state: &mut H) {
81 self.bytes.hash(state);
82 }
83}
84
85impl<D: Domain> PartialOrd for VerificationKey<D> {
86 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
87 self.bytes.partial_cmp(&other.bytes)
88 }
89}
90
91impl<D: Domain> Ord for VerificationKey<D> {
92 fn cmp(&self, other: &Self) -> cmp::Ordering {
93 self.bytes.cmp(&other.bytes)
94 }
95}
96
97impl<D: Domain> From<VerificationKey<D>> for VerificationKeyBytes<D> {
98 fn from(pk: VerificationKey<D>) -> VerificationKeyBytes<D> {
99 pk.bytes
100 }
101}
102
103impl<D: Domain> VerificationKey<D> {
104 pub fn to_bytes(&self) -> [u8; 32] {
108 self.bytes.bytes
109 }
110}
111
112impl<D: Domain> From<VerificationKey<D>> for [u8; 32] {
113 fn from(pk: VerificationKey<D>) -> [u8; 32] {
114 pk.bytes.bytes
115 }
116}
117
118impl<'a, D: Domain> From<&'a VerificationKey<D>> for [u8; 32] {
119 fn from(pk: &'a VerificationKey<D>) -> [u8; 32] {
120 pk.bytes.bytes
121 }
122}
123
124impl<D: Domain> TryFrom<VerificationKeyBytes<D>> for VerificationKey<D> {
125 type Error = Error;
126
127 fn try_from(bytes: VerificationKeyBytes<D>) -> Result<Self, Self::Error> {
128 let point = decaf377::Encoding(bytes.bytes)
130 .vartime_decompress()
131 .map_err(|_| Error::MalformedVerificationKey)?;
132
133 Ok(VerificationKey { point, bytes })
134 }
135}
136
137impl<D: Domain> TryFrom<[u8; 32]> for VerificationKey<D> {
138 type Error = Error;
139
140 fn try_from(bytes: [u8; 32]) -> Result<Self, Self::Error> {
141 VerificationKeyBytes::from(bytes).try_into()
142 }
143}
144
145impl<D: Domain> TryFrom<&[u8]> for VerificationKeyBytes<D> {
146 type Error = Error;
147
148 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
149 if bytes.len() == 32 {
150 let mut bytes32 = [0u8; 32];
151 bytes32.copy_from_slice(&bytes);
152 Ok(bytes32.into())
153 } else {
154 Err(Error::WrongSliceLength {
155 expected: 32,
156 found: bytes.len(),
157 })
158 }
159 }
160}
161
162impl<D: Domain> TryFrom<&[u8]> for VerificationKey<D> {
163 type Error = Error;
164
165 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
166 VerificationKeyBytes::try_from(bytes)?.try_into()
167 }
168}
169
170impl<D: Domain> AsRef<[u8; 32]> for VerificationKey<D> {
171 fn as_ref(&self) -> &[u8; 32] {
172 self.bytes.as_ref()
173 }
174}
175
176impl VerificationKey<SpendAuth> {
177 pub fn randomize(&self, randomizer: &Fr) -> VerificationKey<SpendAuth> {
181 let point = self.point + (SpendAuth::basepoint() * randomizer);
182 let bytes = VerificationKeyBytes {
183 bytes: point.vartime_compress().into(),
184 _marker: PhantomData,
185 };
186 VerificationKey { bytes, point }
187 }
188}
189
190impl<D: Domain> VerificationKey<D> {
191 pub(crate) fn from(s: &Fr) -> VerificationKey<D> {
192 let point = &D::basepoint() * s;
193 let bytes = VerificationKeyBytes {
194 bytes: point.vartime_compress().into(),
195 _marker: PhantomData,
196 };
197 VerificationKey { bytes, point }
198 }
199
200 pub fn verify(&self, msg: &[u8], signature: &Signature<D>) -> Result<(), Error> {
203 use crate::HStar;
204 let c = HStar::default()
205 .update(&signature.r_bytes()[..])
206 .update(&self.bytes.bytes[..]) .update(msg)
208 .finalize();
209 self.verify_prehashed(signature, c)
210 }
211
212 pub fn is_identity(&self) -> bool {
214 self.point == decaf377::Element::IDENTITY
215 }
216
217 #[allow(non_snake_case)]
219 pub(crate) fn verify_prehashed(&self, signature: &Signature<D>, c: Fr) -> Result<(), Error> {
220 let R = decaf377::Encoding(signature.r_bytes())
221 .vartime_decompress()
222 .map_err(|_| Error::InvalidSignature)?;
223
224 let s =
225 Fr::from_bytes_checked(&signature.s_bytes()).map_err(|_| Error::InvalidSignature)?;
226
227 let sB = D::basepoint() * s;
231 let cA = self.point * c;
232 let check = sB - cA - R;
233
234 if check == decaf377::Element::IDENTITY {
235 Ok(())
236 } else {
237 Err(Error::InvalidSignature)
238 }
239 }
240}
241
242impl<D: Domain> PartialEq for VerificationKey<D> {
243 fn eq(&self, other: &Self) -> bool {
244 self.bytes.eq(&other.bytes)
245 }
246}
247
248impl<D: Domain> PartialEq for VerificationKeyBytes<D> {
249 fn eq(&self, other: &Self) -> bool {
250 self.bytes.eq(&other.bytes)
251 }
252}
253
254impl<D: Domain> Eq for VerificationKey<D> {}
255impl<D: Domain> Eq for VerificationKeyBytes<D> {}
256
257#[cfg(feature = "std")]
258mod std_only {
259 use super::*;
260
261 use crate::Binding;
262
263 impl std::fmt::Debug for VerificationKey<Binding> {
264 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
265 f.debug_tuple("VerificationKey<Binding>")
266 .field(&hex::encode(&<[u8; 32]>::from(*self)))
267 .finish()
268 }
269 }
270
271 impl std::fmt::Debug for VerificationKey<SpendAuth> {
272 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
273 f.debug_tuple("VerificationKey<SpendAuth>")
274 .field(&hex::encode(&<[u8; 32]>::from(*self)))
275 .finish()
276 }
277 }
278
279 impl std::fmt::Debug for VerificationKeyBytes<Binding> {
280 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
281 f.debug_tuple("VerificationKeyBytes<Binding>")
282 .field(&hex::encode(&<[u8; 32]>::from(*self)))
283 .finish()
284 }
285 }
286
287 impl std::fmt::Debug for VerificationKeyBytes<SpendAuth> {
288 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
289 f.debug_tuple("VerificationKeyBytes<SpendAuth>")
290 .field(&hex::encode(&<[u8; 32]>::from(*self)))
291 .finish()
292 }
293 }
294}
295
296#[cfg(feature = "std")]
297pub use std_only::*;