1use core::fmt;
10
11use crate::hash::Digest;
12use crate::public_key::bigint::{BigUint, MontgomeryCtx};
13use crate::public_key::io::{
14 decode_biguints, encode_biguints, pem_unwrap, pem_wrap, xml_unwrap, xml_wrap,
15};
16use crate::public_key::primes::{
17 generate_prime_order_group, is_probable_prime, mod_inverse, mod_pow, random_nonzero_below,
18};
19use crate::Csprng;
20use crate::Hmac;
21
22const DSA_PUBLIC_LABEL: &str = "CRYPTOGRAPHY DSA PUBLIC KEY";
23const DSA_PRIVATE_LABEL: &str = "CRYPTOGRAPHY DSA PRIVATE KEY";
24
25#[derive(Clone, Debug, Eq, PartialEq)]
27pub struct DsaPublicKey {
28 p: BigUint,
30 q: BigUint,
32 g: BigUint,
34 y: BigUint,
36 g_mont: Option<BigUint>,
38 y_mont: Option<BigUint>,
40 p_ctx: Option<MontgomeryCtx>,
42 q_ctx: Option<MontgomeryCtx>,
44}
45
46#[derive(Clone, Eq, PartialEq)]
48pub struct DsaPrivateKey {
49 p: BigUint,
51 q: BigUint,
53 g: BigUint,
55 x: BigUint,
57 y: BigUint,
59 g_mont: Option<BigUint>,
61 y_mont: Option<BigUint>,
63 p_ctx: Option<MontgomeryCtx>,
65 q_ctx: Option<MontgomeryCtx>,
67}
68
69#[derive(Clone, Debug, Eq, PartialEq)]
71pub struct DsaSignature {
72 r: BigUint,
73 s: BigUint,
74}
75
76pub struct Dsa;
78
79impl DsaPublicKey {
80 #[must_use]
82 pub fn modulus(&self) -> &BigUint {
83 &self.p
84 }
85
86 #[must_use]
88 pub fn subgroup_order(&self) -> &BigUint {
89 &self.q
90 }
91
92 #[must_use]
94 pub fn generator(&self) -> &BigUint {
95 &self.g
96 }
97
98 #[must_use]
100 pub fn public_component(&self) -> &BigUint {
101 &self.y
102 }
103
104 #[must_use]
106 pub fn verify_message<H: Digest>(&self, message: &[u8], signature: &DsaSignature) -> bool {
107 let digest = H::digest(message);
108 self.verify(&digest, signature)
109 }
110
111 #[must_use]
113 pub fn verify_message_bytes<H: Digest>(&self, message: &[u8], signature: &[u8]) -> bool {
114 let digest = H::digest(message);
115 self.verify_bytes(&digest, signature)
116 }
117
118 #[must_use]
120 pub fn verify_digest_scalar(&self, hash: &BigUint, signature: &DsaSignature) -> bool {
121 if signature.r.is_zero()
122 || signature.s.is_zero()
123 || signature.r >= self.q
124 || signature.s >= self.q
125 {
126 return false;
127 }
128
129 let Some(w) = mod_inverse(&signature.s, &self.q) else {
130 return false;
131 };
132 let z = hash.modulo(&self.q);
136 let u1 = if let Some(ctx) = &self.q_ctx {
137 ctx.mul(&z, &w)
138 } else {
139 BigUint::mod_mul(&z, &w, &self.q)
140 };
141 let u2 = if let Some(ctx) = &self.q_ctx {
142 ctx.mul(&signature.r, &w)
143 } else {
144 BigUint::mod_mul(&signature.r, &w, &self.q)
145 };
146
147 let g_term = if let (Some(ctx), Some(g_mont)) = (&self.p_ctx, &self.g_mont) {
148 ctx.pow_encoded(g_mont, &u1)
149 } else {
150 mod_pow(&self.g, &u1, &self.p)
151 };
152 let y_term = if let (Some(ctx), Some(y_mont)) = (&self.p_ctx, &self.y_mont) {
153 ctx.pow_encoded(y_mont, &u2)
154 } else {
155 mod_pow(&self.y, &u2, &self.p)
156 };
157 let combined = if let Some(ctx) = &self.p_ctx {
158 ctx.mul(&g_term, &y_term)
159 } else {
160 BigUint::mod_mul(&g_term, &y_term, &self.p)
161 };
162
163 combined.modulo(&self.q) == signature.r
164 }
165
166 #[must_use]
171 pub fn verify(&self, digest: &[u8], signature: &DsaSignature) -> bool {
172 self.verify_digest_scalar(&digest_to_scalar(digest, &self.q), signature)
173 }
174
175 #[must_use]
177 pub fn verify_bytes(&self, digest: &[u8], signature: &[u8]) -> bool {
178 let Some(signature) = DsaSignature::from_key_blob(signature) else {
179 return false;
180 };
181 self.verify(digest, &signature)
182 }
183
184 #[must_use]
186 pub fn to_key_blob(&self) -> Vec<u8> {
187 encode_biguints(&[&self.p, &self.q, &self.g, &self.y])
188 }
189
190 #[must_use]
192 pub fn from_key_blob(blob: &[u8]) -> Option<Self> {
193 let mut fields = decode_biguints(blob)?.into_iter();
194 let p = fields.next()?;
195 let q = fields.next()?;
196 let g = fields.next()?;
197 let y = fields.next()?;
198 if fields.next().is_some() || !validate_domain(&p, &q, &g) || y <= BigUint::one() || y >= p
199 {
200 return None;
201 }
202 let p_ctx = MontgomeryCtx::new(&p);
203 let q_ctx = MontgomeryCtx::new(&q);
204 let g_mont = p_ctx.as_ref().map(|ctx| ctx.encode(&g));
205 let y_mont = p_ctx.as_ref().map(|ctx| ctx.encode(&y));
206 Some(Self {
207 p,
208 q,
209 g,
210 y,
211 g_mont,
212 y_mont,
213 p_ctx,
214 q_ctx,
215 })
216 }
217
218 #[must_use]
220 pub fn to_pem(&self) -> String {
221 pem_wrap(DSA_PUBLIC_LABEL, &self.to_key_blob())
222 }
223
224 #[must_use]
226 pub fn to_xml(&self) -> String {
227 xml_wrap(
228 "DsaPublicKey",
229 &[
230 ("p", &self.p),
231 ("q", &self.q),
232 ("g", &self.g),
233 ("y", &self.y),
234 ],
235 )
236 }
237
238 #[must_use]
240 pub fn from_pem(pem: &str) -> Option<Self> {
241 let blob = pem_unwrap(DSA_PUBLIC_LABEL, pem)?;
242 Self::from_key_blob(&blob)
243 }
244
245 #[must_use]
247 pub fn from_xml(xml: &str) -> Option<Self> {
248 let mut fields = xml_unwrap("DsaPublicKey", &["p", "q", "g", "y"], xml)?.into_iter();
249 let p = fields.next()?;
250 let q = fields.next()?;
251 let g = fields.next()?;
252 let y = fields.next()?;
253 if fields.next().is_some() || !validate_domain(&p, &q, &g) || y <= BigUint::one() || y >= p
254 {
255 return None;
256 }
257 let p_ctx = MontgomeryCtx::new(&p);
258 let q_ctx = MontgomeryCtx::new(&q);
259 let g_mont = p_ctx.as_ref().map(|ctx| ctx.encode(&g));
260 let y_mont = p_ctx.as_ref().map(|ctx| ctx.encode(&y));
261 Some(Self {
262 p,
263 q,
264 g,
265 y,
266 g_mont,
267 y_mont,
268 p_ctx,
269 q_ctx,
270 })
271 }
272}
273
274impl DsaPrivateKey {
275 #[must_use]
277 pub fn modulus(&self) -> &BigUint {
278 &self.p
279 }
280
281 #[must_use]
283 pub fn subgroup_order(&self) -> &BigUint {
284 &self.q
285 }
286
287 #[must_use]
289 pub fn generator(&self) -> &BigUint {
290 &self.g
291 }
292
293 #[must_use]
295 pub fn exponent(&self) -> &BigUint {
296 &self.x
297 }
298
299 #[must_use]
301 pub fn to_public_key(&self) -> DsaPublicKey {
302 DsaPublicKey {
303 p: self.p.clone(),
304 q: self.q.clone(),
305 g: self.g.clone(),
306 y: self.y.clone(),
307 g_mont: self.g_mont.clone(),
308 y_mont: self.y_mont.clone(),
309 p_ctx: self.p_ctx.clone(),
310 q_ctx: self.q_ctx.clone(),
311 }
312 }
313
314 #[must_use]
323 pub fn sign_digest_with_nonce(&self, digest: &[u8], nonce: &BigUint) -> Option<DsaSignature> {
324 if nonce.is_zero() || nonce >= &self.q {
325 return None;
326 }
327
328 let z = digest_to_scalar(digest, &self.q);
329 let r = if let (Some(ctx), Some(g_mont)) = (&self.p_ctx, &self.g_mont) {
330 ctx.pow_encoded(g_mont, nonce)
331 } else {
332 mod_pow(&self.g, nonce, &self.p)
333 }
334 .modulo(&self.q);
335 if r.is_zero() {
336 return None;
337 }
338
339 let nonce_inv = mod_inverse(nonce, &self.q)?;
340 let xr = if let Some(ctx) = &self.q_ctx {
341 ctx.mul(&self.x, &r)
342 } else {
343 BigUint::mod_mul(&self.x, &r, &self.q)
344 };
345 let sum = z.add_ref(&xr).modulo(&self.q);
346 let s = if let Some(ctx) = &self.q_ctx {
347 ctx.mul(&nonce_inv, &sum)
348 } else {
349 BigUint::mod_mul(&nonce_inv, &sum, &self.q)
350 };
351 if s.is_zero() {
352 return None;
353 }
354
355 Some(DsaSignature { r, s })
356 }
357
358 #[must_use]
360 pub fn sign_digest<H: Digest>(&self, digest: &[u8]) -> Option<DsaSignature> {
361 let nonce = rfc6979_nonce::<H>(&self.q, &self.x, digest)?;
362 self.sign_digest_with_nonce(digest, &nonce)
363 }
364
365 #[must_use]
367 pub fn sign_digest_with_rng<R: Csprng>(
368 &self,
369 digest: &[u8],
370 rng: &mut R,
371 ) -> Option<DsaSignature> {
372 loop {
373 let nonce = random_nonzero_below(rng, &self.q)?;
376 if let Some(signature) = self.sign_digest_with_nonce(digest, &nonce) {
377 return Some(signature);
378 }
379 }
380 }
381
382 #[must_use]
384 pub fn sign_message<H: Digest>(&self, message: &[u8]) -> Option<DsaSignature> {
385 let digest = H::digest(message);
386 self.sign_digest::<H>(&digest)
387 }
388
389 #[must_use]
391 pub fn sign_message_with_rng<H: Digest, R: Csprng>(
392 &self,
393 message: &[u8],
394 rng: &mut R,
395 ) -> Option<DsaSignature> {
396 let digest = H::digest(message);
397 self.sign_digest_with_rng(&digest, rng)
398 }
399
400 #[must_use]
402 pub fn sign_digest_bytes<H: Digest>(&self, digest: &[u8]) -> Option<Vec<u8>> {
403 let signature = self.sign_digest::<H>(digest)?;
404 Some(signature.to_key_blob())
405 }
406
407 #[must_use]
409 pub fn sign_digest_bytes_with_rng<H: Digest, R: Csprng>(
410 &self,
411 digest: &[u8],
412 rng: &mut R,
413 ) -> Option<Vec<u8>> {
414 let signature = self.sign_digest_with_rng(digest, rng)?;
415 Some(signature.to_key_blob())
416 }
417
418 #[must_use]
420 pub fn sign_message_bytes<H: Digest>(&self, message: &[u8]) -> Option<Vec<u8>> {
421 let signature = self.sign_message::<H>(message)?;
422 Some(signature.to_key_blob())
423 }
424
425 #[must_use]
427 pub fn sign_message_bytes_with_rng<H: Digest, R: Csprng>(
428 &self,
429 message: &[u8],
430 rng: &mut R,
431 ) -> Option<Vec<u8>> {
432 let signature = self.sign_message_with_rng::<H, R>(message, rng)?;
433 Some(signature.to_key_blob())
434 }
435
436 #[must_use]
438 pub fn to_key_blob(&self) -> Vec<u8> {
439 encode_biguints(&[&self.p, &self.q, &self.g, &self.x])
440 }
441
442 #[must_use]
444 pub fn from_key_blob(blob: &[u8]) -> Option<Self> {
445 let mut fields = decode_biguints(blob)?.into_iter();
446 let p = fields.next()?;
447 let q = fields.next()?;
448 let g = fields.next()?;
449 let x = fields.next()?;
450 if fields.next().is_some() || !validate_domain(&p, &q, &g) || x.is_zero() || x >= q {
451 return None;
452 }
453 let y = mod_pow(&g, &x, &p);
454 let p_ctx = MontgomeryCtx::new(&p);
455 let q_ctx = MontgomeryCtx::new(&q);
456 let g_mont = p_ctx.as_ref().map(|ctx| ctx.encode(&g));
457 let y_mont = p_ctx.as_ref().map(|ctx| ctx.encode(&y));
458 Some(Self {
459 p,
460 q,
461 g,
462 x,
463 y,
464 g_mont,
465 y_mont,
466 p_ctx,
467 q_ctx,
468 })
469 }
470
471 #[must_use]
473 pub fn to_pem(&self) -> String {
474 pem_wrap(DSA_PRIVATE_LABEL, &self.to_key_blob())
475 }
476
477 #[must_use]
479 pub fn to_xml(&self) -> String {
480 xml_wrap(
481 "DsaPrivateKey",
482 &[
483 ("p", &self.p),
484 ("q", &self.q),
485 ("g", &self.g),
486 ("x", &self.x),
487 ],
488 )
489 }
490
491 #[must_use]
493 pub fn from_pem(pem: &str) -> Option<Self> {
494 let blob = pem_unwrap(DSA_PRIVATE_LABEL, pem)?;
495 Self::from_key_blob(&blob)
496 }
497
498 #[must_use]
500 pub fn from_xml(xml: &str) -> Option<Self> {
501 let mut fields = xml_unwrap("DsaPrivateKey", &["p", "q", "g", "x"], xml)?.into_iter();
502 let p = fields.next()?;
503 let q = fields.next()?;
504 let g = fields.next()?;
505 let x = fields.next()?;
506 if fields.next().is_some() || !validate_domain(&p, &q, &g) || x.is_zero() || x >= q {
507 return None;
508 }
509 let y = mod_pow(&g, &x, &p);
510 let p_ctx = MontgomeryCtx::new(&p);
511 let q_ctx = MontgomeryCtx::new(&q);
512 let g_mont = p_ctx.as_ref().map(|ctx| ctx.encode(&g));
513 let y_mont = p_ctx.as_ref().map(|ctx| ctx.encode(&y));
514 Some(Self {
515 p,
516 q,
517 g,
518 x,
519 y,
520 g_mont,
521 y_mont,
522 p_ctx,
523 q_ctx,
524 })
525 }
526}
527
528impl fmt::Debug for DsaPrivateKey {
529 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
530 f.write_str("DsaPrivateKey(<redacted>)")
531 }
532}
533
534impl DsaSignature {
535 #[must_use]
537 pub fn r(&self) -> &BigUint {
538 &self.r
539 }
540
541 #[must_use]
543 pub fn s(&self) -> &BigUint {
544 &self.s
545 }
546
547 #[must_use]
549 pub fn to_key_blob(&self) -> Vec<u8> {
550 encode_biguints(&[&self.r, &self.s])
551 }
552
553 #[must_use]
559 pub fn from_key_blob(blob: &[u8]) -> Option<Self> {
560 let mut fields = decode_biguints(blob)?.into_iter();
561 let r = fields.next()?;
562 let s = fields.next()?;
563 if fields.next().is_some() || r.is_zero() || s.is_zero() {
564 return None;
565 }
566 Some(Self { r, s })
567 }
568}
569
570impl Dsa {
571 #[must_use]
573 pub fn from_secret_exponent(
574 prime: &BigUint,
575 subgroup_order: &BigUint,
576 generator: &BigUint,
577 secret: &BigUint,
578 ) -> Option<(DsaPublicKey, DsaPrivateKey)> {
579 if !validate_domain(prime, subgroup_order, generator)
580 || secret.is_zero()
581 || secret >= subgroup_order
582 {
583 return None;
584 }
585
586 let public_component = mod_pow(generator, secret, prime);
587 let p_ctx = MontgomeryCtx::new(prime);
588 let q_ctx = MontgomeryCtx::new(subgroup_order);
589 let g_mont = p_ctx.as_ref().map(|ctx| ctx.encode(generator));
590 let y_mont = p_ctx.as_ref().map(|ctx| ctx.encode(&public_component));
591 Some((
592 DsaPublicKey {
593 p: prime.clone(),
594 q: subgroup_order.clone(),
595 g: generator.clone(),
596 y: public_component.clone(),
597 g_mont: g_mont.clone(),
598 y_mont: y_mont.clone(),
599 p_ctx: p_ctx.clone(),
600 q_ctx: q_ctx.clone(),
601 },
602 DsaPrivateKey {
603 p: prime.clone(),
604 q: subgroup_order.clone(),
605 g: generator.clone(),
606 x: secret.clone(),
607 y: public_component.clone(),
608 g_mont,
609 y_mont,
610 p_ctx,
611 q_ctx,
612 },
613 ))
614 }
615
616 #[must_use]
618 pub fn generate<R: Csprng>(rng: &mut R, bits: usize) -> Option<(DsaPublicKey, DsaPrivateKey)> {
619 let (prime, subgroup_order, _cofactor, generator) = generate_prime_order_group(rng, bits)?;
620 let secret = random_nonzero_below(rng, &subgroup_order)?;
621 let public_component = mod_pow(&generator, &secret, &prime);
622 let p_ctx = MontgomeryCtx::new(&prime);
623 let q_ctx = MontgomeryCtx::new(&subgroup_order);
624 let g_mont = p_ctx.as_ref().map(|ctx| ctx.encode(&generator));
625 let y_mont = p_ctx.as_ref().map(|ctx| ctx.encode(&public_component));
626 Some((
627 DsaPublicKey {
628 p: prime.clone(),
629 q: subgroup_order.clone(),
630 g: generator.clone(),
631 y: public_component.clone(),
632 g_mont: g_mont.clone(),
633 y_mont: y_mont.clone(),
634 p_ctx: p_ctx.clone(),
635 q_ctx: q_ctx.clone(),
636 },
637 DsaPrivateKey {
638 p: prime,
639 q: subgroup_order,
640 g: generator,
641 x: secret,
642 y: public_component.clone(),
643 g_mont,
644 y_mont,
645 p_ctx,
646 q_ctx,
647 },
648 ))
649 }
650}
651
652fn validate_domain(prime: &BigUint, subgroup_order: &BigUint, generator: &BigUint) -> bool {
657 if !is_probable_prime(prime) || !is_probable_prime(subgroup_order) {
658 return false;
659 }
660 if subgroup_order >= prime {
661 return false;
662 }
663 let p_minus_one = prime.sub_ref(&BigUint::one());
664 if !p_minus_one.modulo(subgroup_order).is_zero() {
665 return false;
666 }
667 if generator <= &BigUint::one() || generator >= prime {
668 return false;
669 }
670 let one = BigUint::one();
671 mod_pow(generator, subgroup_order, prime) == one
672}
673
674fn digest_to_scalar(digest: &[u8], modulus: &BigUint) -> BigUint {
680 let mut value = BigUint::from_be_bytes(digest);
681 let hash_bits = digest.len() * 8;
682 let target_bits = modulus.bits();
683 if hash_bits > target_bits {
684 for _ in 0..(hash_bits - target_bits) {
685 value.shr1();
686 }
687 }
688 value
689}
690
691fn int_to_octets(value: &BigUint, len: usize) -> Vec<u8> {
692 let bytes = value.to_be_bytes();
693 if bytes.len() >= len {
694 return bytes[bytes.len() - len..].to_vec();
695 }
696 let mut out = vec![0u8; len];
697 out[len - bytes.len()..].copy_from_slice(&bytes);
698 out
699}
700
701fn bits_to_int(input: &[u8], target_bits: usize) -> BigUint {
702 let mut value = BigUint::from_be_bytes(input);
703 let input_bits = input.len() * 8;
704 if input_bits > target_bits {
705 for _ in 0..(input_bits - target_bits) {
706 value.shr1();
707 }
708 }
709 value
710}
711
712fn bits_to_octets(input: &[u8], q: &BigUint, q_bits: usize, ro_len: usize) -> Vec<u8> {
713 let z1 = bits_to_int(input, q_bits);
714 let z2 = z1.modulo(q);
715 int_to_octets(&z2, ro_len)
716}
717
718fn rfc6979_nonce<H: Digest>(q: &BigUint, x: &BigUint, digest: &[u8]) -> Option<BigUint> {
719 if q <= &BigUint::one() {
720 return None;
721 }
722
723 let q_bits = q.bits();
724 let ro_len = q_bits.div_ceil(8);
725 let bx = int_to_octets(x, ro_len);
726 let bh = bits_to_octets(digest, q, q_bits, ro_len);
727
728 let mut v = vec![0x01; H::OUTPUT_LEN];
729 let mut k = vec![0x00; H::OUTPUT_LEN];
730
731 let mut data = Vec::with_capacity(v.len() + 1 + bx.len() + bh.len());
732 data.extend_from_slice(&v);
733 data.push(0x00);
734 data.extend_from_slice(&bx);
735 data.extend_from_slice(&bh);
736 k = Hmac::<H>::compute(&k, &data);
737 v = Hmac::<H>::compute(&k, &v);
738
739 data.clear();
740 data.extend_from_slice(&v);
741 data.push(0x01);
742 data.extend_from_slice(&bx);
743 data.extend_from_slice(&bh);
744 k = Hmac::<H>::compute(&k, &data);
745 v = Hmac::<H>::compute(&k, &v);
746
747 loop {
748 let mut t = Vec::with_capacity(ro_len);
749 while t.len() < ro_len {
750 v = Hmac::<H>::compute(&k, &v);
751 let take = (ro_len - t.len()).min(v.len());
752 t.extend_from_slice(&v[..take]);
753 }
754
755 let candidate = bits_to_int(&t, q_bits);
756 if !candidate.is_zero() && &candidate < q {
757 return Some(candidate);
758 }
759
760 data.clear();
761 data.extend_from_slice(&v);
762 data.push(0x00);
763 k = Hmac::<H>::compute(&k, &data);
764 v = Hmac::<H>::compute(&k, &v);
765 }
766}
767
768#[cfg(test)]
769mod tests {
770 use super::{Dsa, DsaPrivateKey, DsaPublicKey, DsaSignature};
771 use crate::public_key::bigint::BigUint;
772 use crate::{CtrDrbgAes256, Sha256, Sha384};
773
774 fn derive_small_reference_key() -> (DsaPublicKey, DsaPrivateKey) {
775 let p = BigUint::from_u64(23);
776 let q = BigUint::from_u64(11);
777 let g = BigUint::from_u64(4);
778 let x = BigUint::from_u64(3);
779 Dsa::from_secret_exponent(&p, &q, &g, &x).expect("valid DSA key")
780 }
781
782 fn decode_hex(hex: &str) -> Vec<u8> {
783 let cleaned: String = hex.chars().filter(|c| !c.is_whitespace()).collect();
784 assert_eq!(
785 cleaned.len() % 2,
786 0,
787 "hex input must have an even number of nybbles"
788 );
789 (0..cleaned.len())
790 .step_by(2)
791 .map(|i| u8::from_str_radix(&cleaned[i..i + 2], 16).expect("valid hex byte"))
792 .collect()
793 }
794
795 fn from_hex(hex: &str) -> BigUint {
796 BigUint::from_be_bytes(&decode_hex(hex))
797 }
798
799 #[test]
800 fn derive_small_reference_key_components() {
801 let (public, private) = derive_small_reference_key();
802 assert_eq!(public.modulus(), &BigUint::from_u64(23));
803 assert_eq!(public.subgroup_order(), &BigUint::from_u64(11));
804 assert_eq!(public.generator(), &BigUint::from_u64(4));
805 assert_eq!(public.public_component(), &BigUint::from_u64(18));
806 assert_eq!(private.exponent(), &BigUint::from_u64(3));
807 }
808
809 #[test]
810 fn exact_small_signature_matches_reference() {
811 let (public, private) = derive_small_reference_key();
812 let nonce = BigUint::from_u64(5);
813 let signature = private
814 .sign_digest_with_nonce(&[0x09], &nonce)
815 .expect("valid DSA nonce");
816 assert_eq!(signature.r(), &BigUint::from_u64(1));
817 assert_eq!(signature.s(), &BigUint::from_u64(5));
821 assert!(public.verify(&[0x09], &signature));
822 }
823
824 #[test]
825 fn rejects_invalid_parameters() {
826 let p = BigUint::from_u64(23);
827 let q = BigUint::from_u64(5);
828 let g = BigUint::from_u64(4);
829 let x = BigUint::from_u64(3);
830 assert!(Dsa::from_secret_exponent(&p, &q, &g, &x).is_none());
831
832 let q = BigUint::from_u64(11);
833 let bad_g = BigUint::from_u64(5);
834 assert!(Dsa::from_secret_exponent(&p, &q, &bad_g, &x).is_none());
835 assert!(Dsa::from_secret_exponent(&p, &q, &g, &BigUint::zero()).is_none());
836 }
837
838 #[test]
839 fn sign_and_verify_roundtrip() {
840 let seed = [0x31u8; 48];
841 let mut drbg = CtrDrbgAes256::new(&seed);
842 let (public, private) = Dsa::generate(&mut drbg, 64).expect("generated DSA key");
843 let digest = b"dsa-signature-digest";
844 let signature = private.sign_digest::<Sha256>(digest).expect("signature");
845 assert!(public.verify(digest, &signature));
846 assert!(!public.verify(b"wrong-digest", &signature));
847 }
848
849 #[test]
850 fn sign_bytes_roundtrip() {
851 let seed = [0x44u8; 48];
852 let mut drbg = CtrDrbgAes256::new(&seed);
853 let (public, private) = Dsa::generate(&mut drbg, 64).expect("generated DSA key");
854 let digest = b"dsa-bytes";
855 let signature = private
856 .sign_digest_bytes::<Sha256>(digest)
857 .expect("signature bytes");
858 assert!(public.verify_bytes(digest, &signature));
859 }
860
861 #[test]
862 fn sign_message_roundtrip() {
863 let seed = [0x45u8; 48];
864 let mut drbg = CtrDrbgAes256::new(&seed);
865 let (public, private) = Dsa::generate(&mut drbg, 64).expect("generated DSA key");
866 let message = b"dsa full message";
867 let signature = private
868 .sign_message::<Sha256>(message)
869 .expect("message signature");
870 assert!(public.verify_message::<Sha256>(message, &signature));
871 }
872
873 #[test]
874 fn tampered_signature_is_rejected() {
875 let seed = [0x46u8; 48];
876 let mut drbg = CtrDrbgAes256::new(&seed);
877 let (public, private) = Dsa::generate(&mut drbg, 64).expect("generated DSA key");
878 let digest = b"dsa-tamper";
879 let mut signature = private.sign_digest::<Sha256>(digest).expect("signature");
880 signature.s = signature
881 .s
882 .add_ref(&BigUint::one())
883 .modulo(public.subgroup_order());
884 if signature.s.is_zero() {
885 signature.s = BigUint::one();
886 }
887 assert!(!public.verify(digest, &signature));
888 }
889
890 #[test]
891 fn cross_key_signature_is_rejected() {
892 let mut drbg_a = CtrDrbgAes256::new(&[0x47; 48]);
893 let mut drbg_b = CtrDrbgAes256::new(&[0x48; 48]);
894 let (public_a, private_a) = Dsa::generate(&mut drbg_a, 64).expect("first key");
895 let (public_b, _) = Dsa::generate(&mut drbg_b, 64).expect("second key");
896 let digest = b"dsa-cross";
897 let signature = private_a.sign_digest::<Sha256>(digest).expect("signature");
898 assert!(public_a.verify(digest, &signature));
899 assert!(!public_b.verify(digest, &signature));
900 }
901
902 #[test]
903 fn sign_digest_with_nonce_rejects_out_of_range_nonce() {
904 let (_public, private) = derive_small_reference_key();
905 assert!(private
906 .sign_digest_with_nonce(&[0x09], &BigUint::zero())
907 .is_none());
908 assert!(private
909 .sign_digest_with_nonce(&[0x09], private.subgroup_order())
910 .is_none());
911 }
912
913 #[test]
914 fn sign_digest_with_nonce_is_deterministic_for_fixed_nonce() {
915 let (_public, private) = derive_small_reference_key();
916 let digest = [0x09];
917 let nonce = BigUint::from_u64(7);
918 let lhs = private
919 .sign_digest_with_nonce(&digest, &nonce)
920 .expect("first explicit nonce signature");
921 let rhs = private
922 .sign_digest_with_nonce(&digest, &nonce)
923 .expect("second explicit nonce signature");
924 assert_eq!(lhs, rhs);
925 }
926
927 #[test]
928 fn generate_rejects_too_few_bits() {
929 let mut drbg = CtrDrbgAes256::new(&[0x49; 48]);
930 for bits in 0..19 {
931 assert!(Dsa::generate(&mut drbg, bits).is_none());
932 }
933 }
934
935 #[test]
936 fn serialization_roundtrip_preserves_verification() {
937 let seed = [0x4Au8; 48];
938 let mut drbg = CtrDrbgAes256::new(&seed);
939 let (public, private) = Dsa::generate(&mut drbg, 64).expect("generated DSA key");
940 let digest = b"dsa-serialize";
941 let signature = private.sign_digest::<Sha256>(digest).expect("signature");
942 let public_xml = public.to_xml();
943 let public_again = DsaPublicKey::from_xml(&public_xml).expect("public xml");
944 assert!(public_again.verify(digest, &signature));
945 }
946
947 #[test]
948 fn digest_to_scalar_truncates_by_digest_width() {
949 let q = BigUint::from_u64(257); let digest = [0x00u8, 0xff];
951 let value = super::digest_to_scalar(&digest, &q);
952 assert_eq!(value, BigUint::one());
953 }
954
955 #[test]
956 fn serialization_roundtrip() {
957 let seed = [0x55u8; 48];
958 let mut drbg = CtrDrbgAes256::new(&seed);
959 let (public, private) = Dsa::generate(&mut drbg, 64).expect("generated DSA key");
960
961 let public_blob = public.to_key_blob();
962 let public_pem = public.to_pem();
963 let public_xml = public.to_xml();
964 let private_blob = private.to_key_blob();
965 let private_pem = private.to_pem();
966 let private_xml = private.to_xml();
967
968 let public_from_blob = DsaPublicKey::from_key_blob(&public_blob).expect("public binary");
969 let public_from_pem = DsaPublicKey::from_pem(&public_pem).expect("public pem");
970 let public_from_xml = DsaPublicKey::from_xml(&public_xml).expect("public xml");
971 let private_from_blob =
972 DsaPrivateKey::from_key_blob(&private_blob).expect("private binary");
973 let private_from_pem = DsaPrivateKey::from_pem(&private_pem).expect("private pem");
974 let private_from_xml = DsaPrivateKey::from_xml(&private_xml).expect("private xml");
975
976 assert_eq!(public_from_blob, public);
977 assert_eq!(public_from_pem, public);
978 assert_eq!(public_from_xml, public);
979 assert_eq!(private_from_blob, private);
980 assert_eq!(private_from_pem, private);
981 assert_eq!(private_from_xml, private);
982 }
983
984 #[test]
985 fn signature_binary_roundtrip() {
986 let signature = DsaSignature {
987 r: BigUint::from_u64(1),
988 s: BigUint::from_u64(9),
989 };
990 let blob = signature.to_key_blob();
991 let parsed = DsaSignature::from_key_blob(&blob).expect("signature");
992 assert_eq!(parsed, signature);
993 }
994
995 #[test]
996 fn verify_message_matches_explicit_digest() {
997 let seed = [0x4Bu8; 48];
998 let mut drbg = CtrDrbgAes256::new(&seed);
999 let (public, private) = Dsa::generate(&mut drbg, 64).expect("generated DSA key");
1000 let message = b"dsa-digest";
1001 let digest = Sha384::digest(message);
1002 let signature = private.sign_digest::<Sha384>(&digest).expect("signature");
1003 assert!(public.verify_message::<Sha384>(message, &signature));
1004 }
1005
1006 #[test]
1007 fn rfc6979_dsa_1024_sha256_sample_vector() {
1008 let p = from_hex(
1010 "86F5CA03DCFEB225063FF830A0C769B9DD9D6153AD91D7CE27F787C43278B447\
1011 E6533B86B18BED6E8A48B784A14C252C5BE0DBF60B86D6385BD2F12FB763ED88\
1012 73ABFD3F5BA2E0A8C0A59082EAC056935E529DAF7C610467899C77ADEDFC846C\
1013 881870B7B19B2B58F9BE0521A17002E3BDD6B86685EE90B3D9A1B02B782B1779",
1014 );
1015 let q = from_hex("996F967F6C8E388D9E28D01E205FBA957A5698B1");
1016 let g = from_hex(
1017 "07B0F92546150B62514BB771E2A0C0CE387F03BDA6C56B505209FF25FD3C133D\
1018 89BBCD97E904E09114D9A7DEFDEADFC9078EA544D2E401AEECC40BB9FBBF78FD\
1019 87995A10A1C27CB7789B594BA7EFB5C4326A9FE59A070E136DB77175464ADCA4\
1020 17BE5DCE2F40D10A46A3A3943F26AB7FD9C0398FF8C76EE0A56826A8A88F1DBD",
1021 );
1022 let x = from_hex("411602CB19A6CCC34494D79D98EF1E7ED5AF25F7");
1023
1024 let (public, private) =
1025 Dsa::from_secret_exponent(&p, &q, &g, &x).expect("RFC key must be valid");
1026 let message = b"sample";
1027 let digest = Sha256::digest(message);
1028
1029 let expected_k = from_hex("519BA0546D0C39202A7D34D7DFA5E760B318BCFB");
1030 let derived_k =
1031 super::rfc6979_nonce::<Sha256>(&q, &x, &digest).expect("RFC nonce must derive");
1032 assert_eq!(derived_k, expected_k, "RFC 6979 nonce mismatch");
1033
1034 let signature = private.sign_message::<Sha256>(message).expect("sign");
1035 let expected_r = from_hex("81F2F5850BE5BC123C43F71A3033E9384611C545");
1036 let expected_s = from_hex("4CDD914B65EB6C66A8AAAD27299BEE6B035F5E89");
1037 assert_eq!(signature.r(), &expected_r);
1038 assert_eq!(signature.s(), &expected_s);
1039 assert!(public.verify_message::<Sha256>(message, &signature));
1040 }
1041}