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
10extern 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
65pub 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#[derive(Clone, Debug)]
80#[must_use]
81pub struct Signature {
82 r: BigUint,
84
85 s: BigUint,
87}
88
89impl Signature {
90 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 #[must_use]
101 pub fn r(&self) -> &BigUint {
102 &self.r
103 }
104
105 #[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 Self::from_der(bytes).map_err(|_| signature::Error::new())
177 }
178}
179
180#[inline]
182fn two() -> BigUint {
183 BigUint::from(2_u8)
184}