secp256k1/ecdsa/
serialized_signature.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Implements [`SerializedSignature`] and related types.
4//!
5//! DER-serialized signatures have the issue that they can have different lengths.
6//! We want to avoid using `Vec` since that would require allocations making the code slower and
7//! unable to run on platforms without allocator. We implement a special type to encapsulate
8//! serialized signatures and since it's a bit more complicated it has its own module.
9
10use core::borrow::Borrow;
11use core::convert::TryFrom;
12use core::{fmt, ops};
13
14pub use into_iter::IntoIter;
15
16use super::Signature;
17use crate::Error;
18
19pub(crate) const MAX_LEN: usize = 72;
20
21/// A DER serialized Signature
22#[derive(Copy, Clone)]
23pub struct SerializedSignature {
24    data: [u8; MAX_LEN],
25    len: usize,
26}
27
28impl fmt::Debug for SerializedSignature {
29    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, f) }
30}
31
32impl fmt::Display for SerializedSignature {
33    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
34        for v in self {
35            write!(f, "{:02x}", v)?;
36        }
37        Ok(())
38    }
39}
40
41impl PartialEq for SerializedSignature {
42    #[inline]
43    fn eq(&self, other: &SerializedSignature) -> bool { **self == **other }
44}
45
46impl PartialEq<[u8]> for SerializedSignature {
47    #[inline]
48    fn eq(&self, other: &[u8]) -> bool { **self == *other }
49}
50
51impl PartialEq<SerializedSignature> for [u8] {
52    #[inline]
53    fn eq(&self, other: &SerializedSignature) -> bool { *self == **other }
54}
55
56impl PartialOrd for SerializedSignature {
57    fn partial_cmp(&self, other: &SerializedSignature) -> Option<core::cmp::Ordering> {
58        Some((**self).cmp(&**other))
59    }
60}
61
62impl Ord for SerializedSignature {
63    fn cmp(&self, other: &SerializedSignature) -> core::cmp::Ordering { (**self).cmp(&**other) }
64}
65
66impl PartialOrd<[u8]> for SerializedSignature {
67    fn partial_cmp(&self, other: &[u8]) -> Option<core::cmp::Ordering> {
68        (**self).partial_cmp(other)
69    }
70}
71
72impl PartialOrd<SerializedSignature> for [u8] {
73    fn partial_cmp(&self, other: &SerializedSignature) -> Option<core::cmp::Ordering> {
74        self.partial_cmp(&**other)
75    }
76}
77
78impl core::hash::Hash for SerializedSignature {
79    fn hash<H: core::hash::Hasher>(&self, state: &mut H) { (**self).hash(state) }
80}
81
82impl AsRef<[u8]> for SerializedSignature {
83    #[inline]
84    fn as_ref(&self) -> &[u8] { self }
85}
86
87impl Borrow<[u8]> for SerializedSignature {
88    #[inline]
89    fn borrow(&self) -> &[u8] { self }
90}
91
92impl ops::Deref for SerializedSignature {
93    type Target = [u8];
94
95    #[inline]
96    fn deref(&self) -> &[u8] { &self.data[..self.len] }
97}
98
99impl Eq for SerializedSignature {}
100
101impl IntoIterator for SerializedSignature {
102    type IntoIter = IntoIter;
103    type Item = u8;
104
105    #[inline]
106    fn into_iter(self) -> Self::IntoIter { IntoIter::new(self) }
107}
108
109impl<'a> IntoIterator for &'a SerializedSignature {
110    type IntoIter = core::slice::Iter<'a, u8>;
111    type Item = &'a u8;
112
113    #[inline]
114    fn into_iter(self) -> Self::IntoIter { self.iter() }
115}
116
117impl From<Signature> for SerializedSignature {
118    fn from(value: Signature) -> Self { Self::from_signature(&value) }
119}
120
121impl<'a> From<&'a Signature> for SerializedSignature {
122    fn from(value: &'a Signature) -> Self { Self::from_signature(value) }
123}
124
125impl TryFrom<SerializedSignature> for Signature {
126    type Error = Error;
127
128    fn try_from(value: SerializedSignature) -> Result<Self, Self::Error> { value.to_signature() }
129}
130
131impl<'a> TryFrom<&'a SerializedSignature> for Signature {
132    type Error = Error;
133
134    fn try_from(value: &'a SerializedSignature) -> Result<Self, Self::Error> {
135        value.to_signature()
136    }
137}
138
139impl SerializedSignature {
140    /// Creates `SerializedSignature` from data and length.
141    ///
142    /// ## Panics
143    ///
144    /// If `len` > `MAX_LEN`
145    #[inline]
146    pub(crate) fn from_raw_parts(data: [u8; MAX_LEN], len: usize) -> Self {
147        assert!(len <= MAX_LEN, "attempt to set length to {} but the maximum is {}", len, MAX_LEN);
148        SerializedSignature { data, len }
149    }
150
151    /// Get the capacity of the underlying data buffer.
152    #[deprecated = "This always returns 72"]
153    #[inline]
154    pub fn capacity(&self) -> usize { self.data.len() }
155
156    /// Get the len of the used data.
157    #[inline]
158    pub fn len(&self) -> usize { self.len }
159
160    /// Set the length of the object.
161    #[inline]
162    pub(crate) fn set_len_unchecked(&mut self, len: usize) { self.len = len; }
163
164    /// Convert the serialized signature into the Signature struct.
165    /// (This DER deserializes it)
166    #[inline]
167    pub fn to_signature(&self) -> Result<Signature, Error> { Signature::from_der(self) }
168
169    /// Create a SerializedSignature from a Signature.
170    /// (this DER serializes it)
171    #[inline]
172    pub fn from_signature(sig: &Signature) -> SerializedSignature { sig.serialize_der() }
173
174    /// Check if the space is zero.
175    #[deprecated = "This always returns false"]
176    #[inline]
177    pub fn is_empty(&self) -> bool { self.len() == 0 }
178}
179
180/// Separate mod to prevent outside code accidentally breaking invariants.
181mod into_iter {
182    use super::*;
183
184    /// Owned iterator over the bytes of [`SerializedSignature`]
185    ///
186    /// Created by [`IntoIterator::into_iter`] method.
187    // allowed because of https://github.com/rust-lang/rust/issues/98348
188    #[allow(missing_copy_implementations)]
189    #[derive(Debug, Clone)]
190    pub struct IntoIter {
191        signature: SerializedSignature,
192        // invariant: pos <= signature.len()
193        pos: usize,
194    }
195
196    impl IntoIter {
197        #[inline]
198        pub(crate) fn new(signature: SerializedSignature) -> Self {
199            IntoIter {
200                signature,
201                // for all unsigned n: 0 <= n
202                pos: 0,
203            }
204        }
205
206        /// Returns the remaining bytes as a slice.
207        ///
208        /// This method is analogous to [`core::slice::Iter::as_slice`].
209        #[inline]
210        pub fn as_slice(&self) -> &[u8] { &self.signature[self.pos..] }
211    }
212
213    impl Iterator for IntoIter {
214        type Item = u8;
215
216        #[inline]
217        fn next(&mut self) -> Option<Self::Item> {
218            let byte = *self.signature.get(self.pos)?;
219            // can't overflow or break invariant because if pos is too large we return early
220            self.pos += 1;
221            Some(byte)
222        }
223
224        #[inline]
225        fn size_hint(&self) -> (usize, Option<usize>) {
226            // can't underlflow thanks to the invariant
227            let len = self.signature.len() - self.pos;
228            (len, Some(len))
229        }
230
231        // override for speed
232        #[inline]
233        fn nth(&mut self, n: usize) -> Option<Self::Item> {
234            if n >= self.len() {
235                // upholds invariant becasue the values will be equal
236                self.pos = self.signature.len();
237                None
238            } else {
239                // if n < signtature.len() - self.pos then n + self.pos < signature.len() which neither
240                // overflows nor breaks the invariant
241                self.pos += n;
242                self.next()
243            }
244        }
245    }
246
247    impl ExactSizeIterator for IntoIter {}
248
249    impl core::iter::FusedIterator for IntoIter {}
250
251    impl DoubleEndedIterator for IntoIter {
252        #[inline]
253        fn next_back(&mut self) -> Option<Self::Item> {
254            if self.pos == self.signature.len() {
255                return None;
256            }
257
258            // if len is 0 then pos is also 0 thanks to the invariant so we would return before we
259            // reach this
260            let new_len = self.signature.len() - 1;
261            let byte = self.signature[new_len];
262            self.signature.set_len_unchecked(new_len);
263            Some(byte)
264        }
265    }
266}
267
268#[cfg(test)]
269mod tests {
270    use super::{SerializedSignature, MAX_LEN};
271
272    #[test]
273    fn iterator_ops_are_homomorphic() {
274        let mut fake_signature_data = [0; MAX_LEN];
275        for (i, byte) in fake_signature_data.iter_mut().enumerate() {
276            *byte = i as u8; // cast ok because MAX_LEN fits in  u8.
277        }
278
279        let fake_signature = SerializedSignature { data: fake_signature_data, len: MAX_LEN };
280
281        let mut iter1 = fake_signature.into_iter();
282        let mut iter2 = fake_signature.iter();
283
284        // while let so we can compare size_hint and as_slice
285        while let (Some(a), Some(b)) = (iter1.next(), iter2.next()) {
286            assert_eq!(a, *b);
287            assert_eq!(iter1.size_hint(), iter2.size_hint());
288            assert_eq!(iter1.as_slice(), iter2.as_slice());
289        }
290
291        let mut iter1 = fake_signature.into_iter();
292        let mut iter2 = fake_signature.iter();
293
294        // manual next_back instead of rev() so that we can check as_slice()
295        // if next_back is implemented correctly then rev() is also correct - provided by `core`
296        while let (Some(a), Some(b)) = (iter1.next_back(), iter2.next_back()) {
297            assert_eq!(a, *b);
298            assert_eq!(iter1.size_hint(), iter2.size_hint());
299            assert_eq!(iter1.as_slice(), iter2.as_slice());
300        }
301    }
302}