1use crate::{Error, Result};
4use core::{
5 fmt,
6 ops::{Add, Range},
7};
8use der::{asn1::UIntRef, Decode, Encode, Reader};
9use elliptic_curve::{
10 bigint::Encoding as _,
11 consts::U9,
12 generic_array::{ArrayLength, GenericArray},
13 FieldSize, PrimeCurve,
14};
15
16#[cfg(feature = "alloc")]
17use alloc::boxed::Box;
18
19#[cfg(feature = "serde")]
20use serdect::serde::{de, ser, Deserialize, Serialize};
21
22pub type MaxOverhead = U9;
37
38pub type MaxSize<C> = <<FieldSize<C> as Add>::Output as Add<MaxOverhead>>::Output;
40
41type SignatureBytes<C> = GenericArray<u8, MaxSize<C>>;
43
44pub struct Signature<C>
48where
49 C: PrimeCurve,
50 MaxSize<C>: ArrayLength<u8>,
51 <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
52{
53 bytes: SignatureBytes<C>,
55
56 r_range: Range<usize>,
58
59 s_range: Range<usize>,
61}
62
63impl<C> signature::Signature for Signature<C>
64where
65 C: PrimeCurve,
66 MaxSize<C>: ArrayLength<u8>,
67 <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
68{
69 fn from_bytes(bytes: &[u8]) -> Result<Self> {
71 bytes.try_into()
72 }
73}
74
75#[allow(clippy::len_without_is_empty)]
76impl<C> Signature<C>
77where
78 C: PrimeCurve,
79 MaxSize<C>: ArrayLength<u8>,
80 <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
81{
82 pub fn len(&self) -> usize {
84 self.s_range.end
85 }
86
87 pub fn as_bytes(&self) -> &[u8] {
89 &self.bytes.as_slice()[..self.len()]
90 }
91
92 #[cfg(feature = "alloc")]
94 pub fn to_bytes(&self) -> Box<[u8]> {
95 self.as_bytes().to_vec().into_boxed_slice()
96 }
97
98 pub(crate) fn from_scalar_bytes(r: &[u8], s: &[u8]) -> der::Result<Self> {
100 let r = UIntRef::new(r)?;
101 let s = UIntRef::new(s)?;
102
103 let mut bytes = SignatureBytes::<C>::default();
104 let mut writer = der::SliceWriter::new(&mut bytes);
105
106 writer.sequence((r.encoded_len()? + s.encoded_len()?)?, |seq| {
107 seq.encode(&r)?;
108 seq.encode(&s)
109 })?;
110
111 writer
112 .finish()?
113 .try_into()
114 .map_err(|_| der::Tag::Sequence.value_error())
115 }
116
117 pub(crate) fn r(&self) -> &[u8] {
119 &self.bytes[self.r_range.clone()]
120 }
121
122 pub(crate) fn s(&self) -> &[u8] {
124 &self.bytes[self.s_range.clone()]
125 }
126}
127
128impl<C> AsRef<[u8]> for Signature<C>
129where
130 C: PrimeCurve,
131 MaxSize<C>: ArrayLength<u8>,
132 <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
133{
134 fn as_ref(&self) -> &[u8] {
135 self.as_bytes()
136 }
137}
138
139impl<C> fmt::Debug for Signature<C>
140where
141 C: PrimeCurve,
142 MaxSize<C>: ArrayLength<u8>,
143 <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
144{
145 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146 write!(f, "ecdsa::der::Signature<{:?}>(", C::default())?;
147
148 for &byte in self.as_ref() {
149 write!(f, "{:02X}", byte)?;
150 }
151
152 write!(f, ")")
153 }
154}
155
156impl<C> TryFrom<&[u8]> for Signature<C>
157where
158 C: PrimeCurve,
159 MaxSize<C>: ArrayLength<u8>,
160 <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
161{
162 type Error = Error;
163
164 fn try_from(input: &[u8]) -> Result<Self> {
165 let (r, s) = decode_der(input).map_err(|_| Error::new())?;
166
167 if r.as_bytes().len() > C::UInt::BYTE_SIZE || s.as_bytes().len() > C::UInt::BYTE_SIZE {
168 return Err(Error::new());
169 }
170
171 let r_range = find_scalar_range(input, r.as_bytes())?;
172 let s_range = find_scalar_range(input, s.as_bytes())?;
173
174 if s_range.end != input.len() {
175 return Err(Error::new());
176 }
177
178 let mut bytes = SignatureBytes::<C>::default();
179 bytes[..s_range.end].copy_from_slice(input);
180
181 Ok(Signature {
182 bytes,
183 r_range,
184 s_range,
185 })
186 }
187}
188
189impl<C> TryFrom<Signature<C>> for super::Signature<C>
190where
191 C: PrimeCurve,
192 MaxSize<C>: ArrayLength<u8>,
193 <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
194{
195 type Error = Error;
196
197 fn try_from(sig: Signature<C>) -> Result<super::Signature<C>> {
198 let mut bytes = super::SignatureBytes::<C>::default();
199 let r_begin = C::UInt::BYTE_SIZE.saturating_sub(sig.r().len());
200 let s_begin = bytes.len().saturating_sub(sig.s().len());
201 bytes[r_begin..C::UInt::BYTE_SIZE].copy_from_slice(sig.r());
202 bytes[s_begin..].copy_from_slice(sig.s());
203 Self::try_from(bytes.as_slice())
204 }
205}
206
207#[cfg(feature = "serde")]
208#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
209impl<C> Serialize for Signature<C>
210where
211 C: PrimeCurve,
212 MaxSize<C>: ArrayLength<u8>,
213 <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
214{
215 fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
216 where
217 S: ser::Serializer,
218 {
219 serdect::slice::serialize_hex_upper_or_bin(&self.as_bytes(), serializer)
220 }
221}
222
223#[cfg(feature = "serde")]
224#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
225impl<'de, C> Deserialize<'de> for Signature<C>
226where
227 C: PrimeCurve,
228 MaxSize<C>: ArrayLength<u8>,
229 <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
230{
231 fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
232 where
233 D: de::Deserializer<'de>,
234 {
235 let mut buf = SignatureBytes::<C>::default();
236 let slice = serdect::slice::deserialize_hex_or_bin(&mut buf, deserializer)?;
237 Self::try_from(slice).map_err(de::Error::custom)
238 }
239}
240
241fn decode_der(der_bytes: &[u8]) -> der::Result<(UIntRef<'_>, UIntRef<'_>)> {
243 let mut reader = der::SliceReader::new(der_bytes)?;
244 let header = der::Header::decode(&mut reader)?;
245 header.tag.assert_eq(der::Tag::Sequence)?;
246
247 let ret = reader.read_nested(header.length, |reader| {
248 let r = UIntRef::decode(reader)?;
249 let s = UIntRef::decode(reader)?;
250 Ok((r, s))
251 })?;
252
253 reader.finish(ret)
254}
255
256fn find_scalar_range(outer: &[u8], inner: &[u8]) -> Result<Range<usize>> {
258 let outer_start = outer.as_ptr() as usize;
259 let inner_start = inner.as_ptr() as usize;
260 let start = inner_start
261 .checked_sub(outer_start)
262 .ok_or_else(Error::new)?;
263 let end = start.checked_add(inner.len()).ok_or_else(Error::new)?;
264 Ok(Range { start, end })
265}
266
267#[cfg(all(feature = "digest", feature = "hazmat"))]
268impl<C> signature::PrehashSignature for Signature<C>
269where
270 C: PrimeCurve + crate::hazmat::DigestPrimitive,
271 MaxSize<C>: ArrayLength<u8>,
272 <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
273{
274 type Digest = C::Digest;
275}
276
277#[cfg(all(test, feature = "arithmetic"))]
278mod tests {
279 use elliptic_curve::dev::MockCurve;
280 use signature::Signature as _;
281
282 type Signature = crate::Signature<MockCurve>;
283
284 const EXAMPLE_SIGNATURE: [u8; 64] = [
285 0xf3, 0xac, 0x80, 0x61, 0xb5, 0x14, 0x79, 0x5b, 0x88, 0x43, 0xe3, 0xd6, 0x62, 0x95, 0x27,
286 0xed, 0x2a, 0xfd, 0x6b, 0x1f, 0x6a, 0x55, 0x5a, 0x7a, 0xca, 0xbb, 0x5e, 0x6f, 0x79, 0xc8,
287 0xc2, 0xac, 0x8b, 0xf7, 0x78, 0x19, 0xca, 0x5, 0xa6, 0xb2, 0x78, 0x6c, 0x76, 0x26, 0x2b,
288 0xf7, 0x37, 0x1c, 0xef, 0x97, 0xb2, 0x18, 0xe9, 0x6f, 0x17, 0x5a, 0x3c, 0xcd, 0xda, 0x2a,
289 0xcc, 0x5, 0x89, 0x3,
290 ];
291
292 #[test]
293 fn test_fixed_to_asn1_signature_roundtrip() {
294 let signature1 = Signature::from_bytes(&EXAMPLE_SIGNATURE).unwrap();
295
296 let asn1_signature = signature1.to_der();
298 let signature2 = Signature::from_der(asn1_signature.as_ref()).unwrap();
299
300 assert_eq!(signature1, signature2);
301 }
302
303 #[test]
304 fn test_asn1_too_short_signature() {
305 assert!(Signature::from_der(&[]).is_err());
306 assert!(Signature::from_der(&[der::Tag::Sequence.into()]).is_err());
307 assert!(Signature::from_der(&[der::Tag::Sequence.into(), 0x00]).is_err());
308 assert!(Signature::from_der(&[
309 der::Tag::Sequence.into(),
310 0x03,
311 der::Tag::Integer.into(),
312 0x01,
313 0x01
314 ])
315 .is_err());
316 }
317
318 #[test]
319 fn test_asn1_non_der_signature() {
320 assert!(Signature::from_der(&[
322 der::Tag::Sequence.into(),
323 0x06, der::Tag::Integer.into(),
325 0x01, 0x01, der::Tag::Integer.into(),
328 0x01, 0x01, ])
331 .is_ok());
332
333 assert!(Signature::from_der(&[
337 der::Tag::Sequence.into(),
338 0x81, 0x06, der::Tag::Integer.into(),
341 0x01, 0x01, der::Tag::Integer.into(),
344 0x01, 0x01, ])
347 .is_err());
348 }
349}