1use crate::{Error, Result};
4use core::{
5 convert::{TryFrom, TryInto},
6 fmt,
7 ops::{Add, Range},
8};
9use der::{asn1::UIntBytes, Decodable};
10use elliptic_curve_flow::{
11 bigint::Encoding as _,
12 consts::U9,
13 generic_array::{ArrayLength, GenericArray},
14 FieldSize, PrimeCurve,
15};
16
17#[cfg(feature = "alloc")]
18use alloc::boxed::Box;
19
20pub type MaxOverhead = U9;
35
36pub type MaxSize<C> = <<FieldSize<C> as Add>::Output as Add<MaxOverhead>>::Output;
38
39type SignatureBytes<C> = GenericArray<u8, MaxSize<C>>;
41
42pub struct Signature<C>
46where
47 C: PrimeCurve,
48 MaxSize<C>: ArrayLength<u8>,
49 <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
50{
51 bytes: SignatureBytes<C>,
53
54 r_range: Range<usize>,
56
57 s_range: Range<usize>,
59}
60
61impl<C> signature_flow::Signature for Signature<C>
62where
63 C: PrimeCurve,
64 MaxSize<C>: ArrayLength<u8>,
65 <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
66{
67 fn from_bytes(bytes: &[u8]) -> Result<Self> {
69 bytes.try_into()
70 }
71}
72
73#[allow(clippy::len_without_is_empty)]
74impl<C> Signature<C>
75where
76 C: PrimeCurve,
77 MaxSize<C>: ArrayLength<u8>,
78 <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
79{
80 pub fn len(&self) -> usize {
82 self.s_range.end
83 }
84
85 pub fn as_bytes(&self) -> &[u8] {
87 &self.bytes.as_slice()[..self.len()]
88 }
89
90 #[cfg(feature = "alloc")]
92 pub fn to_bytes(&self) -> Box<[u8]> {
93 self.as_bytes().to_vec().into_boxed_slice()
94 }
95
96 pub(crate) fn from_scalar_bytes(r: &[u8], s: &[u8]) -> der::Result<Self> {
98 let mut bytes = SignatureBytes::<C>::default();
99 let mut encoder = der::Encoder::new(&mut bytes);
100 encoder.message(&[&UIntBytes::new(r)?, &UIntBytes::new(s)?])?;
101
102 let sig = encoder.finish()?;
103 sig.try_into().map_err(|_| der::Tag::Sequence.value_error())
104 }
105
106 pub(crate) fn r(&self) -> &[u8] {
108 &self.bytes[self.r_range.clone()]
109 }
110
111 pub(crate) fn s(&self) -> &[u8] {
113 &self.bytes[self.s_range.clone()]
114 }
115}
116
117impl<C> AsRef<[u8]> for Signature<C>
118where
119 C: PrimeCurve,
120 MaxSize<C>: ArrayLength<u8>,
121 <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
122{
123 fn as_ref(&self) -> &[u8] {
124 self.as_bytes()
125 }
126}
127
128impl<C> fmt::Debug 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 fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 f.debug_struct("asn1::Signature")
136 .field("r", &self.r())
137 .field("s", &self.s())
138 .finish()
139 }
140}
141
142impl<C> TryFrom<&[u8]> for Signature<C>
143where
144 C: PrimeCurve,
145 MaxSize<C>: ArrayLength<u8>,
146 <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
147{
148 type Error = Error;
149
150 fn try_from(input: &[u8]) -> Result<Self> {
151 let (r, s) = der::Decoder::new(input)
152 .sequence(|decoder| Ok((UIntBytes::decode(decoder)?, UIntBytes::decode(decoder)?)))
153 .map_err(|_| Error::new())?;
154
155 if r.as_bytes().len() > C::UInt::BYTE_SIZE || s.as_bytes().len() > C::UInt::BYTE_SIZE {
156 return Err(Error::new());
157 }
158
159 let r_range = find_scalar_range(input, r.as_bytes())?;
160 let s_range = find_scalar_range(input, s.as_bytes())?;
161
162 if s_range.end != input.len() {
163 return Err(Error::new());
164 }
165
166 let mut bytes = SignatureBytes::<C>::default();
167 bytes[..s_range.end].copy_from_slice(input);
168
169 Ok(Signature {
170 bytes,
171 r_range,
172 s_range,
173 })
174 }
175}
176
177impl<C> TryFrom<Signature<C>> for super::Signature<C>
178where
179 C: PrimeCurve,
180 MaxSize<C>: ArrayLength<u8>,
181 <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
182{
183 type Error = Error;
184
185 fn try_from(sig: Signature<C>) -> Result<super::Signature<C>> {
186 let mut bytes = super::SignatureBytes::<C>::default();
187 let r_begin = C::UInt::BYTE_SIZE.saturating_sub(sig.r().len());
188 let s_begin = bytes.len().saturating_sub(sig.s().len());
189 bytes[r_begin..C::UInt::BYTE_SIZE].copy_from_slice(sig.r());
190 bytes[s_begin..].copy_from_slice(sig.s());
191 Self::try_from(bytes.as_slice())
192 }
193}
194
195fn find_scalar_range(outer: &[u8], inner: &[u8]) -> Result<Range<usize>> {
197 let outer_start = outer.as_ptr() as usize;
198 let inner_start = inner.as_ptr() as usize;
199 let start = inner_start
200 .checked_sub(outer_start)
201 .ok_or_else(Error::new)?;
202 let end = start.checked_add(inner.len()).ok_or_else(Error::new)?;
203 Ok(Range { start, end })
204}
205
206#[cfg(all(feature = "digest", feature = "hazmat"))]
207impl<C> signature_flow::PrehashSignature for Signature<C>
208where
209 C: PrimeCurve + crate::hazmat::DigestPrimitive,
210 MaxSize<C>: ArrayLength<u8>,
211 <FieldSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
212{
213 type Digest = C::Digest;
214}
215
216#[cfg(all(test, feature = "arithmetic"))]
217mod tests {
218 use elliptic_curve_flow::dev::MockCurve;
219 use signature_flow::Signature as _;
220
221 type Signature = crate::Signature<MockCurve>;
222
223 const EXAMPLE_SIGNATURE: [u8; 64] = [
224 0xf3, 0xac, 0x80, 0x61, 0xb5, 0x14, 0x79, 0x5b, 0x88, 0x43, 0xe3, 0xd6, 0x62, 0x95, 0x27,
225 0xed, 0x2a, 0xfd, 0x6b, 0x1f, 0x6a, 0x55, 0x5a, 0x7a, 0xca, 0xbb, 0x5e, 0x6f, 0x79, 0xc8,
226 0xc2, 0xac, 0x8b, 0xf7, 0x78, 0x19, 0xca, 0x5, 0xa6, 0xb2, 0x78, 0x6c, 0x76, 0x26, 0x2b,
227 0xf7, 0x37, 0x1c, 0xef, 0x97, 0xb2, 0x18, 0xe9, 0x6f, 0x17, 0x5a, 0x3c, 0xcd, 0xda, 0x2a,
228 0xcc, 0x5, 0x89, 0x3,
229 ];
230
231 #[test]
232 fn test_fixed_to_asn1_signature_roundtrip() {
233 let signature1 = Signature::from_bytes(&EXAMPLE_SIGNATURE).unwrap();
234
235 let asn1_signature = signature1.to_der();
237 let signature2 = Signature::from_der(asn1_signature.as_ref()).unwrap();
238
239 assert_eq!(signature1, signature2);
240 }
241
242 #[test]
243 fn test_asn1_too_short_signature() {
244 assert!(Signature::from_der(&[]).is_err());
245 assert!(Signature::from_der(&[der::Tag::Sequence.into()]).is_err());
246 assert!(Signature::from_der(&[der::Tag::Sequence.into(), 0x00]).is_err());
247 assert!(Signature::from_der(&[
248 der::Tag::Sequence.into(),
249 0x03,
250 der::Tag::Integer.into(),
251 0x01,
252 0x01
253 ])
254 .is_err());
255 }
256
257 #[test]
258 fn test_asn1_non_der_signature() {
259 assert!(Signature::from_der(&[
261 der::Tag::Sequence.into(),
262 0x06, der::Tag::Integer.into(),
264 0x01, 0x01, der::Tag::Integer.into(),
267 0x01, 0x01, ])
270 .is_ok());
271
272 assert!(Signature::from_der(&[
276 der::Tag::Sequence.into(),
277 0x81, 0x06, der::Tag::Integer.into(),
280 0x01, 0x01, der::Tag::Integer.into(),
283 0x01, 0x01, ])
286 .is_err());
287 }
288}