Skip to content

Commit 56b66a8

Browse files
authored
ecdsa: der: use impl EncodeValue/DecodeValue on SignatureRef (#965)
1 parent 4babc06 commit 56b66a8

File tree

1 file changed

+38
-24
lines changed

1 file changed

+38
-24
lines changed

ecdsa/src/der.rs

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ use core::{
88
fmt::{self, Debug},
99
ops::{Add, Range},
1010
};
11-
use der::{Decode, Encode, FixedTag, Header, Length, Reader, Tag, Writer, asn1::UintRef};
11+
use der::{
12+
Decode, DecodeValue, Encode, EncodeValue, FixedTag, Header, Length, Reader, Sequence, Tag,
13+
Writer, asn1::UintRef,
14+
};
1215
use elliptic_curve::{
1316
FieldBytesSize,
1417
array::{Array, ArraySize, typenum::Unsigned},
@@ -82,7 +85,7 @@ where
8285
{
8386
/// Parse signature from DER-encoded bytes.
8487
pub fn from_bytes(input: &[u8]) -> Result<Self> {
85-
let (r, s) = decode_der(input).map_err(|_| Error::new())?;
88+
let SignatureRef { r, s } = SignatureRef::from_der(input).map_err(|_| Error::new())?;
8689

8790
if r.as_bytes().len() > C::FieldBytesSize::USIZE
8891
|| s.as_bytes().len() > C::FieldBytesSize::USIZE
@@ -110,19 +113,13 @@ where
110113
/// Create an ASN.1 DER encoded signature from big endian `r` and `s` scalar
111114
/// components.
112115
pub(crate) fn from_components(r: &[u8], s: &[u8]) -> der::Result<Self> {
113-
let r = UintRef::new(r)?;
114-
let s = UintRef::new(s)?;
115-
116+
let sig = SignatureRef {
117+
r: UintRef::new(r)?,
118+
s: UintRef::new(s)?,
119+
};
116120
let mut bytes = SignatureBytes::<C>::default();
117-
let mut writer = der::SliceWriter::new(&mut bytes);
118-
119-
writer.sequence((r.encoded_len()? + s.encoded_len()?)?, |seq| {
120-
seq.encode(&r)?;
121-
seq.encode(&s)
122-
})?;
123121

124-
writer
125-
.finish()?
122+
sig.encode_to_slice(&mut bytes)?
126123
.try_into()
127124
.map_err(|_| Tag::Sequence.value_error())
128125
}
@@ -356,20 +353,37 @@ where
356353
}
357354
}
358355

359-
/// Decode the `r` and `s` components of a DER-encoded ECDSA signature.
360-
fn decode_der(der_bytes: &[u8]) -> der::Result<(UintRef<'_>, UintRef<'_>)> {
361-
let mut reader = der::SliceReader::new(der_bytes)?;
362-
let header = Header::decode(&mut reader)?;
363-
header.tag.assert_eq(Tag::Sequence)?;
356+
struct SignatureRef<'a> {
357+
pub r: UintRef<'a>,
358+
pub s: UintRef<'a>,
359+
}
360+
impl EncodeValue for SignatureRef<'_> {
361+
fn value_len(&self) -> der::Result<Length> {
362+
self.r.encoded_len()? + self.s.encoded_len()?
363+
}
364364

365-
let ret = reader.read_nested::<_, _, der::Error>(header.length, |reader| {
366-
let r = UintRef::decode(reader)?;
367-
let s = UintRef::decode(reader)?;
368-
Ok((r, s))
369-
})?;
365+
fn encode_value(&self, encoder: &mut impl Writer) -> der::Result<()> {
366+
self.r.encode(encoder)?;
367+
self.s.encode(encoder)?;
368+
Ok(())
369+
}
370+
}
371+
impl<'a> SignatureRef<'a> {
372+
fn decode_value_inner<R: Reader<'a>>(reader: &mut R) -> der::Result<Self> {
373+
Ok(Self {
374+
r: UintRef::decode(reader)?,
375+
s: UintRef::decode(reader)?,
376+
})
377+
}
378+
}
379+
impl<'a> DecodeValue<'a> for SignatureRef<'a> {
380+
type Error = der::Error;
370381

371-
reader.finish(ret)
382+
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
383+
reader.read_nested(header.length, Self::decode_value_inner)
384+
}
372385
}
386+
impl<'a> Sequence<'a> for SignatureRef<'a> {}
373387

374388
/// Locate the range within a slice at which a particular subslice is located
375389
fn find_scalar_range(outer: &[u8], inner: &[u8]) -> Result<Range<usize>> {

0 commit comments

Comments
 (0)