| 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(any(boringssl, awslc)))] |
| 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 (any(boringssl, awslc))] |
| 190 | type BitType = libc::c_uint; |
| 191 | #[cfg (not(any(boringssl, awslc)))] |
| 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, awslc))] { |
| 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, awslc))] { |
| 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 | |