dsa/
verifying_key.rs

1//!
2//! Module containing the definition of the public key container
3//!
4
5use 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/// DSA public key.
20#[derive(Clone, Debug, PartialEq, PartialOrd)]
21#[must_use]
22pub struct VerifyingKey {
23    /// common components
24    components: Components,
25
26    /// Public component y
27    y: BigUint,
28}
29
30impl VerifyingKey {
31    /// Construct a new public key from the common components and the public component
32    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    /// DSA common components
41    pub const fn components(&self) -> &Components {
42        &self.components
43    }
44
45    /// DSA public component
46    #[must_use]
47    pub const fn y(&self) -> &BigUint {
48        &self.y
49    }
50
51    /// Verify some prehashed data
52    #[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(); // Hash function output size
67
68        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(&parameters)?;
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}