Skip to content

Commit 0d62c1f

Browse files
committed
dsa: reduce Box<[u8]> allocation in SignatureEncoding::to_vec
dsa: refactor: move `SignatureRef` to `signature_ref.rs`
1 parent 6cc40e5 commit 0d62c1f

File tree

2 files changed

+91
-17
lines changed

2 files changed

+91
-17
lines changed

dsa/src/lib.rs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ use pkcs8::spki::ObjectIdentifier;
6666

6767
mod components;
6868
mod generate;
69+
mod signature_ref;
6970
mod signing_key;
7071
mod size;
7172
mod verifying_key;
@@ -77,10 +78,10 @@ pub const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.10040.4.
7778

7879
use alloc::{boxed::Box, vec::Vec};
7980
use pkcs8::der::{
80-
self, Decode, DecodeValue, Encode, EncodeValue, FixedTag, Header, Length, Reader, Sequence,
81-
Writer, asn1::UintRef,
81+
self, Decode, DecodeValue, Encode, EncodeValue, Header, Length, Reader, Sequence, Writer,
8282
};
8383
use signature::SignatureEncoding;
84+
use signature_ref::{SignatureBoxed, SignatureRef};
8485

8586
/// Container of the DSA signature
8687
#[derive(Clone, Debug)]
@@ -112,34 +113,33 @@ impl Signature {
112113
pub fn s(&self) -> &NonZero<BoxedUint> {
113114
&self.s
114115
}
116+
117+
fn to_boxed(&self) -> SignatureBoxed {
118+
SignatureBoxed::new(self)
119+
}
120+
fn to_der_using_ref(&self) -> der::Result<Vec<u8>> {
121+
self.to_boxed().to_ref()?.to_der()
122+
}
115123
}
116124

117125
impl<'a> DecodeValue<'a> for Signature {
118126
type Error = der::Error;
119127

120-
fn decode_value<R: Reader<'a>>(reader: &mut R, _header: Header) -> der::Result<Self> {
121-
let r = UintRef::decode(reader)?;
122-
let s = UintRef::decode(reader)?;
123-
124-
let r = BoxedUint::from_be_slice(r.as_bytes(), r.as_bytes().len() as u32 * 8)
125-
.map_err(|_| UintRef::TAG.value_error())?;
126-
let s = BoxedUint::from_be_slice(s.as_bytes(), s.as_bytes().len() as u32 * 8)
127-
.map_err(|_| UintRef::TAG.value_error())?;
128+
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
129+
let signature_ref = SignatureRef::decode_value(reader, header)?;
128130

129-
Self::from_components(r, s).ok_or_else(|| reader.error(UintRef::TAG.value_error()))
131+
signature_ref.to_owned()
130132
}
131133
}
132134

133135
impl EncodeValue for Signature {
134136
fn value_len(&self) -> der::Result<Length> {
135-
UintRef::new(&self.r.to_be_bytes())?.encoded_len()?
136-
+ UintRef::new(&self.s.to_be_bytes())?.encoded_len()?
137+
// TODO: avoid Box<[u8]> allocation here
138+
self.to_boxed().to_ref()?.value_len()
137139
}
138140

139141
fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
140-
UintRef::new(&self.r.to_be_bytes())?.encode(writer)?;
141-
UintRef::new(&self.s.to_be_bytes())?.encode(writer)?;
142-
Ok(())
142+
self.to_boxed().to_ref()?.encode_value(writer)
143143
}
144144
}
145145

@@ -171,7 +171,7 @@ impl SignatureEncoding for Signature {
171171
}
172172

173173
fn to_vec(&self) -> Vec<u8> {
174-
self.to_der().expect("DER encoding error")
174+
self.to_der_using_ref().expect("DER encoding error")
175175
}
176176
}
177177

dsa/src/signature_ref.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
use alloc::boxed::Box;
2+
use crypto_bigint::{BoxedUint, NonZero};
3+
use pkcs8::der::{
4+
self, Decode, DecodeValue, Encode, EncodeValue, FixedTag, Header, Length, Reader, Sequence,
5+
Writer, asn1::UintRef,
6+
};
7+
8+
use crate::Signature;
9+
10+
pub(crate) struct SignatureBoxed {
11+
r: Box<[u8]>,
12+
s: Box<[u8]>,
13+
}
14+
impl SignatureBoxed {
15+
pub fn new(sig: &Signature) -> Self {
16+
Self {
17+
r: sig.r().to_be_bytes(),
18+
s: sig.s().to_be_bytes(),
19+
}
20+
}
21+
22+
pub fn to_ref(&self) -> der::Result<SignatureRef<'_>> {
23+
Ok(SignatureRef {
24+
r: UintRef::new(&self.r)?,
25+
s: UintRef::new(&self.s)?,
26+
})
27+
}
28+
}
29+
30+
pub(crate) struct SignatureRef<'a> {
31+
r: UintRef<'a>,
32+
s: UintRef<'a>,
33+
}
34+
impl<'a> SignatureRef<'a> {
35+
pub fn to_owned(&self) -> der::Result<Signature> {
36+
let r = BoxedUint::from_be_slice(self.r.as_bytes(), self.r.as_bytes().len() as u32 * 8)
37+
.map_err(|_| UintRef::TAG.value_error())?;
38+
let s = BoxedUint::from_be_slice(self.s.as_bytes(), self.s.as_bytes().len() as u32 * 8)
39+
.map_err(|_| UintRef::TAG.value_error())?;
40+
41+
let r = NonZero::new(r)
42+
.into_option()
43+
.ok_or(UintRef::TAG.value_error())?;
44+
let s = NonZero::new(s)
45+
.into_option()
46+
.ok_or(UintRef::TAG.value_error())?;
47+
48+
Ok(Signature::from_components(r, s))
49+
}
50+
}
51+
52+
impl<'a> DecodeValue<'a> for SignatureRef<'a> {
53+
type Error = der::Error;
54+
55+
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
56+
Ok(SignatureRef {
57+
r: UintRef::decode(reader)?,
58+
s: UintRef::decode(reader)?,
59+
})
60+
}
61+
}
62+
63+
impl EncodeValue for SignatureRef<'_> {
64+
fn value_len(&self) -> der::Result<Length> {
65+
self.r.encoded_len()? + self.s.encoded_len()?
66+
}
67+
68+
fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
69+
self.r.encode(writer)?;
70+
self.s.encode(writer)?;
71+
Ok(())
72+
}
73+
}
74+
impl<'a> Sequence<'a> for SignatureRef<'a> {}

0 commit comments

Comments
 (0)