Skip to main content

openssl/
dsa.rs

1//! Digital Signatures
2//!
3//! DSA ensures a message originated from a known sender, and was not modified.
4//! DSA uses asymmetrical keys and an algorithm to output a signature of the message
5//! using the private key that can be validated with the public key but not be generated
6//! without the private key.
7
8use foreign_types::{ForeignType, ForeignTypeRef};
9#[cfg(not(any(boringssl, awslc)))]
10use libc::c_int;
11use std::fmt;
12use std::mem;
13use std::ptr;
14
15use crate::bn::{BigNum, BigNumRef};
16use crate::error::ErrorStack;
17use crate::pkey::{HasParams, HasPrivate, HasPublic, Params, Private, Public};
18use crate::util::ForeignTypeRefExt;
19use crate::{cvt, cvt_p};
20use openssl_macros::corresponds;
21
22generic_foreign_type_and_impl_send_sync! {
23    type CType = ffi::DSA;
24    fn drop = ffi::DSA_free;
25
26    /// Object representing DSA keys.
27    ///
28    /// A DSA object contains the parameters p, q, and g.  There is a private
29    /// and public key.  The values p, g, and q are:
30    ///
31    /// * `p`: DSA prime parameter
32    /// * `q`: DSA sub-prime parameter
33    /// * `g`: DSA base parameter
34    ///
35    /// These values are used to calculate a pair of asymmetrical keys used for
36    /// signing.
37    ///
38    /// OpenSSL documentation at [`DSA_new`]
39    ///
40    /// [`DSA_new`]: https://docs.openssl.org/master/man3/DSA_new/
41    ///
42    /// # Examples
43    ///
44    /// ```
45    /// use openssl::dsa::Dsa;
46    /// use openssl::error::ErrorStack;
47    /// use openssl::pkey::Private;
48    ///
49    /// fn create_dsa() -> Result<Dsa<Private>, ErrorStack> {
50    ///     let sign = Dsa::generate(2048)?;
51    ///     Ok(sign)
52    /// }
53    /// # fn main() {
54    /// #    create_dsa();
55    /// # }
56    /// ```
57    pub struct Dsa<T>;
58    /// Reference to [`Dsa`].
59    ///
60    /// [`Dsa`]: struct.Dsa.html
61    pub struct DsaRef<T>;
62}
63
64impl<T> Clone for Dsa<T> {
65    fn clone(&self) -> Dsa<T> {
66        (**self).to_owned()
67    }
68}
69
70impl<T> ToOwned for DsaRef<T> {
71    type Owned = Dsa<T>;
72
73    fn to_owned(&self) -> Dsa<T> {
74        unsafe {
75            let r = ffi::DSA_up_ref(self.as_ptr());
76            assert!(r == 1);
77            Dsa::from_ptr(self.as_ptr())
78        }
79    }
80}
81
82impl<T> DsaRef<T>
83where
84    T: HasPublic,
85{
86    to_pem! {
87        /// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure.
88        ///
89        /// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
90        #[corresponds(PEM_write_bio_DSA_PUBKEY)]
91        public_key_to_pem,
92        ffi::PEM_write_bio_DSA_PUBKEY
93    }
94
95    to_der! {
96        /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
97        #[corresponds(i2d_DSA_PUBKEY)]
98        public_key_to_der,
99        ffi::i2d_DSA_PUBKEY
100    }
101
102    /// Returns a reference to the public key component of `self`.
103    #[corresponds(DSA_get0_key)]
104    pub fn pub_key(&self) -> &BigNumRef {
105        unsafe {
106            let mut pub_key = ptr::null();
107            DSA_get0_key(self.as_ptr(), &mut pub_key, ptr::null_mut());
108            BigNumRef::from_const_ptr(pub_key)
109        }
110    }
111}
112
113impl<T> DsaRef<T>
114where
115    T: HasPrivate,
116{
117    private_key_to_pem! {
118        /// Serializes the private key to a PEM-encoded DSAPrivateKey structure.
119        ///
120        /// The output will have a header of `-----BEGIN DSA PRIVATE KEY-----`.
121        #[corresponds(PEM_write_bio_DSAPrivateKey)]
122        private_key_to_pem,
123        /// Serializes the private key to a PEM-encoded encrypted DSAPrivateKey structure.
124        ///
125        /// The output will have a header of `-----BEGIN DSA PRIVATE KEY-----`.
126        #[corresponds(PEM_write_bio_DSAPrivateKey)]
127        private_key_to_pem_passphrase,
128        ffi::PEM_write_bio_DSAPrivateKey
129    }
130
131    to_der! {
132        /// Serializes the private_key to a DER-encoded `DSAPrivateKey` structure.
133        #[corresponds(i2d_DSAPrivateKey)]
134        private_key_to_der,
135        ffi::i2d_DSAPrivateKey
136    }
137
138    /// Returns a reference to the private key component of `self`.
139    #[corresponds(DSA_get0_key)]
140    pub fn priv_key(&self) -> &BigNumRef {
141        unsafe {
142            let mut priv_key = ptr::null();
143            DSA_get0_key(self.as_ptr(), ptr::null_mut(), &mut priv_key);
144            BigNumRef::from_const_ptr(priv_key)
145        }
146    }
147}
148
149impl<T> DsaRef<T>
150where
151    T: HasParams,
152{
153    /// Returns the maximum size of the signature output by `self` in bytes.
154    #[corresponds(DSA_size)]
155    pub fn size(&self) -> u32 {
156        unsafe { ffi::DSA_size(self.as_ptr()) as u32 }
157    }
158
159    /// Returns the DSA prime parameter of `self`.
160    ///
161    /// Panics if `self` has no prime parameter set. Use [`DsaRef::p_opt`] to
162    /// handle that case without a panic.
163    #[corresponds(DSA_get0_pqg)]
164    pub fn p(&self) -> &BigNumRef {
165        self.p_opt().expect("DSA has no p parameter")
166    }
167
168    /// Returns the DSA prime parameter of `self`, or `None` if it is not set.
169    #[corresponds(DSA_get0_pqg)]
170    pub fn p_opt(&self) -> Option<&BigNumRef> {
171        unsafe {
172            let mut p = ptr::null();
173            DSA_get0_pqg(self.as_ptr(), &mut p, ptr::null_mut(), ptr::null_mut());
174            BigNumRef::from_const_ptr_opt(p)
175        }
176    }
177
178    /// Returns the DSA sub-prime parameter of `self`.
179    ///
180    /// Panics if `self` has no sub-prime parameter set. Use [`DsaRef::q_opt`]
181    /// to handle that case without a panic.
182    #[corresponds(DSA_get0_pqg)]
183    pub fn q(&self) -> &BigNumRef {
184        self.q_opt().expect("DSA has no q parameter")
185    }
186
187    /// Returns the DSA sub-prime parameter of `self`, or `None` if it is not
188    /// set.
189    #[corresponds(DSA_get0_pqg)]
190    pub fn q_opt(&self) -> Option<&BigNumRef> {
191        unsafe {
192            let mut q = ptr::null();
193            DSA_get0_pqg(self.as_ptr(), ptr::null_mut(), &mut q, ptr::null_mut());
194            BigNumRef::from_const_ptr_opt(q)
195        }
196    }
197
198    /// Returns the DSA base parameter of `self`.
199    ///
200    /// Panics if `self` has no base parameter set. Use [`DsaRef::g_opt`] to
201    /// handle that case without a panic.
202    #[corresponds(DSA_get0_pqg)]
203    pub fn g(&self) -> &BigNumRef {
204        self.g_opt().expect("DSA has no g parameter")
205    }
206
207    /// Returns the DSA base parameter of `self`, or `None` if it is not set.
208    #[corresponds(DSA_get0_pqg)]
209    pub fn g_opt(&self) -> Option<&BigNumRef> {
210        unsafe {
211            let mut g = ptr::null();
212            DSA_get0_pqg(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut g);
213            BigNumRef::from_const_ptr_opt(g)
214        }
215    }
216}
217/// Returns an error if any of the p, q, g parameters are missing.
218///
219/// `d2i_DSA_PUBKEY` accepts a SubjectPublicKeyInfo whose AlgorithmIdentifier
220/// parameters are absent, which leaves the key without p, q and g.
221fn check_pqg<T>(dsa: &DsaRef<T>) -> Result<(), ErrorStack>
222where
223    T: HasParams,
224{
225    if dsa.p_opt().is_none() || dsa.q_opt().is_none() || dsa.g_opt().is_none() {
226        return Err(ErrorStack::get());
227    }
228    Ok(())
229}
230
231#[cfg(any(boringssl, awslc))]
232type BitType = libc::c_uint;
233#[cfg(not(any(boringssl, awslc)))]
234type BitType = c_int;
235
236impl Dsa<Params> {
237    /// Creates a DSA params based upon the given parameters.
238    #[corresponds(DSA_set0_pqg)]
239    pub fn from_pqg(p: BigNum, q: BigNum, g: BigNum) -> Result<Dsa<Params>, ErrorStack> {
240        unsafe {
241            let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
242            cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?;
243            mem::forget((p, q, g));
244            Ok(dsa)
245        }
246    }
247
248    /// Generates DSA params based on the given number of bits.
249    #[corresponds(DSA_generate_parameters_ex)]
250    pub fn generate_params(bits: u32) -> Result<Dsa<Params>, ErrorStack> {
251        ffi::init();
252        unsafe {
253            let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
254            cvt(ffi::DSA_generate_parameters_ex(
255                dsa.0,
256                bits as BitType,
257                ptr::null(),
258                0,
259                ptr::null_mut(),
260                ptr::null_mut(),
261                ptr::null_mut(),
262            ))?;
263            Ok(dsa)
264        }
265    }
266
267    /// Generates a private key based on the DSA params.
268    #[corresponds(DSA_generate_key)]
269    pub fn generate_key(self) -> Result<Dsa<Private>, ErrorStack> {
270        unsafe {
271            let dsa_ptr = self.0;
272            cvt(ffi::DSA_generate_key(dsa_ptr))?;
273            mem::forget(self);
274            Ok(Dsa::from_ptr(dsa_ptr))
275        }
276    }
277}
278
279impl Dsa<Private> {
280    /// Generate a DSA key pair.
281    ///
282    /// The `bits` parameter corresponds to the length of the prime `p`.
283    pub fn generate(bits: u32) -> Result<Dsa<Private>, ErrorStack> {
284        let params = Dsa::generate_params(bits)?;
285        params.generate_key()
286    }
287
288    /// Create a DSA key pair with the given parameters
289    ///
290    /// `p`, `q` and `g` are the common parameters.
291    /// `priv_key` is the private component of the key pair.
292    /// `pub_key` is the public component of the key. Can be computed via `g^(priv_key) mod p`
293    pub fn from_private_components(
294        p: BigNum,
295        q: BigNum,
296        g: BigNum,
297        priv_key: BigNum,
298        pub_key: BigNum,
299    ) -> Result<Dsa<Private>, ErrorStack> {
300        ffi::init();
301        unsafe {
302            let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
303            cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?;
304            mem::forget((p, q, g));
305            cvt(DSA_set0_key(dsa.0, pub_key.as_ptr(), priv_key.as_ptr()))?;
306            mem::forget((pub_key, priv_key));
307            Ok(dsa)
308        }
309    }
310}
311
312impl Dsa<Public> {
313    /// Decodes a PEM-encoded SubjectPublicKeyInfo structure containing a DSA key.
314    ///
315    /// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
316    ///
317    /// A key whose AlgorithmIdentifier carries no DSA parameters is rejected.
318    #[corresponds(PEM_read_bio_DSA_PUBKEY)]
319    pub fn public_key_from_pem(pem: &[u8]) -> Result<Dsa<Public>, ErrorStack> {
320        unsafe {
321            crate::init();
322            let bio = crate::bio::MemBioSlice::new(pem)?;
323            let dsa = cvt_p(ffi::PEM_read_bio_DSA_PUBKEY(
324                bio.as_ptr(),
325                ptr::null_mut(),
326                None,
327                ptr::null_mut(),
328            ))
329            .map(|p| Dsa::from_ptr(p))?;
330            check_pqg(&dsa)?;
331            Ok(dsa)
332        }
333    }
334
335    /// Decodes a DER-encoded SubjectPublicKeyInfo structure containing a DSA key.
336    ///
337    /// A key whose AlgorithmIdentifier carries no DSA parameters is rejected.
338    #[corresponds(d2i_DSA_PUBKEY)]
339    pub fn public_key_from_der(der: &[u8]) -> Result<Dsa<Public>, ErrorStack> {
340        unsafe {
341            ffi::init();
342            let len = ::std::cmp::min(der.len(), libc::c_long::MAX as usize) as libc::c_long;
343            let dsa = cvt_p(ffi::d2i_DSA_PUBKEY(ptr::null_mut(), &mut der.as_ptr(), len))
344                .map(|p| Dsa::from_ptr(p))?;
345            check_pqg(&dsa)?;
346            Ok(dsa)
347        }
348    }
349
350    /// Create a new DSA key with only public components.
351    ///
352    /// `p`, `q` and `g` are the common parameters.
353    /// `pub_key` is the public component of the key.
354    pub fn from_public_components(
355        p: BigNum,
356        q: BigNum,
357        g: BigNum,
358        pub_key: BigNum,
359    ) -> Result<Dsa<Public>, ErrorStack> {
360        ffi::init();
361        unsafe {
362            let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
363            cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?;
364            mem::forget((p, q, g));
365            cvt(DSA_set0_key(dsa.0, pub_key.as_ptr(), ptr::null_mut()))?;
366            mem::forget(pub_key);
367            Ok(dsa)
368        }
369    }
370}
371
372impl<T> fmt::Debug for Dsa<T> {
373    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
374        write!(f, "DSA")
375    }
376}
377
378use ffi::{DSA_get0_key, DSA_get0_pqg, DSA_set0_key, DSA_set0_pqg};
379
380foreign_type_and_impl_send_sync! {
381    type CType = ffi::DSA_SIG;
382    fn drop = ffi::DSA_SIG_free;
383
384    /// Object representing DSA signature.
385    ///
386    /// DSA signatures consist of two components: `r` and `s`.
387    ///
388    /// # Examples
389    ///
390    /// ```
391    /// use std::convert::TryInto;
392    ///
393    /// use openssl::bn::BigNum;
394    /// use openssl::dsa::{Dsa, DsaSig};
395    /// use openssl::hash::MessageDigest;
396    /// use openssl::pkey::PKey;
397    /// use openssl::sign::{Signer, Verifier};
398    ///
399    /// const TEST_DATA: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
400    /// let dsa_ref = Dsa::generate(1024).unwrap();
401    ///
402    /// let pub_key: PKey<_> = dsa_ref.clone().try_into().unwrap();
403    /// let priv_key: PKey<_> = dsa_ref.try_into().unwrap();
404    ///
405    /// let mut signer = if let Ok(signer) = Signer::new(MessageDigest::sha256(), &priv_key) {
406    ///     signer
407    /// } else {
408    ///     // DSA signing is not supported (eg. BoringSSL)
409    ///     return;
410    /// };
411    ///
412    /// signer.update(TEST_DATA).unwrap();
413    ///
414    /// let signature = signer.sign_to_vec().unwrap();
415    /// // Parse DER-encoded DSA signature
416    /// let signature = DsaSig::from_der(&signature).unwrap();
417    ///
418    /// // Extract components `r` and `s`
419    /// let r = BigNum::from_slice(&signature.r().to_vec()).unwrap();
420    /// let s = BigNum::from_slice(&signature.s().to_vec()).unwrap();
421    ///
422    /// // Construct new DSA signature from components
423    /// let signature = DsaSig::from_private_components(r, s).unwrap();
424    ///
425    /// // Serialize DSA signature to DER
426    /// let signature = signature.to_der().unwrap();
427    ///
428    /// let mut verifier = Verifier::new(MessageDigest::sha256(), &pub_key).unwrap();
429    /// verifier.update(TEST_DATA).unwrap();
430    /// assert!(verifier.verify(&signature[..]).unwrap());
431    /// ```
432    pub struct DsaSig;
433
434    /// Reference to a [`DsaSig`].
435    pub struct DsaSigRef;
436}
437
438impl DsaSig {
439    /// Returns a new `DsaSig` by setting the `r` and `s` values associated with an DSA signature.
440    #[corresponds(DSA_SIG_set0)]
441    pub fn from_private_components(r: BigNum, s: BigNum) -> Result<Self, ErrorStack> {
442        unsafe {
443            let sig = cvt_p(ffi::DSA_SIG_new())?;
444            DSA_SIG_set0(sig, r.as_ptr(), s.as_ptr());
445            mem::forget((r, s));
446            Ok(DsaSig::from_ptr(sig))
447        }
448    }
449
450    from_der! {
451        /// Decodes a DER-encoded DSA signature.
452        #[corresponds(d2i_DSA_SIG)]
453        from_der,
454        DsaSig,
455        ffi::d2i_DSA_SIG
456    }
457}
458
459impl fmt::Debug for DsaSig {
460    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
461        f.debug_struct("DsaSig")
462            .field("r", self.r())
463            .field("s", self.s())
464            .finish()
465    }
466}
467
468impl DsaSigRef {
469    to_der! {
470        /// Serializes the DSA signature into a DER-encoded `DSASignature` structure.
471        #[corresponds(i2d_DSA_SIG)]
472        to_der,
473        ffi::i2d_DSA_SIG
474    }
475
476    /// Returns internal component `r` of an `DsaSig`.
477    #[corresponds(DSA_SIG_get0)]
478    pub fn r(&self) -> &BigNumRef {
479        unsafe {
480            let mut r = ptr::null();
481            DSA_SIG_get0(self.as_ptr(), &mut r, ptr::null_mut());
482            BigNumRef::from_const_ptr(r)
483        }
484    }
485
486    /// Returns internal component `s` of an `DsaSig`.
487    #[corresponds(DSA_SIG_get0)]
488    pub fn s(&self) -> &BigNumRef {
489        unsafe {
490            let mut s = ptr::null();
491            DSA_SIG_get0(self.as_ptr(), ptr::null_mut(), &mut s);
492            BigNumRef::from_const_ptr(s)
493        }
494    }
495}
496
497use ffi::{DSA_SIG_get0, DSA_SIG_set0};
498
499#[cfg(test)]
500mod test {
501    use super::*;
502    use crate::bn::BigNumContext;
503    #[cfg(not(any(boringssl, awslc_fips)))]
504    use crate::hash::MessageDigest;
505    #[cfg(not(any(boringssl, awslc_fips)))]
506    use crate::pkey::PKey;
507    #[cfg(not(any(boringssl, awslc_fips)))]
508    use crate::sign::{Signer, Verifier};
509
510    #[test]
511    pub fn test_generate() {
512        Dsa::generate(1024).unwrap();
513    }
514
515    #[test]
516    fn test_pubkey_generation() {
517        let dsa = Dsa::generate(1024).unwrap();
518        let p = dsa.p();
519        let g = dsa.g();
520        let priv_key = dsa.priv_key();
521        let pub_key = dsa.pub_key();
522        let mut ctx = BigNumContext::new().unwrap();
523        let mut calc = BigNum::new().unwrap();
524        calc.mod_exp(g, priv_key, p, &mut ctx).unwrap();
525        assert_eq!(&calc, pub_key)
526    }
527
528    #[test]
529    fn test_priv_key_from_parts() {
530        let p = BigNum::from_u32(283).unwrap();
531        let q = BigNum::from_u32(47).unwrap();
532        let g = BigNum::from_u32(60).unwrap();
533        let priv_key = BigNum::from_u32(15).unwrap();
534        let pub_key = BigNum::from_u32(207).unwrap();
535
536        let dsa = Dsa::from_private_components(p, q, g, priv_key, pub_key).unwrap();
537        assert_eq!(dsa.pub_key(), &BigNum::from_u32(207).unwrap());
538        assert_eq!(dsa.priv_key(), &BigNum::from_u32(15).unwrap());
539        assert_eq!(dsa.p(), &BigNum::from_u32(283).unwrap());
540        assert_eq!(dsa.q(), &BigNum::from_u32(47).unwrap());
541        assert_eq!(dsa.g(), &BigNum::from_u32(60).unwrap());
542    }
543
544    #[test]
545    fn test_pub_key_from_parts() {
546        let p = BigNum::from_u32(283).unwrap();
547        let q = BigNum::from_u32(47).unwrap();
548        let g = BigNum::from_u32(60).unwrap();
549        let pub_key = BigNum::from_u32(207).unwrap();
550
551        let dsa = Dsa::from_public_components(p, q, g, pub_key).unwrap();
552        assert_eq!(dsa.pub_key(), &BigNum::from_u32(207).unwrap());
553        assert_eq!(dsa.p(), &BigNum::from_u32(283).unwrap());
554        assert_eq!(dsa.q(), &BigNum::from_u32(47).unwrap());
555        assert_eq!(dsa.g(), &BigNum::from_u32(60).unwrap());
556    }
557
558    #[test]
559    fn test_params() {
560        let params = Dsa::generate_params(1024).unwrap();
561        let p = params.p().to_owned().unwrap();
562        let q = params.q().to_owned().unwrap();
563        let g = params.g().to_owned().unwrap();
564        let key = params.generate_key().unwrap();
565        let params2 = Dsa::from_pqg(
566            key.p().to_owned().unwrap(),
567            key.q().to_owned().unwrap(),
568            key.g().to_owned().unwrap(),
569        )
570        .unwrap();
571        assert_eq!(p, *params2.p());
572        assert_eq!(q, *params2.q());
573        assert_eq!(g, *params2.g());
574    }
575
576    #[test]
577    #[cfg(not(any(boringssl, awslc_fips)))]
578    fn test_signature() {
579        const TEST_DATA: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
580        let dsa_ref = Dsa::generate(1024).unwrap();
581
582        let p = dsa_ref.p();
583        let q = dsa_ref.q();
584        let g = dsa_ref.g();
585
586        let pub_key = dsa_ref.pub_key();
587        let priv_key = dsa_ref.priv_key();
588
589        let priv_key = Dsa::from_private_components(
590            BigNumRef::to_owned(p).unwrap(),
591            BigNumRef::to_owned(q).unwrap(),
592            BigNumRef::to_owned(g).unwrap(),
593            BigNumRef::to_owned(priv_key).unwrap(),
594            BigNumRef::to_owned(pub_key).unwrap(),
595        )
596        .unwrap();
597        let priv_key = PKey::from_dsa(priv_key).unwrap();
598
599        let pub_key = Dsa::from_public_components(
600            BigNumRef::to_owned(p).unwrap(),
601            BigNumRef::to_owned(q).unwrap(),
602            BigNumRef::to_owned(g).unwrap(),
603            BigNumRef::to_owned(pub_key).unwrap(),
604        )
605        .unwrap();
606        let pub_key = PKey::from_dsa(pub_key).unwrap();
607
608        let mut signer = Signer::new(MessageDigest::sha256(), &priv_key).unwrap();
609        signer.update(TEST_DATA).unwrap();
610
611        let signature = signer.sign_to_vec().unwrap();
612        let mut verifier = Verifier::new(MessageDigest::sha256(), &pub_key).unwrap();
613        verifier.update(TEST_DATA).unwrap();
614        assert!(verifier.verify(&signature[..]).unwrap());
615    }
616
617    #[test]
618    #[cfg(not(any(boringssl, awslc_fips)))]
619    fn test_signature_der() {
620        use std::convert::TryInto;
621
622        const TEST_DATA: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
623        let dsa_ref = Dsa::generate(1024).unwrap();
624
625        let pub_key: PKey<_> = dsa_ref.clone().try_into().unwrap();
626        let priv_key: PKey<_> = dsa_ref.try_into().unwrap();
627
628        let mut signer = Signer::new(MessageDigest::sha256(), &priv_key).unwrap();
629        signer.update(TEST_DATA).unwrap();
630
631        let signature = signer.sign_to_vec().unwrap();
632        eprintln!("{:?}", signature);
633        let signature = DsaSig::from_der(&signature).unwrap();
634
635        let r = BigNum::from_slice(&signature.r().to_vec()).unwrap();
636        let s = BigNum::from_slice(&signature.s().to_vec()).unwrap();
637
638        let signature = DsaSig::from_private_components(r, s).unwrap();
639        let signature = signature.to_der().unwrap();
640
641        let mut verifier = Verifier::new(MessageDigest::sha256(), &pub_key).unwrap();
642        verifier.update(TEST_DATA).unwrap();
643        assert!(verifier.verify(&signature[..]).unwrap());
644    }
645
646    #[test]
647    #[allow(clippy::redundant_clone)]
648    fn clone() {
649        let key = Dsa::generate(2048).unwrap();
650        drop(key.clone());
651    }
652
653    #[test]
654    fn dsa_sig_debug() {
655        let sig = DsaSig::from_der(&[
656            48, 46, 2, 21, 0, 135, 169, 24, 58, 153, 37, 175, 248, 200, 45, 251, 112, 238, 238, 89,
657            172, 177, 182, 166, 237, 2, 21, 0, 159, 146, 151, 237, 187, 8, 82, 115, 14, 183, 103,
658            12, 203, 46, 161, 208, 251, 167, 123, 131,
659        ])
660        .unwrap();
661        let s = format!("{:?}", sig);
662        assert_eq!(s, "DsaSig { r: 774484690634577222213819810519929266740561094381, s: 910998676210681457251421818099943952372231273347 }");
663    }
664
665    /// A DER SubjectPublicKeyInfo with algorithm id-dsa and ABSENT parameters.
666    const DSA_SPKI_NO_PARAMS: &[u8] = &[
667        0x30, 0x11, 0x30, 0x09, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x38, 0x04, 0x01, 0x03, 0x04,
668        0x00, 0x02, 0x01, 0x05,
669    ];
670
671    fn dsa_without_params() -> Dsa<Params> {
672        unsafe {
673            ffi::init();
674            Dsa::from_ptr(cvt_p(ffi::DSA_new()).unwrap())
675        }
676    }
677
678    #[test]
679    fn public_key_from_der_rejects_missing_params() {
680        assert!(Dsa::public_key_from_der(DSA_SPKI_NO_PARAMS).is_err());
681    }
682
683    #[test]
684    fn p_opt_is_none_without_params() {
685        let dsa = dsa_without_params();
686        assert!(dsa.p_opt().is_none());
687        assert!(dsa.q_opt().is_none());
688        assert!(dsa.g_opt().is_none());
689    }
690
691    #[test]
692    #[should_panic(expected = "DSA has no p parameter")]
693    fn p_panics_without_params() {
694        dsa_without_params().p();
695    }
696}