1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#![no_std]
#![forbid(unsafe_code)]
#![warn(missing_docs, rust_2018_idioms)]
#![doc = include_str!("../README.md")]
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
)]

//!
//! # Examples
//!
//! Generate a DSA keypair
//!
//! ```
//! # use dsa::{KeySize, Components, SigningKey};
//! let mut csprng = rand::thread_rng();
//! let components = Components::generate(&mut csprng, KeySize::DSA_2048_256);
//! let signing_key = SigningKey::generate(&mut csprng, components);
//! let verifying_key = signing_key.verifying_key();
//! ```
//!
//! Create keypair from existing components
//!
//! ```
//! # use dsa::{Components, SigningKey, VerifyingKey};
//! # use num_bigint::BigUint;
//! # use num_traits::One;
//! # let read_common_parameters = || (BigUint::one(), BigUint::one(), BigUint::one());
//! # let read_public_component = || BigUint::one();
//! # let read_private_component = || BigUint::one();
//! # || -> signature::Result<()> {
//! let (p, q, g) = read_common_parameters();
//! let components = Components::from_components(p, q, g)?;
//!
//! let x = read_public_component();
//! let verifying_key = VerifyingKey::from_components(components, x)?;
//!
//! let y = read_private_component();
//! let signing_key = SigningKey::from_components(verifying_key, y)?;
//!
//! # Ok(())
//! # }();
//! ```
//!

extern crate alloc;

pub use crate::{
    components::Components, signing_key::SigningKey, size::KeySize, verifying_key::VerifyingKey,
};

pub use num_bigint::BigUint;
pub use pkcs8;
pub use signature;

use pkcs8::spki::ObjectIdentifier;

mod components;
mod generate;
mod signing_key;
mod size;
mod verifying_key;

/// DSA object identifier as defined by [RFC3279 § 2.3.2].
///
/// [RFC3279 2.3.2]: https://www.rfc-editor.org/rfc/rfc3279#section-2.3.2
pub const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.10040.4.1");

use alloc::{boxed::Box, vec::Vec};
use num_traits::Zero;
use pkcs8::der::{
    self, asn1::UintRef, Decode, DecodeValue, Encode, EncodeValue, Header, Length, Reader,
    Sequence, Writer,
};
use signature::SignatureEncoding;

/// Container of the DSA signature
#[derive(Clone, Debug)]
#[must_use]
pub struct Signature {
    /// Signature part r
    r: BigUint,

    /// Signature part s
    s: BigUint,
}

impl Signature {
    /// Create a new Signature container from its components
    pub fn from_components(r: BigUint, s: BigUint) -> signature::Result<Self> {
        if r.is_zero() || s.is_zero() {
            return Err(signature::Error::new());
        }

        Ok(Self { r, s })
    }

    /// Signature part r
    #[must_use]
    pub fn r(&self) -> &BigUint {
        &self.r
    }

    /// Signature part s
    #[must_use]
    pub fn s(&self) -> &BigUint {
        &self.s
    }
}

impl<'a> DecodeValue<'a> for Signature {
    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
        reader.read_nested(header.length, |reader| {
            let r = UintRef::decode(reader)?;
            let s = UintRef::decode(reader)?;

            let r = BigUint::from_bytes_be(r.as_bytes());
            let s = BigUint::from_bytes_be(s.as_bytes());

            Self::from_components(r, s).map_err(|_| der::Tag::Integer.value_error())
        })
    }
}

impl EncodeValue for Signature {
    fn value_len(&self) -> der::Result<Length> {
        UintRef::new(&self.r.to_bytes_be())?.encoded_len()?
            + UintRef::new(&self.s.to_bytes_be())?.encoded_len()?
    }

    fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
        UintRef::new(&self.r.to_bytes_be())?.encode(writer)?;
        UintRef::new(&self.s.to_bytes_be())?.encode(writer)?;
        Ok(())
    }
}

impl From<Signature> for Box<[u8]> {
    fn from(sig: Signature) -> Box<[u8]> {
        sig.to_bytes()
    }
}

impl PartialEq for Signature {
    fn eq(&self, other: &Self) -> bool {
        self.r().eq(other.r()) && self.s().eq(other.s())
    }
}

impl PartialOrd for Signature {
    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
        (self.r(), self.s()).partial_cmp(&(other.r(), other.s()))
    }
}

impl<'a> Sequence<'a> for Signature {}

impl SignatureEncoding for Signature {
    type Repr = Box<[u8]>;

    fn to_bytes(&self) -> Box<[u8]> {
        SignatureEncoding::to_vec(self).into_boxed_slice()
    }

    fn to_vec(&self) -> Vec<u8> {
        self.to_der().expect("DER encoding error")
    }
}

impl TryFrom<&[u8]> for Signature {
    type Error = signature::Error;

    fn try_from(bytes: &[u8]) -> signature::Result<Self> {
        // TODO(tarcieri): capture error source when `std` feature enabled
        Self::from_der(bytes).map_err(|_| signature::Error::new())
    }
}

/// Returns a `BigUint` with the value 2
#[inline]
fn two() -> BigUint {
    BigUint::from(2_u8)
}