1use crate::{
4 EcdsaCurve, Error, Result, Signature, SignatureSize,
5 hazmat::{self, DigestAlgorithm, bits2field},
6};
7use core::{cmp::Ordering, fmt::Debug};
8use digest::{Digest, Update};
9use elliptic_curve::{
10 AffinePoint, CurveArithmetic, FieldBytesSize, ProjectivePoint, PublicKey,
11 array::ArraySize,
12 point::PointCompression,
13 sec1::{self, CompressedPoint, FromSec1Point, Sec1Point, ToSec1Point},
14};
15use signature::{DigestVerifier, MultipartVerifier, Verifier, hazmat::PrehashVerifier};
16
17#[cfg(feature = "alloc")]
18use alloc::boxed::Box;
19
20#[cfg(feature = "der")]
21use {crate::der, core::ops::Add};
22
23#[cfg(feature = "pem")]
24use {core::str::FromStr, elliptic_curve::pkcs8::DecodePublicKey};
25
26#[cfg(feature = "pkcs8")]
27use elliptic_curve::pkcs8::{
28 self, AssociatedOid, ObjectIdentifier,
29 der::AnyRef,
30 spki::{
31 self, AlgorithmIdentifier, AssociatedAlgorithmIdentifier, SignatureAlgorithmIdentifier,
32 },
33};
34
35#[cfg(feature = "serde")]
36use serdect::serde::{Deserialize, Serialize, de, ser};
37
38#[cfg(feature = "sha2")]
39use {
40 crate::{
41 ECDSA_SHA224_OID, ECDSA_SHA256_OID, ECDSA_SHA384_OID, ECDSA_SHA512_OID, SignatureWithOid,
42 },
43 sha2::{Sha224, Sha256, Sha384, Sha512},
44};
45
46#[cfg(all(feature = "alloc", feature = "pkcs8"))]
47use elliptic_curve::pkcs8::EncodePublicKey;
48
49#[derive(Clone, Debug)]
75pub struct VerifyingKey<C>
76where
77 C: EcdsaCurve + CurveArithmetic,
78{
79 pub(crate) inner: PublicKey<C>,
80}
81
82impl<C> VerifyingKey<C>
83where
84 C: EcdsaCurve + CurveArithmetic,
85 AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
86 FieldBytesSize<C>: sec1::ModulusSize,
87{
88 pub fn from_sec1_bytes(bytes: &[u8]) -> Result<Self> {
90 PublicKey::from_sec1_bytes(bytes)
91 .map(|pk| Self { inner: pk })
92 .map_err(|_| Error::new())
93 }
94
95 pub fn from_affine(affine: AffinePoint<C>) -> Result<Self> {
100 Ok(Self {
101 inner: PublicKey::from_affine(affine).map_err(|_| Error::new())?,
102 })
103 }
104
105 pub fn from_sec1_point(public_key: &Sec1Point<C>) -> Result<Self> {
107 PublicKey::<C>::from_sec1_point(public_key)
108 .into_option()
109 .map(|public_key| Self { inner: public_key })
110 .ok_or_else(Error::new)
111 }
112
113 pub fn to_sec1_point(&self, compress: bool) -> Sec1Point<C> {
116 self.inner.to_sec1_point(compress)
117 }
118
119 #[cfg(feature = "alloc")]
126 pub fn to_sec1_bytes(&self) -> Box<[u8]>
127 where
128 C: PointCompression,
129 {
130 self.inner.to_sec1_bytes()
131 }
132
133 pub fn as_affine(&self) -> &AffinePoint<C> {
135 self.inner.as_affine()
136 }
137}
138
139impl<C, D> DigestVerifier<D, Signature<C>> for VerifyingKey<C>
144where
145 C: EcdsaCurve + CurveArithmetic,
146 D: Digest + Update,
147 SignatureSize<C>: ArraySize,
148{
149 fn verify_digest<F: Fn(&mut D) -> Result<()>>(
150 &self,
151 f: F,
152 signature: &Signature<C>,
153 ) -> Result<()> {
154 let mut digest = D::new();
155 f(&mut digest)?;
156 self.verify_prehash(&digest.finalize(), signature)
157 }
158}
159
160impl<C> PrehashVerifier<Signature<C>> for VerifyingKey<C>
161where
162 C: EcdsaCurve + CurveArithmetic,
163 SignatureSize<C>: ArraySize,
164{
165 fn verify_prehash(&self, prehash: &[u8], signature: &Signature<C>) -> Result<()> {
166 hazmat::verify_prehashed::<C>(
167 &ProjectivePoint::<C>::from(*self.inner.as_affine()),
168 &bits2field::<C>(prehash)?,
169 signature,
170 )
171 }
172}
173
174impl<C> Verifier<Signature<C>> for VerifyingKey<C>
175where
176 C: EcdsaCurve + CurveArithmetic + DigestAlgorithm,
177 SignatureSize<C>: ArraySize,
178{
179 fn verify(&self, msg: &[u8], signature: &Signature<C>) -> Result<()> {
180 self.multipart_verify(&[msg], signature)
181 }
182}
183
184impl<C> MultipartVerifier<Signature<C>> for VerifyingKey<C>
185where
186 C: EcdsaCurve + CurveArithmetic + DigestAlgorithm,
187 SignatureSize<C>: ArraySize,
188{
189 fn multipart_verify(&self, msg: &[&[u8]], signature: &Signature<C>) -> Result<()> {
190 self.verify_digest(
191 |digest: &mut C::Digest| {
192 msg.iter().for_each(|slice| Update::update(digest, slice));
193 Ok(())
194 },
195 signature,
196 )
197 }
198}
199
200#[cfg(feature = "sha2")]
201impl<C> Verifier<SignatureWithOid<C>> for VerifyingKey<C>
202where
203 C: EcdsaCurve + CurveArithmetic + DigestAlgorithm,
204 SignatureSize<C>: ArraySize,
205{
206 fn verify(&self, msg: &[u8], sig: &SignatureWithOid<C>) -> Result<()> {
207 self.multipart_verify(&[msg], sig)
208 }
209}
210
211#[cfg(feature = "sha2")]
212impl<C> MultipartVerifier<SignatureWithOid<C>> for VerifyingKey<C>
213where
214 C: EcdsaCurve + CurveArithmetic + DigestAlgorithm,
215 SignatureSize<C>: ArraySize,
216{
217 fn multipart_verify(&self, msg: &[&[u8]], sig: &SignatureWithOid<C>) -> Result<()> {
218 match sig.oid() {
219 ECDSA_SHA224_OID => {
220 let mut digest = Sha224::default();
221 msg.iter()
222 .for_each(|slice| Update::update(&mut digest, slice));
223 self.verify_prehash(&digest.finalize(), sig.signature())
224 }
225 ECDSA_SHA256_OID => {
226 let mut digest = Sha256::default();
227 msg.iter()
228 .for_each(|slice| Update::update(&mut digest, slice));
229 self.verify_prehash(&digest.finalize(), sig.signature())
230 }
231 ECDSA_SHA384_OID => {
232 let mut digest = Sha384::default();
233 msg.iter()
234 .for_each(|slice| Update::update(&mut digest, slice));
235 self.verify_prehash(&digest.finalize(), sig.signature())
236 }
237 ECDSA_SHA512_OID => {
238 let mut digest = Sha512::default();
239 msg.iter()
240 .for_each(|slice| Update::update(&mut digest, slice));
241 self.verify_prehash(&digest.finalize(), sig.signature())
242 }
243 _ => Err(Error::new()),
244 }
245 }
246}
247
248#[cfg(feature = "der")]
249impl<C, D> DigestVerifier<D, der::Signature<C>> for VerifyingKey<C>
250where
251 C: EcdsaCurve + CurveArithmetic,
252 D: Digest + Update,
253 SignatureSize<C>: ArraySize,
254 der::MaxSize<C>: ArraySize,
255 <FieldBytesSize<C> as Add>::Output: Add<der::MaxOverhead> + ArraySize,
256{
257 fn verify_digest<F: Fn(&mut D) -> Result<()>>(
258 &self,
259 f: F,
260 signature: &der::Signature<C>,
261 ) -> Result<()> {
262 let signature = Signature::<C>::try_from(signature.clone())?;
263 DigestVerifier::<D, Signature<C>>::verify_digest(self, f, &signature)
264 }
265}
266
267#[cfg(feature = "der")]
268impl<C> PrehashVerifier<der::Signature<C>> for VerifyingKey<C>
269where
270 C: EcdsaCurve + CurveArithmetic,
271 SignatureSize<C>: ArraySize,
272 der::MaxSize<C>: ArraySize,
273 <FieldBytesSize<C> as Add>::Output: Add<der::MaxOverhead> + ArraySize,
274{
275 fn verify_prehash(&self, prehash: &[u8], signature: &der::Signature<C>) -> Result<()> {
276 let signature = Signature::<C>::try_from(signature.clone())?;
277 PrehashVerifier::<Signature<C>>::verify_prehash(self, prehash, &signature)
278 }
279}
280
281#[cfg(feature = "der")]
282impl<C> Verifier<der::Signature<C>> for VerifyingKey<C>
283where
284 C: EcdsaCurve + CurveArithmetic + DigestAlgorithm,
285 SignatureSize<C>: ArraySize,
286 der::MaxSize<C>: ArraySize,
287 <FieldBytesSize<C> as Add>::Output: Add<der::MaxOverhead> + ArraySize,
288{
289 fn verify(&self, msg: &[u8], signature: &der::Signature<C>) -> Result<()> {
290 let signature = Signature::<C>::try_from(signature.clone())?;
291 Verifier::<Signature<C>>::verify(self, msg, &signature)
292 }
293}
294
295#[cfg(feature = "der")]
296impl<C> MultipartVerifier<der::Signature<C>> for VerifyingKey<C>
297where
298 C: EcdsaCurve + CurveArithmetic + DigestAlgorithm,
299 SignatureSize<C>: ArraySize,
300 der::MaxSize<C>: ArraySize,
301 <FieldBytesSize<C> as Add>::Output: Add<der::MaxOverhead> + ArraySize,
302{
303 fn multipart_verify(&self, msg: &[&[u8]], signature: &der::Signature<C>) -> Result<()> {
304 let signature = Signature::<C>::try_from(signature.clone())?;
305 MultipartVerifier::<Signature<C>>::multipart_verify(self, msg, &signature)
306 }
307}
308
309impl<C> AsRef<AffinePoint<C>> for VerifyingKey<C>
314where
315 C: EcdsaCurve + CurveArithmetic,
316 AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
317 FieldBytesSize<C>: sec1::ModulusSize,
318{
319 fn as_ref(&self) -> &AffinePoint<C> {
320 self.as_affine()
321 }
322}
323
324impl<C> Copy for VerifyingKey<C> where C: EcdsaCurve + CurveArithmetic {}
325
326impl<C> From<VerifyingKey<C>> for CompressedPoint<C>
327where
328 C: EcdsaCurve + CurveArithmetic + PointCompression,
329 AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
330 FieldBytesSize<C>: sec1::ModulusSize,
331{
332 fn from(verifying_key: VerifyingKey<C>) -> CompressedPoint<C> {
333 verifying_key.inner.into()
334 }
335}
336
337impl<C> From<&VerifyingKey<C>> for CompressedPoint<C>
338where
339 C: EcdsaCurve + CurveArithmetic + PointCompression,
340 AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
341 FieldBytesSize<C>: sec1::ModulusSize,
342{
343 fn from(verifying_key: &VerifyingKey<C>) -> CompressedPoint<C> {
344 verifying_key.inner.into()
345 }
346}
347
348impl<C> From<VerifyingKey<C>> for Sec1Point<C>
349where
350 C: EcdsaCurve + CurveArithmetic + PointCompression,
351 AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
352 FieldBytesSize<C>: sec1::ModulusSize,
353{
354 fn from(verifying_key: VerifyingKey<C>) -> Sec1Point<C> {
355 verifying_key.inner.into()
356 }
357}
358
359impl<C> From<&VerifyingKey<C>> for Sec1Point<C>
360where
361 C: EcdsaCurve + CurveArithmetic + PointCompression,
362 AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
363 FieldBytesSize<C>: sec1::ModulusSize,
364{
365 fn from(verifying_key: &VerifyingKey<C>) -> Sec1Point<C> {
366 verifying_key.inner.into()
367 }
368}
369
370impl<C> Eq for VerifyingKey<C> where C: EcdsaCurve + CurveArithmetic {}
371
372impl<C> PartialEq for VerifyingKey<C>
373where
374 C: EcdsaCurve + CurveArithmetic,
375{
376 fn eq(&self, other: &Self) -> bool {
377 self.inner.eq(&other.inner)
378 }
379}
380
381impl<C> From<PublicKey<C>> for VerifyingKey<C>
382where
383 C: EcdsaCurve + CurveArithmetic,
384{
385 fn from(public_key: PublicKey<C>) -> VerifyingKey<C> {
386 VerifyingKey { inner: public_key }
387 }
388}
389
390impl<C> From<&PublicKey<C>> for VerifyingKey<C>
391where
392 C: EcdsaCurve + CurveArithmetic,
393{
394 fn from(public_key: &PublicKey<C>) -> VerifyingKey<C> {
395 (*public_key).into()
396 }
397}
398
399impl<C> From<VerifyingKey<C>> for PublicKey<C>
400where
401 C: EcdsaCurve + CurveArithmetic,
402{
403 fn from(verifying_key: VerifyingKey<C>) -> PublicKey<C> {
404 verifying_key.inner
405 }
406}
407
408impl<C> From<&VerifyingKey<C>> for PublicKey<C>
409where
410 C: EcdsaCurve + CurveArithmetic,
411{
412 fn from(verifying_key: &VerifyingKey<C>) -> PublicKey<C> {
413 (*verifying_key).into()
414 }
415}
416
417impl<C> PartialOrd for VerifyingKey<C>
418where
419 C: EcdsaCurve + CurveArithmetic,
420 AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
421 FieldBytesSize<C>: sec1::ModulusSize,
422{
423 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
424 Some(self.cmp(other))
425 }
426}
427
428impl<C> Ord for VerifyingKey<C>
429where
430 C: EcdsaCurve + CurveArithmetic,
431 AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
432 FieldBytesSize<C>: sec1::ModulusSize,
433{
434 fn cmp(&self, other: &Self) -> Ordering {
435 self.inner.cmp(&other.inner)
436 }
437}
438
439impl<C> TryFrom<&[u8]> for VerifyingKey<C>
440where
441 C: EcdsaCurve + CurveArithmetic,
442 AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
443 FieldBytesSize<C>: sec1::ModulusSize,
444{
445 type Error = Error;
446
447 fn try_from(bytes: &[u8]) -> Result<Self> {
448 Self::from_sec1_bytes(bytes)
449 }
450}
451
452#[cfg(feature = "pkcs8")]
453impl<C> AssociatedAlgorithmIdentifier for VerifyingKey<C>
454where
455 C: EcdsaCurve + AssociatedOid + CurveArithmetic,
456 AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
457 FieldBytesSize<C>: sec1::ModulusSize,
458{
459 type Params = ObjectIdentifier;
460
461 const ALGORITHM_IDENTIFIER: AlgorithmIdentifier<ObjectIdentifier> =
462 PublicKey::<C>::ALGORITHM_IDENTIFIER;
463}
464
465#[cfg(feature = "pkcs8")]
466impl<C> SignatureAlgorithmIdentifier for VerifyingKey<C>
467where
468 C: EcdsaCurve + CurveArithmetic,
469 AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
470 FieldBytesSize<C>: sec1::ModulusSize,
471 Signature<C>: AssociatedAlgorithmIdentifier<Params = AnyRef<'static>>,
472{
473 type Params = AnyRef<'static>;
474
475 const SIGNATURE_ALGORITHM_IDENTIFIER: AlgorithmIdentifier<Self::Params> =
476 Signature::<C>::ALGORITHM_IDENTIFIER;
477}
478
479#[cfg(feature = "pkcs8")]
480impl<C> TryFrom<pkcs8::SubjectPublicKeyInfoRef<'_>> for VerifyingKey<C>
481where
482 C: EcdsaCurve + AssociatedOid + CurveArithmetic + PointCompression,
483 AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
484 FieldBytesSize<C>: sec1::ModulusSize,
485{
486 type Error = spki::Error;
487
488 fn try_from(spki: pkcs8::SubjectPublicKeyInfoRef<'_>) -> spki::Result<Self> {
489 PublicKey::try_from(spki).map(|inner| Self { inner })
490 }
491}
492
493#[cfg(all(feature = "alloc", feature = "pkcs8"))]
494impl<C> EncodePublicKey for VerifyingKey<C>
495where
496 C: EcdsaCurve + AssociatedOid + CurveArithmetic + PointCompression,
497 AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
498 FieldBytesSize<C>: sec1::ModulusSize,
499{
500 fn to_public_key_der(&self) -> spki::Result<pkcs8::Document> {
501 self.inner.to_public_key_der()
502 }
503}
504
505#[cfg(feature = "pem")]
506impl<C> FromStr for VerifyingKey<C>
507where
508 C: EcdsaCurve + AssociatedOid + CurveArithmetic + PointCompression,
509 AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
510 FieldBytesSize<C>: sec1::ModulusSize,
511{
512 type Err = Error;
513
514 fn from_str(s: &str) -> Result<Self> {
515 Self::from_public_key_pem(s).map_err(|_| Error::new())
516 }
517}
518
519#[cfg(feature = "serde")]
520impl<C> Serialize for VerifyingKey<C>
521where
522 C: EcdsaCurve + AssociatedOid + CurveArithmetic + PointCompression,
523 AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
524 FieldBytesSize<C>: sec1::ModulusSize,
525{
526 fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
527 where
528 S: ser::Serializer,
529 {
530 self.inner.serialize(serializer)
531 }
532}
533
534#[cfg(feature = "serde")]
535impl<'de, C> Deserialize<'de> for VerifyingKey<C>
536where
537 C: EcdsaCurve + AssociatedOid + CurveArithmetic + PointCompression,
538 AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
539 FieldBytesSize<C>: sec1::ModulusSize,
540{
541 fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
542 where
543 D: de::Deserializer<'de>,
544 {
545 PublicKey::<C>::deserialize(deserializer).map(Into::into)
546 }
547}