1use crate::{two, Components, Signature, OID};
6use core::cmp::min;
7use digest::Digest;
8use num_bigint::{BigUint, ModInverse};
9use num_traits::One;
10use pkcs8::{
11 der::{
12 asn1::{BitStringRef, UintRef},
13 AnyRef, Decode, Encode,
14 },
15 spki, AlgorithmIdentifierRef, EncodePublicKey, SubjectPublicKeyInfoRef,
16};
17use signature::{hazmat::PrehashVerifier, DigestVerifier, Verifier};
18
19#[derive(Clone, Debug, PartialEq, PartialOrd)]
21#[must_use]
22pub struct VerifyingKey {
23 components: Components,
25
26 y: BigUint,
28}
29
30impl VerifyingKey {
31 pub fn from_components(components: Components, y: BigUint) -> signature::Result<Self> {
33 if y < two() || y.modpow(components.q(), components.p()) != BigUint::one() {
34 return Err(signature::Error::new());
35 }
36
37 Ok(Self { components, y })
38 }
39
40 pub const fn components(&self) -> &Components {
42 &self.components
43 }
44
45 #[must_use]
47 pub const fn y(&self) -> &BigUint {
48 &self.y
49 }
50
51 #[must_use]
53 fn verify_prehashed(&self, hash: &[u8], signature: &Signature) -> Option<bool> {
54 let components = self.components();
55 let (p, q, g) = (components.p(), components.q(), components.g());
56 let (r, s) = (signature.r(), signature.s());
57 let y = self.y();
58
59 if signature.r() >= q || signature.s() >= q {
60 return Some(false);
61 }
62
63 let w = s.mod_inverse(q)?.to_biguint().unwrap();
64
65 let n = q.bits() / 8;
66 let block_size = hash.len(); let z_len = min(n, block_size);
69 let z = BigUint::from_bytes_be(&hash[..z_len]);
70
71 let u1 = (&z * &w) % q;
72 let u2 = (r * &w) % q;
73 let v = (g.modpow(&u1, p) * y.modpow(&u2, p) % p) % q;
74
75 Some(v == *r)
76 }
77}
78
79impl Verifier<Signature> for VerifyingKey {
80 fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), signature::Error> {
81 self.verify_digest(sha2::Sha256::new_with_prefix(msg), signature)
82 }
83}
84
85impl PrehashVerifier<Signature> for VerifyingKey {
86 fn verify_prehash(
87 &self,
88 prehash: &[u8],
89 signature: &Signature,
90 ) -> Result<(), signature::Error> {
91 if let Some(true) = self.verify_prehashed(prehash, signature) {
92 Ok(())
93 } else {
94 Err(signature::Error::new())
95 }
96 }
97}
98
99impl<D> DigestVerifier<D, Signature> for VerifyingKey
100where
101 D: Digest,
102{
103 fn verify_digest(&self, digest: D, signature: &Signature) -> Result<(), signature::Error> {
104 let hash = digest.finalize();
105
106 let is_valid = self
107 .verify_prehashed(&hash, signature)
108 .ok_or_else(signature::Error::new)?;
109
110 if !is_valid {
111 return Err(signature::Error::new());
112 }
113
114 Ok(())
115 }
116}
117
118impl EncodePublicKey for VerifyingKey {
119 fn to_public_key_der(&self) -> spki::Result<spki::Document> {
120 let parameters = self.components.to_der()?;
121 let parameters = AnyRef::from_der(¶meters)?;
122 let algorithm = AlgorithmIdentifierRef {
123 oid: OID,
124 parameters: Some(parameters),
125 };
126
127 let y_bytes = self.y.to_bytes_be();
128 let y = UintRef::new(&y_bytes)?;
129 let public_key = y.to_der()?;
130
131 SubjectPublicKeyInfoRef {
132 algorithm,
133 subject_public_key: BitStringRef::new(0, &public_key)?,
134 }
135 .try_into()
136 }
137}
138
139impl<'a> TryFrom<SubjectPublicKeyInfoRef<'a>> for VerifyingKey {
140 type Error = spki::Error;
141
142 fn try_from(value: SubjectPublicKeyInfoRef<'a>) -> Result<Self, Self::Error> {
143 value.algorithm.assert_algorithm_oid(OID)?;
144
145 let parameters = value.algorithm.parameters_any()?;
146 let components = parameters.decode_as()?;
147 let y = UintRef::from_der(
148 value
149 .subject_public_key
150 .as_bytes()
151 .ok_or(spki::Error::KeyMalformed)?,
152 )?;
153
154 Self::from_components(components, BigUint::from_bytes_be(y.as_bytes()))
155 .map_err(|_| spki::Error::KeyMalformed)
156 }
157}