From 2b1cad7bb5d26cdc06a667e768aeeb258644b24d Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Mon, 12 May 2025 11:58:35 +0200 Subject: [PATCH 1/3] ecdsa: der: use impl `EncodeValue`/`DecodeValue` on `SignatureRef` --- ecdsa/src/der.rs | 72 +++++++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/ecdsa/src/der.rs b/ecdsa/src/der.rs index 65a88def..8e1971ed 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 } = decode_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,19 +353,44 @@ where } } +struct SignatureRef<'a> { + pub r: UintRef<'a>, + pub s: UintRef<'a>, +} +impl<'a> EncodeValue for SignatureRef<'a> { + 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) -> core::result::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, + ) -> core::result::Result { + reader.read_nested(header.length, Self::decode_value_inner) + } +} +impl<'a> Sequence<'a> for SignatureRef<'a> {} + /// 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) +fn decode_der(der_bytes: &[u8]) -> der::Result> { + SignatureRef::from_der(der_bytes) } /// Locate the range within a slice at which a particular subslice is located From 6c23b72199c738926b544629e00e4b4bb3a3b031 Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Mon, 12 May 2025 18:35:23 +0200 Subject: [PATCH 2/3] ecdsa: use `der::Result` --- ecdsa/src/der.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ecdsa/src/der.rs b/ecdsa/src/der.rs index 8e1971ed..28f9a1c7 100644 --- a/ecdsa/src/der.rs +++ b/ecdsa/src/der.rs @@ -369,7 +369,7 @@ impl<'a> EncodeValue for SignatureRef<'a> { } } impl<'a> SignatureRef<'a> { - fn decode_value_inner>(reader: &mut R) -> core::result::Result { + fn decode_value_inner>(reader: &mut R) -> der::Result { Ok(Self { r: UintRef::decode(reader)?, s: UintRef::decode(reader)?, @@ -379,10 +379,7 @@ impl<'a> SignatureRef<'a> { impl<'a> DecodeValue<'a> for SignatureRef<'a> { type Error = der::Error; - fn decode_value>( - reader: &mut R, - header: Header, - ) -> core::result::Result { + fn decode_value>(reader: &mut R, header: Header) -> der::Result { reader.read_nested(header.length, Self::decode_value_inner) } } From 6ffb2a6ea54a144d59cfdd4054d6f086dcb7d102 Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Mon, 12 May 2025 18:37:08 +0200 Subject: [PATCH 3/3] ecdsa: cargo clippy --- ecdsa/src/der.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ecdsa/src/der.rs b/ecdsa/src/der.rs index 28f9a1c7..ddb25d5d 100644 --- a/ecdsa/src/der.rs +++ b/ecdsa/src/der.rs @@ -357,7 +357,7 @@ struct SignatureRef<'a> { pub r: UintRef<'a>, pub s: UintRef<'a>, } -impl<'a> EncodeValue for SignatureRef<'a> { +impl EncodeValue for SignatureRef<'_> { fn value_len(&self) -> der::Result { self.r.encoded_len()? + self.s.encoded_len()? }