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