Skip to main content

dsa/
lib.rs

1#![no_std]
2#![forbid(unsafe_code)]
3#![warn(missing_docs, rust_2018_idioms)]
4#![doc = include_str!("../README.md")]
5#![doc(
6    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
7    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
8)]
9
10//!
11//! # Examples
12//!
13//! Generate a DSA keypair
14//!
15//! ```
16//! # use dsa::{KeySize, Components, SigningKey};
17//! let mut csprng = rand::thread_rng();
18//! let components = Components::generate(&mut csprng, KeySize::DSA_2048_256);
19//! let signing_key = SigningKey::generate(&mut csprng, components);
20//! let verifying_key = signing_key.verifying_key();
21//! ```
22//!
23//! Create keypair from existing components
24//!
25//! ```
26//! # use dsa::{Components, SigningKey, VerifyingKey};
27//! # use num_bigint::BigUint;
28//! # use num_traits::One;
29//! # let read_common_parameters = || (BigUint::one(), BigUint::one(), BigUint::one());
30//! # let read_public_component = || BigUint::one();
31//! # let read_private_component = || BigUint::one();
32//! # || -> signature::Result<()> {
33//! let (p, q, g) = read_common_parameters();
34//! let components = Components::from_components(p, q, g)?;
35//!
36//! let x = read_public_component();
37//! let verifying_key = VerifyingKey::from_components(components, x)?;
38//!
39//! let y = read_private_component();
40//! let signing_key = SigningKey::from_components(verifying_key, y)?;
41//!
42//! # Ok(())
43//! # }();
44//! ```
45//!
46
47extern crate alloc;
48
49pub use crate::{
50    components::Components, signing_key::SigningKey, size::KeySize, verifying_key::VerifyingKey,
51};
52
53pub use num_bigint::BigUint;
54pub use pkcs8;
55pub use signature;
56
57use pkcs8::spki::ObjectIdentifier;
58
59mod components;
60mod generate;
61mod signing_key;
62mod size;
63mod verifying_key;
64
65/// DSA object identifier as defined by [RFC3279 ยง 2.3.2].
66///
67/// [RFC3279 2.3.2]: https://www.rfc-editor.org/rfc/rfc3279#section-2.3.2
68pub const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.10040.4.1");
69
70use alloc::{boxed::Box, vec::Vec};
71use num_traits::Zero;
72use pkcs8::der::{
73    self, asn1::UintRef, Decode, DecodeValue, Encode, EncodeValue, Header, Length, Reader,
74    Sequence, Writer,
75};
76use signature::SignatureEncoding;
77
78/// Container of the DSA signature
79#[derive(Clone, Debug)]
80#[must_use]
81pub struct Signature {
82    /// Signature part r
83    r: BigUint,
84
85    /// Signature part s
86    s: BigUint,
87}
88
89impl Signature {
90    /// Create a new Signature container from its components
91    pub fn from_components(r: BigUint, s: BigUint) -> signature::Result<Self> {
92        if r.is_zero() || s.is_zero() {
93            return Err(signature::Error::new());
94        }
95
96        Ok(Self { r, s })
97    }
98
99    /// Signature part r
100    #[must_use]
101    pub fn r(&self) -> &BigUint {
102        &self.r
103    }
104
105    /// Signature part s
106    #[must_use]
107    pub fn s(&self) -> &BigUint {
108        &self.s
109    }
110}
111
112impl<'a> DecodeValue<'a> for Signature {
113    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
114        reader.read_nested(header.length, |reader| {
115            let r = UintRef::decode(reader)?;
116            let s = UintRef::decode(reader)?;
117
118            let r = BigUint::from_bytes_be(r.as_bytes());
119            let s = BigUint::from_bytes_be(s.as_bytes());
120
121            Self::from_components(r, s).map_err(|_| der::Tag::Integer.value_error())
122        })
123    }
124}
125
126impl EncodeValue for Signature {
127    fn value_len(&self) -> der::Result<Length> {
128        UintRef::new(&self.r.to_bytes_be())?.encoded_len()?
129            + UintRef::new(&self.s.to_bytes_be())?.encoded_len()?
130    }
131
132    fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
133        UintRef::new(&self.r.to_bytes_be())?.encode(writer)?;
134        UintRef::new(&self.s.to_bytes_be())?.encode(writer)?;
135        Ok(())
136    }
137}
138
139impl From<Signature> for Box<[u8]> {
140    fn from(sig: Signature) -> Box<[u8]> {
141        sig.to_bytes()
142    }
143}
144
145impl PartialEq for Signature {
146    fn eq(&self, other: &Self) -> bool {
147        self.r().eq(other.r()) && self.s().eq(other.s())
148    }
149}
150
151impl PartialOrd for Signature {
152    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
153        (self.r(), self.s()).partial_cmp(&(other.r(), other.s()))
154    }
155}
156
157impl<'a> Sequence<'a> for Signature {}
158
159impl SignatureEncoding for Signature {
160    type Repr = Box<[u8]>;
161
162    fn to_bytes(&self) -> Box<[u8]> {
163        SignatureEncoding::to_vec(self).into_boxed_slice()
164    }
165
166    fn to_vec(&self) -> Vec<u8> {
167        self.to_der().expect("DER encoding error")
168    }
169}
170
171impl TryFrom<&[u8]> for Signature {
172    type Error = signature::Error;
173
174    fn try_from(bytes: &[u8]) -> signature::Result<Self> {
175        // TODO(tarcieri): capture error source when `std` feature enabled
176        Self::from_der(bytes).map_err(|_| signature::Error::new())
177    }
178}
179
180/// Returns a `BigUint` with the value 2
181#[inline]
182fn two() -> BigUint {
183    BigUint::from(2_u8)
184}