/rust/registry/src/index.crates.io-1949cf8c6b5b557f/openssl-0.10.62/src/dsa.rs
Line | Count | Source |
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 | 0 | fn clone(&self) -> Dsa<T> { |
67 | 0 | (**self).to_owned() |
68 | 0 | } |
69 | | } |
70 | | |
71 | | impl<T> ToOwned for DsaRef<T> { |
72 | | type Owned = Dsa<T>; |
73 | | |
74 | 0 | fn to_owned(&self) -> Dsa<T> { |
75 | | unsafe { |
76 | 0 | ffi::DSA_up_ref(self.as_ptr()); |
77 | 0 | Dsa::from_ptr(self.as_ptr()) |
78 | | } |
79 | 0 | } |
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 | 0 | pub fn pub_key(&self) -> &BigNumRef { |
105 | | unsafe { |
106 | 0 | let mut pub_key = ptr::null(); |
107 | 0 | DSA_get0_key(self.as_ptr(), &mut pub_key, ptr::null_mut()); |
108 | 0 | BigNumRef::from_const_ptr(pub_key) |
109 | | } |
110 | 0 | } |
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 | 0 | pub fn priv_key(&self) -> &BigNumRef { |
141 | | unsafe { |
142 | 0 | let mut priv_key = ptr::null(); |
143 | 0 | DSA_get0_key(self.as_ptr(), ptr::null_mut(), &mut priv_key); |
144 | 0 | BigNumRef::from_const_ptr(priv_key) |
145 | | } |
146 | 0 | } |
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 | 0 | pub fn size(&self) -> u32 { |
156 | 0 | unsafe { ffi::DSA_size(self.as_ptr()) as u32 } |
157 | 0 | } |
158 | | |
159 | | /// Returns the DSA prime parameter of `self`. |
160 | | #[corresponds(DSA_get0_pqg)] |
161 | 0 | pub fn p(&self) -> &BigNumRef { |
162 | | unsafe { |
163 | 0 | let mut p = ptr::null(); |
164 | 0 | DSA_get0_pqg(self.as_ptr(), &mut p, ptr::null_mut(), ptr::null_mut()); |
165 | 0 | BigNumRef::from_const_ptr(p) |
166 | | } |
167 | 0 | } |
168 | | |
169 | | /// Returns the DSA sub-prime parameter of `self`. |
170 | | #[corresponds(DSA_get0_pqg)] |
171 | 0 | pub fn q(&self) -> &BigNumRef { |
172 | | unsafe { |
173 | 0 | let mut q = ptr::null(); |
174 | 0 | DSA_get0_pqg(self.as_ptr(), ptr::null_mut(), &mut q, ptr::null_mut()); |
175 | 0 | BigNumRef::from_const_ptr(q) |
176 | | } |
177 | 0 | } |
178 | | |
179 | | /// Returns the DSA base parameter of `self`. |
180 | | #[corresponds(DSA_get0_pqg)] |
181 | 0 | pub fn g(&self) -> &BigNumRef { |
182 | | unsafe { |
183 | 0 | let mut g = ptr::null(); |
184 | 0 | DSA_get0_pqg(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut g); |
185 | 0 | BigNumRef::from_const_ptr(g) |
186 | | } |
187 | 0 | } |
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 | 0 | pub fn from_pqg(p: BigNum, q: BigNum, g: BigNum) -> Result<Dsa<Params>, ErrorStack> { |
198 | | unsafe { |
199 | 0 | let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?); |
200 | 0 | cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?; |
201 | 0 | mem::forget((p, q, g)); |
202 | 0 | Ok(dsa) |
203 | | } |
204 | 0 | } |
205 | | |
206 | | /// Generates DSA params based on the given number of bits. |
207 | | #[corresponds(DSA_generate_parameters_ex)] |
208 | 0 | pub fn generate_params(bits: u32) -> Result<Dsa<Params>, ErrorStack> { |
209 | 0 | ffi::init(); |
210 | | unsafe { |
211 | 0 | let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?); |
212 | 0 | cvt(ffi::DSA_generate_parameters_ex( |
213 | 0 | dsa.0, |
214 | 0 | bits as BitType, |
215 | 0 | ptr::null(), |
216 | | 0, |
217 | 0 | ptr::null_mut(), |
218 | 0 | ptr::null_mut(), |
219 | 0 | ptr::null_mut(), |
220 | 0 | ))?; |
221 | 0 | Ok(dsa) |
222 | | } |
223 | 0 | } |
224 | | |
225 | | /// Generates a private key based on the DSA params. |
226 | | #[corresponds(DSA_generate_key)] |
227 | 0 | pub fn generate_key(self) -> Result<Dsa<Private>, ErrorStack> { |
228 | | unsafe { |
229 | 0 | let dsa_ptr = self.0; |
230 | 0 | cvt(ffi::DSA_generate_key(dsa_ptr))?; |
231 | 0 | mem::forget(self); |
232 | 0 | Ok(Dsa::from_ptr(dsa_ptr)) |
233 | | } |
234 | 0 | } |
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 | 0 | pub fn generate(bits: u32) -> Result<Dsa<Private>, ErrorStack> { |
242 | 0 | let params = Dsa::generate_params(bits)?; |
243 | 0 | params.generate_key() |
244 | 0 | } |
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 | 0 | pub fn from_private_components( |
252 | 0 | p: BigNum, |
253 | 0 | q: BigNum, |
254 | 0 | g: BigNum, |
255 | 0 | priv_key: BigNum, |
256 | 0 | pub_key: BigNum, |
257 | 0 | ) -> Result<Dsa<Private>, ErrorStack> { |
258 | 0 | ffi::init(); |
259 | | unsafe { |
260 | 0 | let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?); |
261 | 0 | cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?; |
262 | 0 | mem::forget((p, q, g)); |
263 | 0 | cvt(DSA_set0_key(dsa.0, pub_key.as_ptr(), priv_key.as_ptr()))?; |
264 | 0 | mem::forget((pub_key, priv_key)); |
265 | 0 | Ok(dsa) |
266 | | } |
267 | 0 | } |
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 | 0 | pub fn from_public_components( |
294 | 0 | p: BigNum, |
295 | 0 | q: BigNum, |
296 | 0 | g: BigNum, |
297 | 0 | pub_key: BigNum, |
298 | 0 | ) -> Result<Dsa<Public>, ErrorStack> { |
299 | 0 | ffi::init(); |
300 | | unsafe { |
301 | 0 | let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?); |
302 | 0 | cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?; |
303 | 0 | mem::forget((p, q, g)); |
304 | 0 | cvt(DSA_set0_key(dsa.0, pub_key.as_ptr(), ptr::null_mut()))?; |
305 | 0 | mem::forget(pub_key); |
306 | 0 | Ok(dsa) |
307 | | } |
308 | 0 | } |
309 | | } |
310 | | |
311 | | impl<T> fmt::Debug for Dsa<T> { |
312 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
313 | 0 | write!(f, "DSA") |
314 | 0 | } |
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 | 0 | pub fn from_private_components(r: BigNum, s: BigNum) -> Result<Self, ErrorStack> { |
441 | | unsafe { |
442 | 0 | let sig = cvt_p(ffi::DSA_SIG_new())?; |
443 | 0 | DSA_SIG_set0(sig, r.as_ptr(), s.as_ptr()); |
444 | 0 | mem::forget((r, s)); |
445 | 0 | Ok(DsaSig::from_ptr(sig)) |
446 | | } |
447 | 0 | } |
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 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
460 | 0 | f.debug_struct("DsaSig") |
461 | 0 | .field("r", self.r()) |
462 | 0 | .field("s", self.s()) |
463 | 0 | .finish() |
464 | 0 | } |
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 | 0 | pub fn r(&self) -> &BigNumRef { |
478 | | unsafe { |
479 | 0 | let mut r = ptr::null(); |
480 | 0 | DSA_SIG_get0(self.as_ptr(), &mut r, ptr::null_mut()); |
481 | 0 | BigNumRef::from_const_ptr(r) |
482 | | } |
483 | 0 | } |
484 | | |
485 | | /// Returns internal component `s` of an `DsaSig`. |
486 | | #[corresponds(DSA_SIG_get0)] |
487 | 0 | pub fn s(&self) -> &BigNumRef { |
488 | | unsafe { |
489 | 0 | let mut s = ptr::null(); |
490 | 0 | DSA_SIG_get0(self.as_ptr(), ptr::null_mut(), &mut s); |
491 | 0 | BigNumRef::from_const_ptr(s) |
492 | | } |
493 | 0 | } |
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 | | } |