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