1use der::{
4 Decode,
5 asn1::{SequenceOf, UintRef},
6};
7use digest::array::{Array, ArraySize};
8use ecdsa::{
9 EcdsaCurve, EncodedPoint, Signature, SignatureSize, SigningKey as EcSigningKey,
10 VerifyingKey as EcVerifyingKey, hazmat::DigestAlgorithm,
11};
12use elliptic_curve::{
13 AffinePoint, CurveArithmetic, FieldBytes, FieldBytesSize,
14 point::AffineCoordinates,
15 sec1::{FromEncodedPoint, ToEncodedPoint},
16};
17use sec1::point::ModulusSize;
18use signature::{Signer, Verifier};
19
20use crate::{SignMessage, ToVerifier, VerifySignature};
21
22pub trait Curve
24where
25 AffinePoint<Self::Curve>: FromEncodedPoint<Self::Curve> + ToEncodedPoint<Self::Curve>,
27 FieldBytesSize<Self::Curve>: ModulusSize,
28 EcSigningKey<Self::Curve>: Signer<Signature<Self::Curve>>,
30 EcVerifyingKey<Self::Curve>: Verifier<Signature<Self::Curve>>,
31 SignatureSize<Self::Curve>: ArraySize,
32{
33 type Curve: EcdsaCurve + CurveArithmetic + DigestAlgorithm;
35}
36
37pub trait Parameters: VerifySignature {
39 fn x(&self) -> Vec<u8>;
41
42 fn y(&self) -> Vec<u8>;
44}
45
46impl<C> Curve for C
47where
48 C: EcdsaCurve + CurveArithmetic + DigestAlgorithm,
49 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
51 FieldBytesSize<C>: ModulusSize,
52 EcSigningKey<C>: Signer<Signature<C>>,
54 EcVerifyingKey<C>: Verifier<Signature<C>>,
55 SignatureSize<C>: ArraySize,
56{
57 type Curve = C;
58}
59
60pub struct VerifyingKey<C: Curve> {
62 pub(crate) key: EcVerifyingKey<C::Curve>,
64}
65
66pub struct SigningKey<C: Curve> {
68 pub(crate) key: EcSigningKey<C::Curve>,
70}
71
72impl<C: Curve> VerifyingKey<C> {
73 pub fn from_coordinates(x: &[u8], y: &[u8]) -> Option<Self> {
75 let x = Array::try_from(x).ok()?;
76 let y = Array::try_from(y).ok()?;
77 let point = EncodedPoint::<C::Curve>::from_affine_coordinates(&x, &y, false);
78 let point = AffinePoint::<C::Curve>::from_encoded_point(&point).into_option()?;
79 let key = EcVerifyingKey::from_affine(point).ok()?;
80 Some(Self { key })
81 }
82}
83
84impl<C: Curve> Parameters for VerifyingKey<C> {
85 fn x(&self) -> Vec<u8> {
86 self.key.as_affine().x().to_vec()
87 }
88
89 fn y(&self) -> Vec<u8> {
90 self.key.as_affine().y().to_vec()
91 }
92}
93
94impl<C: Curve> VerifySignature for VerifyingKey<C> {
95 fn verifies_signature(&self, signature: &[u8], message: &[u8]) -> bool {
96 if let Ok(signature) = Signature::from_slice(signature) {
97 self.key.verify(message, &signature).is_ok()
98 } else if let Ok(sequence) = SequenceOf::<UintRef, 2>::from_der(signature) {
99 let Some(r) = sequence.get(0) else {
106 return false;
107 };
108 let Some(s) = sequence.get(1) else {
109 return false;
110 };
111
112 let mut r_array = Array::<u8, FieldBytesSize<C::Curve>>::default();
114 if r.as_bytes().len() > r_array.len() {
115 return false;
116 }
117 let offset = r_array.len().saturating_sub(r.as_bytes().len());
118 #[allow(clippy::indexing_slicing, reason = "offest is always in bounds")]
119 r_array[offset..].copy_from_slice(r.as_bytes());
120
121 let mut s_array = Array::<u8, FieldBytesSize<C::Curve>>::default();
122 if s.as_bytes().len() > s_array.len() {
123 return false;
124 }
125 let offset = r_array.len().saturating_sub(s.as_bytes().len());
126 #[allow(clippy::indexing_slicing, reason = "offest is always in bounds")]
127 s_array[offset..].copy_from_slice(s.as_bytes());
128
129 let Ok(r) = FieldBytes::<C::Curve>::try_from(r_array.as_slice()) else {
130 return false;
131 };
132 let Ok(s) = FieldBytes::<C::Curve>::try_from(s_array.as_slice()) else {
133 return false;
134 };
135 let Ok(signature) = Signature::<C::Curve>::from_scalars(r, s) else {
136 return false;
137 };
138 self.key.verify(message, &signature).is_ok()
141 } else {
142 false
143 }
144 }
145}
146
147impl<C: Curve> SignMessage for SigningKey<C> {
148 fn sign(&self, message: &[u8]) -> Vec<u8> {
149 let signature: Signature<C::Curve> = self.key.sign(message);
150 signature.to_vec()
151 }
152}
153
154impl<C: Curve> ToVerifier for SigningKey<C> {
155 type Key = VerifyingKey<C>;
156
157 fn verifying_key(&self) -> Self::Key {
158 let key = *self.key.verifying_key();
159 VerifyingKey { key }
160 }
161}