1use crate::{
4 hazmat::{DigestPrimitive, FromDigest, VerifyPrimitive},
5 Error, Result, Signature, SignatureSize,
6};
7use core::{cmp::Ordering, convert::TryFrom, fmt::Debug, ops::Add};
8use elliptic_curve_flow::{
9 consts::U1,
10 generic_array::ArrayLength,
11 sec1::{
12 EncodedPoint, FromEncodedPoint, ToEncodedPoint, UncompressedPointSize, UntaggedPointSize,
13 },
14 AffinePoint, FieldSize, PointCompression, PrimeCurve, ProjectiveArithmetic, PublicKey, Scalar,
15};
16use signature_flow::{digest::Digest, DigestVerifier, Verifier};
17
18#[cfg(feature = "pkcs8")]
19use crate::elliptic_curve_flow::{
20 pkcs8::{self, FromPublicKey},
21 AlgorithmParameters,
22};
23
24#[cfg(feature = "pem")]
25use core::str::FromStr;
26
27#[cfg_attr(docsrs, doc(cfg(feature = "verify")))]
32#[derive(Clone, Debug)]
33pub struct VerifyingKey<C>
34where
35 C: PrimeCurve + ProjectiveArithmetic,
36{
37 pub(crate) inner: PublicKey<C>,
38}
39
40impl<C> VerifyingKey<C>
41where
42 C: PrimeCurve + ProjectiveArithmetic,
43 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
44 UntaggedPointSize<C>: Add<U1> + ArrayLength<u8>,
45 UncompressedPointSize<C>: ArrayLength<u8>,
46{
47 pub fn from_sec1_bytes(bytes: &[u8]) -> Result<Self> {
49 PublicKey::from_sec1_bytes(bytes)
50 .map(|pk| Self { inner: pk })
51 .map_err(|_| Error::new())
52 }
53
54 pub fn from_encoded_point(public_key: &EncodedPoint<C>) -> Result<Self> {
56 PublicKey::<C>::from_encoded_point(public_key)
57 .map(|public_key| Self { inner: public_key })
58 .ok_or_else(Error::new)
59 }
60
61 pub fn to_encoded_point(&self, compress: bool) -> EncodedPoint<C> {
64 self.inner.to_encoded_point(compress)
65 }
66}
67
68impl<C> Copy for VerifyingKey<C> where C: PrimeCurve + ProjectiveArithmetic {}
69
70impl<C, D> DigestVerifier<D, Signature<C>> for VerifyingKey<C>
71where
72 C: PrimeCurve + ProjectiveArithmetic,
73 D: Digest<OutputSize = FieldSize<C>>,
74 AffinePoint<C>: VerifyPrimitive<C>,
75 Scalar<C>: FromDigest<C>,
76 SignatureSize<C>: ArrayLength<u8>,
77{
78 fn verify_digest(&self, digest: D, signature: &Signature<C>) -> Result<()> {
79 self.inner
80 .as_affine()
81 .verify_prehashed(&Scalar::<C>::from_digest(digest), signature)
82 }
83}
84
85impl<C> Verifier<Signature<C>> for VerifyingKey<C>
86where
87 C: PrimeCurve + ProjectiveArithmetic + DigestPrimitive,
88 C::Digest: Digest<OutputSize = FieldSize<C>>,
89 AffinePoint<C>: VerifyPrimitive<C>,
90 Scalar<C>: FromDigest<C>,
91 SignatureSize<C>: ArrayLength<u8>,
92{
93 fn verify(&self, msg: &[u8], signature: &Signature<C>) -> Result<()> {
94 self.verify_digest(C::Digest::new().chain(msg), signature)
95 }
96}
97
98impl<C> From<&VerifyingKey<C>> for EncodedPoint<C>
99where
100 C: PrimeCurve + ProjectiveArithmetic + PointCompression,
101 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
102 UntaggedPointSize<C>: Add<U1> + ArrayLength<u8>,
103 UncompressedPointSize<C>: ArrayLength<u8>,
104{
105 fn from(verifying_key: &VerifyingKey<C>) -> EncodedPoint<C> {
106 verifying_key.to_encoded_point(C::COMPRESS_POINTS)
107 }
108}
109
110impl<C> From<PublicKey<C>> for VerifyingKey<C>
111where
112 C: PrimeCurve + ProjectiveArithmetic,
113{
114 fn from(public_key: PublicKey<C>) -> VerifyingKey<C> {
115 VerifyingKey { inner: public_key }
116 }
117}
118
119impl<C> From<&PublicKey<C>> for VerifyingKey<C>
120where
121 C: PrimeCurve + ProjectiveArithmetic,
122{
123 fn from(public_key: &PublicKey<C>) -> VerifyingKey<C> {
124 public_key.clone().into()
125 }
126}
127
128impl<C> From<VerifyingKey<C>> for PublicKey<C>
129where
130 C: PrimeCurve + ProjectiveArithmetic,
131{
132 fn from(verifying_key: VerifyingKey<C>) -> PublicKey<C> {
133 verifying_key.inner
134 }
135}
136
137impl<C> From<&VerifyingKey<C>> for PublicKey<C>
138where
139 C: PrimeCurve + ProjectiveArithmetic,
140{
141 fn from(verifying_key: &VerifyingKey<C>) -> PublicKey<C> {
142 verifying_key.clone().into()
143 }
144}
145
146impl<C> Eq for VerifyingKey<C>
147where
148 C: PrimeCurve + ProjectiveArithmetic,
149 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
150 UntaggedPointSize<C>: Add<U1> + ArrayLength<u8>,
151 UncompressedPointSize<C>: ArrayLength<u8>,
152{
153}
154
155impl<C> PartialEq for VerifyingKey<C>
156where
157 C: PrimeCurve + ProjectiveArithmetic,
158 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
159 UntaggedPointSize<C>: Add<U1> + ArrayLength<u8>,
160 UncompressedPointSize<C>: ArrayLength<u8>,
161{
162 fn eq(&self, other: &Self) -> bool {
163 self.inner.eq(&other.inner)
164 }
165}
166
167impl<C> PartialOrd for VerifyingKey<C>
168where
169 C: PrimeCurve + ProjectiveArithmetic,
170 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
171 UntaggedPointSize<C>: Add<U1> + ArrayLength<u8>,
172 UncompressedPointSize<C>: ArrayLength<u8>,
173{
174 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
175 self.inner.partial_cmp(&other.inner)
176 }
177}
178
179impl<C> Ord for VerifyingKey<C>
180where
181 C: PrimeCurve + ProjectiveArithmetic,
182 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
183 UntaggedPointSize<C>: Add<U1> + ArrayLength<u8>,
184 UncompressedPointSize<C>: ArrayLength<u8>,
185{
186 fn cmp(&self, other: &Self) -> Ordering {
187 self.inner.cmp(&other.inner)
188 }
189}
190
191impl<C> TryFrom<&[u8]> for VerifyingKey<C>
192where
193 C: PrimeCurve + ProjectiveArithmetic,
194 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
195 UntaggedPointSize<C>: Add<U1> + ArrayLength<u8>,
196 UncompressedPointSize<C>: ArrayLength<u8>,
197{
198 type Error = Error;
199
200 fn try_from(bytes: &[u8]) -> Result<Self> {
201 Self::from_sec1_bytes(bytes)
202 }
203}
204
205#[cfg(feature = "pkcs8")]
206#[cfg_attr(docsrs, doc(cfg(feature = "pkcs8")))]
207impl<C> FromPublicKey for VerifyingKey<C>
208where
209 C: PrimeCurve + AlgorithmParameters + ProjectiveArithmetic + PointCompression,
210 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
211 UntaggedPointSize<C>: Add<U1> + ArrayLength<u8>,
212 UncompressedPointSize<C>: ArrayLength<u8>,
213{
214 fn from_spki(spki: pkcs8::SubjectPublicKeyInfo<'_>) -> pkcs8::Result<Self> {
215 PublicKey::from_spki(spki).map(|inner| Self { inner })
216 }
217}
218
219#[cfg(feature = "pem")]
220#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
221impl<C> FromStr for VerifyingKey<C>
222where
223 C: PrimeCurve + AlgorithmParameters + ProjectiveArithmetic + PointCompression,
224 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
225 UntaggedPointSize<C>: Add<U1> + ArrayLength<u8>,
226 UncompressedPointSize<C>: ArrayLength<u8>,
227{
228 type Err = Error;
229
230 fn from_str(s: &str) -> Result<Self> {
231 Self::from_public_key_pem(s).map_err(|_| Error::new())
232 }
233}