From 56b66a832b3461de1216d5d2b4cedb0717e107c6 Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Fri, 6 Jun 2025 16:28:44 +0200 Subject: [PATCH] ecdsa: der: use impl `EncodeValue`/`DecodeValue` on `SignatureRef` (#965) --- ecdsa/src/der.rs | 66 +++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/ecdsa/src/der.rs b/ecdsa/src/der.rs index 65a88de..541f395 100644 --- a/ecdsa/src/der.rs +++ b/ecdsa/src/der.rs @@ -8,7 +8,10 @@ use core::{ fmt::{self, Debug}, ops::{Add, Range}, }; -use der::{Decode, Encode, FixedTag, Header, Length, Reader, Tag, Writer, asn1::UintRef}; +use der::{ + Decode, DecodeValue, Encode, EncodeValue, FixedTag, Header, Length, Reader, Sequence, Tag, + Writer, asn1::UintRef, +}; use elliptic_curve::{ FieldBytesSize, array::{Array, ArraySize, typenum::Unsigned}, @@ -82,7 +85,7 @@ where { /// Parse signature from DER-encoded bytes. pub fn from_bytes(input: &[u8]) -> Result { - let (r, s) = decode_der(input).map_err(|_| Error::new())?; + let SignatureRef { r, s } = SignatureRef::from_der(input).map_err(|_| Error::new())?; if r.as_bytes().len() > C::FieldBytesSize::USIZE || s.as_bytes().len() > C::FieldBytesSize::USIZE @@ -110,19 +113,13 @@ where /// Create an ASN.1 DER encoded signature from big endian `r` and `s` scalar /// components. pub(crate) fn from_components(r: &[u8], s: &[u8]) -> der::Result { - let r = UintRef::new(r)?; - let s = UintRef::new(s)?; - + let sig = SignatureRef { + r: UintRef::new(r)?, + s: UintRef::new(s)?, + }; let mut bytes = SignatureBytes::::default(); - let mut writer = der::SliceWriter::new(&mut bytes); - writer.sequence((r.encoded_len()? + s.encoded_len()?)?, |seq| { - seq.encode(&r)?; - seq.encode(&s) - })?; - - writer - .finish()? + sig.encode_to_slice(&mut bytes)? .try_into() .map_err(|_| Tag::Sequence.value_error()) } @@ -356,20 +353,37 @@ where } } -/// Decode the `r` and `s` components of a DER-encoded ECDSA signature. -fn decode_der(der_bytes: &[u8]) -> der::Result<(UintRef<'_>, UintRef<'_>)> { - let mut reader = der::SliceReader::new(der_bytes)?; - let header = Header::decode(&mut reader)?; - header.tag.assert_eq(Tag::Sequence)?; - - let ret = reader.read_nested::<_, _, der::Error>(header.length, |reader| { - let r = UintRef::decode(reader)?; - let s = UintRef::decode(reader)?; - Ok((r, s)) - })?; - - reader.finish(ret) +struct SignatureRef<'a> { + pub r: UintRef<'a>, + pub s: UintRef<'a>, } +impl EncodeValue for SignatureRef<'_> { + fn value_len(&self) -> der::Result { + self.r.encoded_len()? + self.s.encoded_len()? + } + + fn encode_value(&self, encoder: &mut impl Writer) -> der::Result<()> { + self.r.encode(encoder)?; + self.s.encode(encoder)?; + Ok(()) + } +} +impl<'a> SignatureRef<'a> { + fn decode_value_inner>(reader: &mut R) -> der::Result { + Ok(Self { + r: UintRef::decode(reader)?, + s: UintRef::decode(reader)?, + }) + } +} +impl<'a> DecodeValue<'a> for SignatureRef<'a> { + type Error = der::Error; + + fn decode_value>(reader: &mut R, header: Header) -> der::Result { + reader.read_nested(header.length, Self::decode_value_inner) + } +} +impl<'a> Sequence<'a> for SignatureRef<'a> {} /// Locate the range within a slice at which a particular subslice is located fn find_scalar_range(outer: &[u8], inner: &[u8]) -> Result> {