ts_crypto/
elliptic.rs

1//! Elliptic curve cryptography
2
3use digest::array::{Array, ArraySize};
4use ecdsa::{
5    EcdsaCurve, EncodedPoint, Signature, SignatureSize, SigningKey as EcSigningKey,
6    VerifyingKey as EcVerifyingKey, hazmat::DigestAlgorithm,
7};
8use elliptic_curve::{
9    AffinePoint, CurveArithmetic, FieldBytesSize,
10    point::AffineCoordinates,
11    sec1::{FromEncodedPoint, ToEncodedPoint},
12};
13use sec1::point::ModulusSize;
14use signature::{Signer, Verifier};
15
16use crate::{SignMessage, ToVerifier, VerifySignature};
17
18/// An elliptic curve for `ECDSA`
19pub trait Curve
20where
21    // Curve has point operations
22    AffinePoint<Self::Curve>: FromEncodedPoint<Self::Curve> + ToEncodedPoint<Self::Curve>,
23    FieldBytesSize<Self::Curve>: ModulusSize,
24    // Curve be used in a key
25    EcSigningKey<Self::Curve>: Signer<Signature<Self::Curve>>,
26    EcVerifyingKey<Self::Curve>: Verifier<Signature<Self::Curve>>,
27    SignatureSize<Self::Curve>: ArraySize,
28{
29    /// The inner curve
30    type Curve: EcdsaCurve + CurveArithmetic + DigestAlgorithm;
31}
32
33/// Parameters for an `ECDSA` key
34pub trait Parameters: VerifySignature {
35    /// Get the x coordinate for this key
36    fn x(&self) -> Vec<u8>;
37
38    /// Get the y coordinate for this key
39    fn y(&self) -> Vec<u8>;
40}
41
42impl<C> Curve for C
43where
44    C: EcdsaCurve + CurveArithmetic + DigestAlgorithm,
45    // Curve has point operations
46    AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
47    FieldBytesSize<C>: ModulusSize,
48    // Curve be used in a key
49    EcSigningKey<C>: Signer<Signature<C>>,
50    EcVerifyingKey<C>: Verifier<Signature<C>>,
51    SignatureSize<C>: ArraySize,
52{
53    type Curve = C;
54}
55
56/// An `ECDSA` verifying key
57pub struct VerifyingKey<C: Curve> {
58    /// The inner verifying key
59    pub(crate) key: EcVerifyingKey<C::Curve>,
60}
61
62/// An `ECDSA` signing key
63pub struct SigningKey<C: Curve> {
64    /// The inner signing key
65    pub(crate) key: EcSigningKey<C::Curve>,
66}
67
68impl<C: Curve> VerifyingKey<C> {
69    /// Create a key from coordinates on the curve
70    pub fn from_coordinates(x: &[u8], y: &[u8]) -> Option<Self> {
71        let x = Array::try_from(x).ok()?;
72        let y = Array::try_from(y).ok()?;
73        let point = EncodedPoint::<C::Curve>::from_affine_coordinates(&x, &y, false);
74        let point = AffinePoint::<C::Curve>::from_encoded_point(&point).into_option()?;
75        let key = EcVerifyingKey::from_affine(point).ok()?;
76        Some(Self { key })
77    }
78}
79
80impl<C: Curve> Parameters for VerifyingKey<C> {
81    fn x(&self) -> Vec<u8> {
82        self.key.as_affine().x().to_vec()
83    }
84
85    fn y(&self) -> Vec<u8> {
86        self.key.as_affine().y().to_vec()
87    }
88}
89
90impl<C: Curve> VerifySignature for VerifyingKey<C> {
91    fn verifies_signature(&self, signature: &[u8], message: &[u8]) -> bool {
92        let Ok(signature) = Signature::from_slice(signature) else {
93            return false;
94        };
95        self.key.verify(message, &signature).is_ok()
96    }
97}
98
99impl<C: Curve> SignMessage for SigningKey<C> {
100    fn sign(&self, message: &[u8]) -> Vec<u8> {
101        let signature: Signature<C::Curve> = self.key.sign(message);
102        signature.to_vec()
103    }
104}
105
106impl<C: Curve> ToVerifier for SigningKey<C> {
107    type Key = VerifyingKey<C>;
108
109    fn verifying_key(&self) -> Self::Key {
110        let key = *self.key.verifying_key();
111        VerifyingKey { key }
112    }
113}