// elliptic curves over GF(2^(L*K)) #pragma once #define MAXL 16 #define MAXK 193 class field; class field_element; class curve; class full_curve_parameter; class small_field { friend class field; #if MAXL > 16 // assumes that unsigned short is at least 16 bits typedef unsigned lunit; #else #if MAXL > 8 typedef unsigned short lunit; #else typedef unsigned char lunit; #endif #endif // construction public: small_field( unsigned L, unsigned root ); ~small_field(); // methods public: unsigned * curve_order(); // properties public: lunit * const alog; // index range is [0..(BASE-2)] lunit * const log; // index range is [1..(BASE-1)], but log[0] is set to (BASE-1) const unsigned L, BASE, BASE_M1; }; // elements are polynomials with coefficients in small_field class field : public small_field { friend class curve; friend class field_element; friend class full_curve_parameter; // construction public: field( class full_curve_parameter & a ); virtual unsigned rand( unsigned base ); // methods private: typedef unsigned poly[ 2 * MAXK ]; static void add( const poly a, const poly b, poly c ); static void copy ( const poly a, poly b ); static int equal( const poly a, const poly b ); void div( poly a, unsigned b ); void set_random( poly a ); int set_K( unsigned K, unsigned T ); void reduce( poly a ); void mul( const poly a, const poly b, poly c ); void square( const poly a, poly b ); void inverse( const poly a, poly b ); int trace( const poly a ); int slow_trace( const poly a ); void quad_solve( const poly a, poly b ); void sqrt( const poly a, poly b ); void addmul( poly a, unsigned alpha, unsigned j, const poly b ); friend field_element sqrt( const field_element x ); void unpack( const bigint & x, poly a ); bigint pack( const poly a ); // properties private: const unsigned M, K, T; unsigned prng; poly nzt; // element with non-zero trace poly tm; // trace mask ( trace(x) is number of bits in x & tm ) }; class field_element { friend class field; friend class curve; friend class point; friend field_element sqrt( const field_element x ); // construction public: field_element( const field_element & x ); field_element( field * F ); field_element(); // methods public: int operator == ( const field_element & x ) const; int operator == ( unsigned x ) const; field_element operator + ( const field_element & x ) const; field_element operator * ( const field_element & x ) const; field_element operator / ( const field_element & x ) const; field_element & operator = ( const field_element & x ); // properties private: field * f; field::poly v; }; class point { friend class curve; friend class ec_crypt; friend point operator * ( const bigint & k, const point & P ); // construction public: point(); point( const point & P ); point( curve * C ); // methods public: point & operator = ( const point & P ); point operator + ( const point & P ) const; point operator - ( const point & P ) const; // properties private: curve * c; field_element x, y; }; struct curve_parameter { unsigned L; unsigned K; unsigned T; unsigned root; unsigned b; unsigned nso; unsigned ntf; }; class full_curve_parameter : public curve_parameter { // construction public: full_curve_parameter( const curve_parameter & bp ); // properties public: bigint tm, p0, P0; }; class curve : public field { friend class curve_factory; friend class point; friend point operator * ( const bigint & k, const point & P ); // construction public: curve( full_curve_parameter & a ); // methods public: point random_point(); static bigint pack( const point & P ); point unpack( const bigint & X ); static bigint to_vlong( const point & P ); // methods private: void add( const point & P, const point & Q, point & R ); void sub( const point & P, const point & Q, point & R ); void mul( const point & P, const bigint & x, point & Q ); int calc_y( point & R, unsigned ybit=0 ); static int MOV( unsigned B, const bigint & q, const bigint & r ); static bigint small_lucas( bigint P, bigint Z, unsigned ik ); static unsigned ybit( const field_element & x ); static field_element sq( const field_element & x ); // properties public: point PP; // point with prime order bigint p; // prime order of P // properties private: field_element b; }; class curve_factory // Used for calculating curve_parameter but in practice // use pre-calculated table ncdata.hpp or equivalent { // construction public: curve_factory( unsigned L ); // can take a long time ~curve_factory(); // methods public: int find( unsigned K, curve_parameter & result ); // properties private: unsigned L; unsigned root; unsigned so_min; unsigned so_max; unsigned *so_set; bigint comp; }; struct bigint_pair { bigint r; bigint s; }; class ECC_BASE : private curve { // construction public: ECC_BASE( full_curve_parameter & a ); ~ECC_BASE(); // methods public: virtual unsigned rand( unsigned base ); bigint create_private_key(); bigint create_public_key( const bigint & private_key ); bigint encrypt( const bigint & public_key, bigint & message ); bigint decrypt( const bigint & private_key, const bigint & message ); bigint_pair schnorr_sign( const bigint & msg, const bigint & private_key, bigint (*hash)(const bigint &, const bigint &) = 0, unsigned hashbits = 1 ); bool schnorr_verify( const bigint & msg, const bigint_pair & sig, const bigint & public_key, bigint (*hash)(const bigint &, const bigint &) = 0, unsigned hashbits = 1 ); bigint_pair dsa_sign( const bigint & msg, const bigint & private_key, bigint (*hash)(const bigint &, const bigint &)); bool dsa_verify( const bigint & msg, const bigint_pair & sig, const bigint & public_key, bigint (*hash)(const bigint &, const bigint &)); // properties public: const unsigned bits; // number of bits in prime order #ifdef WIN32 HCRYPTPROV m_cryptProv; #endif };