use crate::utils::AffinePoint as SP1AffinePointTrait;
use elliptic_curve::{
ff, generic_array::typenum::consts::U32, subtle::CtOption, CurveArithmetic, FieldBytes,
};
use std::{fmt::Debug, ops::Neg};
pub mod affine;
pub use affine::AffinePoint;
pub mod projective;
pub use projective::ProjectivePoint;
const POINT_LIMBS: usize = 4 * 2;
const FIELD_BYTES_SIZE_USIZE: usize = 32;
#[allow(non_camel_case_types)]
type FIELD_BYTES_SIZE = U32;
pub trait ECDSACurve
where
Self: CurveArithmetic<
FieldBytesSize = FIELD_BYTES_SIZE,
AffinePoint = AffinePoint<Self>,
ProjectivePoint = ProjectivePoint<Self>,
>,
{
type FieldElement: Field<Self> + Neg<Output = Self::FieldElement>;
type SP1AffinePoint: ECDSAPoint;
const EQUATION_A: Self::FieldElement;
const EQUATION_B: Self::FieldElement;
}
pub trait Field<C: ECDSACurve>: ff::PrimeField {
fn from_bytes(bytes: &FieldBytes<C>) -> CtOption<Self>;
fn to_bytes(self) -> FieldBytes<C>;
fn normalize(self) -> Self;
}
pub type FieldElement<C> = <C as ECDSACurve>::FieldElement;
pub trait ECDSAPoint:
SP1AffinePointTrait<POINT_LIMBS> + Clone + Copy + Debug + Send + Sync
{
#[inline]
fn from(x: &[u8], y: &[u8]) -> Self {
<Self as SP1AffinePointTrait<POINT_LIMBS>>::from(x, y)
}
}
impl<P> ECDSAPoint for P where
P: SP1AffinePointTrait<POINT_LIMBS> + Clone + Copy + Debug + Send + Sync
{
}
pub mod ecdh {
pub use elliptic_curve::ecdh::{diffie_hellman, EphemeralSecret, SharedSecret};
use super::{AffinePoint, ECDSACurve, Field};
impl<C: ECDSACurve> From<&AffinePoint<C>> for SharedSecret<C> {
fn from(affine: &AffinePoint<C>) -> SharedSecret<C> {
let (x, _) = affine.field_elements();
x.to_bytes().into()
}
}
}