3 //! DSA ensures a message originated from a known sender, and was not modified.
4 //! DSA uses asymetrical 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.
9 use foreign_types
::{ForeignType, ForeignTypeRef}
;
15 use crate::bn
::{BigNum, BigNumRef}
;
16 use crate::error
::ErrorStack
;
17 use crate::pkey
::{HasParams, HasPrivate, HasPublic, Private, Public}
;
18 use crate::util
::ForeignTypeRefExt
;
19 use crate::{cvt, cvt_p}
;
21 generic_foreign_type_and_impl_send_sync
! {
22 type CType
= ffi
::DSA
;
23 fn drop
= ffi
::DSA_free
;
25 /// Object representing DSA keys.
27 /// A DSA object contains the parameters p, q, and g. There is a private
28 /// and public key. The values p, g, and q are:
30 /// * `p`: DSA prime parameter
31 /// * `q`: DSA sub-prime parameter
32 /// * `g`: DSA base parameter
34 /// These values are used to calculate a pair of asymetrical keys used for
37 /// OpenSSL documentation at [`DSA_new`]
39 /// [`DSA_new`]: https://www.openssl.org/docs/man1.1.0/crypto/DSA_new.html
44 /// use openssl::dsa::Dsa;
45 /// use openssl::error::ErrorStack;
46 /// use openssl::pkey::Private;
48 /// fn create_dsa() -> Result<Dsa<Private>, ErrorStack> {
49 /// let sign = Dsa::generate(2048)?;
57 /// Reference to [`Dsa`].
59 /// [`Dsa`]: struct.Dsa.html
63 impl<T
> Clone
for Dsa
<T
> {
64 fn clone(&self) -> Dsa
<T
> {
69 impl<T
> ToOwned
for DsaRef
<T
> {
72 fn to_owned(&self) -> Dsa
<T
> {
74 ffi
::DSA_up_ref(self.as_ptr());
75 Dsa
::from_ptr(self.as_ptr())
85 /// Serialies the public key into a PEM-encoded SubjectPublicKeyInfo structure.
87 /// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
89 /// This corresponds to [`PEM_write_bio_DSA_PUBKEY`].
91 /// [`PEM_write_bio_DSA_PUBKEY`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_DSA_PUBKEY.html
93 ffi
::PEM_write_bio_DSA_PUBKEY
97 /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
99 /// This corresponds to [`i2d_DSA_PUBKEY`].
101 /// [`i2d_DSA_PUBKEY`]: https://www.openssl.org/docs/man1.1.0/crypto/i2d_DSA_PUBKEY.html
106 /// Returns a reference to the public key component of `self`.
107 pub fn pub_key(&self) -> &BigNumRef
{
109 let mut pub_key
= ptr
::null();
110 DSA_get0_key(self.as_ptr(), &mut pub_key
, ptr
::null_mut());
111 BigNumRef
::from_const_ptr(pub_key
)
120 private_key_to_pem
! {
121 /// Serializes the private key to a PEM-encoded DSAPrivateKey structure.
123 /// The output will have a header of `-----BEGIN DSA PRIVATE KEY-----`.
125 /// This corresponds to [`PEM_write_bio_DSAPrivateKey`].
127 /// [`PEM_write_bio_DSAPrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_DSAPrivateKey.html
129 /// Serializes the private key to a PEM-encoded encrypted DSAPrivateKey structure.
131 /// The output will have a header of `-----BEGIN DSA PRIVATE KEY-----`.
133 /// This corresponds to [`PEM_write_bio_DSAPrivateKey`].
135 /// [`PEM_write_bio_DSAPrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_DSAPrivateKey.html
136 private_key_to_pem_passphrase
,
137 ffi
::PEM_write_bio_DSAPrivateKey
140 /// Returns a reference to the private key component of `self`.
141 pub fn priv_key(&self) -> &BigNumRef
{
143 let mut priv_key
= ptr
::null();
144 DSA_get0_key(self.as_ptr(), ptr
::null_mut(), &mut priv_key
);
145 BigNumRef
::from_const_ptr(priv_key
)
154 /// Returns the maximum size of the signature output by `self` in bytes.
156 /// OpenSSL documentation at [`DSA_size`]
158 /// [`DSA_size`]: https://www.openssl.org/docs/man1.1.0/crypto/DSA_size.html
159 pub fn size(&self) -> u32 {
160 unsafe { ffi::DSA_size(self.as_ptr()) as u32 }
163 /// Returns the DSA prime parameter of `self`.
164 pub fn p(&self) -> &BigNumRef
{
166 let mut p
= ptr
::null();
167 DSA_get0_pqg(self.as_ptr(), &mut p
, ptr
::null_mut(), ptr
::null_mut());
168 BigNumRef
::from_const_ptr(p
)
172 /// Returns the DSA sub-prime parameter of `self`.
173 pub fn q(&self) -> &BigNumRef
{
175 let mut q
= ptr
::null();
176 DSA_get0_pqg(self.as_ptr(), ptr
::null_mut(), &mut q
, ptr
::null_mut());
177 BigNumRef
::from_const_ptr(q
)
181 /// Returns the DSA base parameter of `self`.
182 pub fn g(&self) -> &BigNumRef
{
184 let mut g
= ptr
::null();
185 DSA_get0_pqg(self.as_ptr(), ptr
::null_mut(), ptr
::null_mut(), &mut g
);
186 BigNumRef
::from_const_ptr(g
)
192 /// Generate a DSA key pair.
194 /// Calls [`DSA_generate_parameters_ex`] to populate the `p`, `g`, and `q` values.
195 /// These values are used to generate the key pair with [`DSA_generate_key`].
197 /// The `bits` parameter corresponds to the length of the prime `p`.
199 /// [`DSA_generate_parameters_ex`]: https://www.openssl.org/docs/man1.1.0/crypto/DSA_generate_parameters_ex.html
200 /// [`DSA_generate_key`]: https://www.openssl.org/docs/man1.1.0/crypto/DSA_generate_key.html
201 pub fn generate(bits
: u32) -> Result
<Dsa
<Private
>, ErrorStack
> {
204 let dsa
= Dsa
::from_ptr(cvt_p(ffi
::DSA_new())?
);
205 cvt(ffi
::DSA_generate_parameters_ex(
214 cvt(ffi
::DSA_generate_key(dsa
.0))?
;
219 /// Create a DSA key pair with the given parameters
221 /// `p`, `q` and `g` are the common parameters.
222 /// `priv_key` is the private component of the key pair.
223 /// `pub_key` is the public component of the key. Can be computed via `g^(priv_key) mod p`
224 pub fn from_private_components(
230 ) -> Result
<Dsa
<Private
>, ErrorStack
> {
233 let dsa
= Dsa
::from_ptr(cvt_p(ffi
::DSA_new())?
);
234 cvt(DSA_set0_pqg(dsa
.0, p
.as_ptr(), q
.as_ptr(), g
.as_ptr()))?
;
235 mem
::forget((p
, q
, g
));
236 cvt(DSA_set0_key(dsa
.0, pub_key
.as_ptr(), priv_key
.as_ptr()))?
;
237 mem
::forget((pub_key
, priv_key
));
245 /// Decodes a PEM-encoded SubjectPublicKeyInfo structure containing a DSA key.
247 /// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
249 /// This corresponds to [`PEM_read_bio_DSA_PUBKEY`].
251 /// [`PEM_read_bio_DSA_PUBKEY`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_DSA_PUBKEY.html
254 ffi
::PEM_read_bio_DSA_PUBKEY
258 /// Decodes a DER-encoded SubjectPublicKeyInfo structure containing a DSA key.
260 /// This corresponds to [`d2i_DSA_PUBKEY`].
262 /// [`d2i_DSA_PUBKEY`]: https://www.openssl.org/docs/man1.0.2/crypto/d2i_DSA_PUBKEY.html
268 /// Create a new DSA key with only public components.
270 /// `p`, `q` and `g` are the common parameters.
271 /// `pub_key` is the public component of the key.
272 pub fn from_public_components(
277 ) -> Result
<Dsa
<Public
>, ErrorStack
> {
280 let dsa
= Dsa
::from_ptr(cvt_p(ffi
::DSA_new())?
);
281 cvt(DSA_set0_pqg(dsa
.0, p
.as_ptr(), q
.as_ptr(), g
.as_ptr()))?
;
282 mem
::forget((p
, q
, g
));
283 cvt(DSA_set0_key(dsa
.0, pub_key
.as_ptr(), ptr
::null_mut()))?
;
284 mem
::forget(pub_key
);
290 impl<T
> fmt
::Debug
for Dsa
<T
> {
291 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
297 if #[cfg(any(ossl110, libressl273))] {
298 use ffi
::{DSA_get0_key, DSA_get0_pqg, DSA_set0_key, DSA_set0_pqg}
;
301 unsafe fn DSA_get0_pqg(
303 p
: *mut *const ffi
::BIGNUM
,
304 q
: *mut *const ffi
::BIGNUM
,
305 g
: *mut *const ffi
::BIGNUM
)
319 unsafe fn DSA_get0_key(
321 pub_key
: *mut *const ffi
::BIGNUM
,
322 priv_key
: *mut *const ffi
::BIGNUM
)
324 if !pub_key
.is_null() {
325 *pub_key
= (*d
).pub_key
;
327 if !priv_key
.is_null() {
328 *priv_key
= (*d
).priv_key
;
333 unsafe fn DSA_set0_key(
335 pub_key
: *mut ffi
::BIGNUM
,
336 priv_key
: *mut ffi
::BIGNUM
) -> c_int
338 (*d
).pub_key
= pub_key
;
339 (*d
).priv_key
= priv_key
;
344 unsafe fn DSA_set0_pqg(
348 g
: *mut ffi
::BIGNUM
) -> c_int
361 use crate::bn
::BigNumContext
;
362 use crate::hash
::MessageDigest
;
363 use crate::pkey
::PKey
;
364 use crate::sign
::{Signer, Verifier}
;
367 pub fn test_generate() {
368 Dsa
::generate(1024).unwrap();
372 fn test_pubkey_generation() {
373 let dsa
= Dsa
::generate(1024).unwrap();
376 let priv_key
= dsa
.priv_key();
377 let pub_key
= dsa
.pub_key();
378 let mut ctx
= BigNumContext
::new().unwrap();
379 let mut calc
= BigNum
::new().unwrap();
380 calc
.mod_exp(g
, priv_key
, p
, &mut ctx
).unwrap();
381 assert_eq
!(&calc
, pub_key
)
385 fn test_priv_key_from_parts() {
386 let p
= BigNum
::from_u32(283).unwrap();
387 let q
= BigNum
::from_u32(47).unwrap();
388 let g
= BigNum
::from_u32(60).unwrap();
389 let priv_key
= BigNum
::from_u32(15).unwrap();
390 let pub_key
= BigNum
::from_u32(207).unwrap();
392 let dsa
= Dsa
::from_private_components(p
, q
, g
, priv_key
, pub_key
).unwrap();
393 assert_eq
!(dsa
.pub_key(), &BigNum
::from_u32(207).unwrap());
394 assert_eq
!(dsa
.priv_key(), &BigNum
::from_u32(15).unwrap());
395 assert_eq
!(dsa
.p(), &BigNum
::from_u32(283).unwrap());
396 assert_eq
!(dsa
.q(), &BigNum
::from_u32(47).unwrap());
397 assert_eq
!(dsa
.g(), &BigNum
::from_u32(60).unwrap());
401 fn test_pub_key_from_parts() {
402 let p
= BigNum
::from_u32(283).unwrap();
403 let q
= BigNum
::from_u32(47).unwrap();
404 let g
= BigNum
::from_u32(60).unwrap();
405 let pub_key
= BigNum
::from_u32(207).unwrap();
407 let dsa
= Dsa
::from_public_components(p
, q
, g
, pub_key
).unwrap();
408 assert_eq
!(dsa
.pub_key(), &BigNum
::from_u32(207).unwrap());
409 assert_eq
!(dsa
.p(), &BigNum
::from_u32(283).unwrap());
410 assert_eq
!(dsa
.q(), &BigNum
::from_u32(47).unwrap());
411 assert_eq
!(dsa
.g(), &BigNum
::from_u32(60).unwrap());
415 fn test_signature() {
416 const TEST_DATA
: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
417 let dsa_ref
= Dsa
::generate(1024).unwrap();
423 let pub_key
= dsa_ref
.pub_key();
424 let priv_key
= dsa_ref
.priv_key();
426 let priv_key
= Dsa
::from_private_components(
427 BigNumRef
::to_owned(p
).unwrap(),
428 BigNumRef
::to_owned(q
).unwrap(),
429 BigNumRef
::to_owned(g
).unwrap(),
430 BigNumRef
::to_owned(priv_key
).unwrap(),
431 BigNumRef
::to_owned(pub_key
).unwrap(),
434 let priv_key
= PKey
::from_dsa(priv_key
).unwrap();
436 let pub_key
= Dsa
::from_public_components(
437 BigNumRef
::to_owned(p
).unwrap(),
438 BigNumRef
::to_owned(q
).unwrap(),
439 BigNumRef
::to_owned(g
).unwrap(),
440 BigNumRef
::to_owned(pub_key
).unwrap(),
443 let pub_key
= PKey
::from_dsa(pub_key
).unwrap();
445 let mut signer
= Signer
::new(MessageDigest
::sha256(), &priv_key
).unwrap();
446 signer
.update(TEST_DATA
).unwrap();
448 let signature
= signer
.sign_to_vec().unwrap();
449 let mut verifier
= Verifier
::new(MessageDigest
::sha256(), &pub_key
).unwrap();
450 verifier
.update(TEST_DATA
).unwrap();
451 assert
!(verifier
.verify(&signature
[..]).unwrap());
455 #[allow(clippy::redundant_clone)]
457 let key
= Dsa
::generate(2048).unwrap();