From 0f7e642f247ccf35d2554415f174d9af7395883a Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 17 Jan 2024 10:08:05 -0700 Subject: [PATCH] ecdsa: add DER support to `SignatureWithOid` Adds the following methods: - `from_der_with_digest` - `from_der_with_oid` - `to_der` These handle deserializing/serializing ASN.1 DER-encoded signatures. --- ecdsa/src/lib.rs | 61 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/ecdsa/src/lib.rs b/ecdsa/src/lib.rs index a098fa6c..2a351825 100644 --- a/ecdsa/src/lib.rs +++ b/ecdsa/src/lib.rs @@ -595,6 +595,27 @@ where Self::new_with_digest::(Signature::::from_slice(slice)?) } + /// Parse a signature from ASN.1 DER and associate the given digest's OID with it. + #[cfg(feature = "der")] + pub fn from_der_with_digest(der_bytes: &[u8]) -> Result + where + D: AssociatedOid + Digest, + der::MaxSize: ArraySize, + as Add>::Output: Add + ArraySize, + { + Self::new_with_digest::(Signature::::from_der(der_bytes)?) + } + + /// Parse a signature from ASN.1 DER and associate the given OID with it. + #[cfg(feature = "der")] + pub fn from_der_with_oid(der_bytes: &[u8], oid: ObjectIdentifier) -> Result + where + der::MaxSize: ArraySize, + as Add>::Output: Add + ArraySize, + { + Self::new(Signature::::from_der(der_bytes)?, oid) + } + /// Get the fixed-width ECDSA signature. pub fn signature(&self) -> &Signature { &self.signature @@ -605,13 +626,27 @@ where self.oid } - /// Serialize this signature as bytes. + /// Serialize this signature as fixed-width bytes. pub fn to_bytes(&self) -> SignatureBytes where SignatureSize: ArraySize, { self.signature.to_bytes() } + + /// Serialize this signature as ASN.1 DER. + /// + /// Note that this includes only the `r` and `s` signature components, and not the OID. + /// + /// See [`der::Signature`] documentation for more information. + #[cfg(feature = "der")] + pub fn to_der(&self) -> der::Signature + where + der::MaxSize: ArraySize, + as Add>::Output: Add + ArraySize, + { + self.signature.clone().into() + } } #[cfg(feature = "digest")] @@ -644,6 +679,30 @@ where } } +#[cfg(all(feature = "der", feature = "digest"))] +impl From> for der::Signature +where + C: PrimeCurve, + der::MaxSize: ArraySize, + as Add>::Output: Add + ArraySize, +{ + fn from(sig: SignatureWithOid) -> der::Signature { + sig.to_der() + } +} + +#[cfg(all(feature = "der", feature = "digest"))] +impl From<&SignatureWithOid> for der::Signature +where + C: PrimeCurve, + der::MaxSize: ArraySize, + as Add>::Output: Add + ArraySize, +{ + fn from(sig: &SignatureWithOid) -> der::Signature { + sig.to_der() + } +} + /// NOTE: this implementation assumes the default digest for the given elliptic /// curve as defined by [`hazmat::DigestPrimitive`]. ///