Main Page   Reference Manual   Compound List   File List  

libecc/point.h

Go to the documentation of this file.
00001 //
00009 //
00010 // This file is part of the libecc package.
00011 // Copyright (C) 2003, 2004 by
00012 //
00013 // Carlo Wood, Run on IRC <carlo@alinoe.com>
00014 // RSA-1024 0x624ACAD5 1997-01-26                    Sign & Encrypt
00015 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6  F6 F6 55 DD 1C DC FF 61
00016 //
00017 // This program is free software; you can redistribute it and/or
00018 // modify it under the terms of the GNU General Public License
00019 // as published by the Free Software Foundation; either version 2
00020 // of the License, or (at your option) any later version.
00021 //
00022 // This program is distributed in the hope that it will be useful,
00023 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00024 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025 // GNU General Public License for more details.
00026 //
00027 // You should have received a copy of the GNU General Public License
00028 // along with this program; if not, write to the Free Software
00029 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00030 //
00031 
00032 #ifndef LIBECC_POINT_H
00033 #define LIBECC_POINT_H
00034 
00035 #include <gmpxx.h>
00036 #include <libecc/polynomial.h>
00037 #include <libecc/rds.h>
00038 
00039 namespacelibecc {
00040 
00041 enum order_algorithm {
00042   order_brute_force,
00043   order_default = order_brute_force
00044 };
00045 
00056 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00057   classpoint {
00058   public:
00062     typedef Polynomial polynomial_type;
00063   private:
00064     polynomial_type M_x;        // x coordinate of the point.
00065     polynomial_type M_y;        // y coordinate of the point.
00066     bool M_zero;                // Set when this is the 'point at infinity', in which case M_x and M_y are meaningless.
00067   public:
00071     point(void) : M_zero(true) { }
00077     point(std::string x, std::string y) : M_x(x), M_y(y), M_zero(false) { }
00081     point(polynomial_type const& x, polynomial_type const& y) : M_x(x), M_y(y), M_zero(false) { }
00085     point& operator=(point const& p1);
00089     point& operator+=(point const& p1);
00093     void MULTIPLY_and_assign(point const& pnt, mpz_class const& scalar);
00097     mpz_class order(order_algorithm algorithm = order_default) const;
00103     bool operator==(point const& p1) const;
00109     bool operator!=(point const& p1) const;
00115     bool check(void) const;
00121     polynomial_type const& get_x(void) const{ return M_x; }
00127     polynomial_type const& get_y(void) const{ return M_y; }
00131     bool is_zero(void) const{ return M_zero; }
00135     void print_on(std::ostream& os) const;
00139     void randomize(rds& random_source);
00140   };
00141 
00142 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00143   void
00144   point<Polynomial, a, b>::randomize(rds& random_source)
00145   {
00146     M_zero = false;
00147     for(bool notdone = true; notdone;)
00148     {
00149       random_source.read(M_x.get_bitset());
00150       bitset_digit_t x2buf[polynomial_type::square_digits];
00151       polynomial_type& x2 = M_x.square(x2buf);                    // x^2
00152       polynomial_type r((M_x + a) * x2 + b);                      // x^3 + a x^2 + b
00153       try
00154       {
00155         M_y = polynomial_type(M_x, r);
00156         notdone = false;
00157       }
00158       catch(std::domain_error const&)
00159       {
00160       }
00161     }
00162     bitset_digit_t digit;
00163     random_source.read(&digit, 1);
00164     if ((digit & 1))
00165     {
00166       if (!M_x.get_bitset().any())
00167         M_zero = true;
00168       else
00169         M_y += M_x;
00170     }
00171   }
00172 
00173 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00174   bool
00175   point<Polynomial, a, b>::check(void) const
00176  {
00177     if (M_zero)
00178       return true;
00179     bitset_digit_t x2buf[polynomial_type::square_digits];
00180     polynomial_type& x2 = M_x.square(x2buf);                    // x^2
00181     polynomial_type r((M_x + a) * x2 + b);                      // x^3 + a x^2 + b
00182     bitset_digit_t y2buf[polynomial_type::square_digits];
00183     polynomial_type& y2 = M_y.square(y2buf);
00184     polynomial_type l(y2 + M_x * M_y);                          // y^2 + x y
00185     return (r == l);
00186   }
00187 
00188 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00189   inline bool
00190   point<Polynomial, a, b>::operator!=(point const& p1) const
00191  {
00192     return (M_zero != p1.M_zero || (!M_zero && (M_x != p1.M_x || M_y != p1.M_y)));
00193   }
00194 
00195 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00196   inline bool
00197   point<Polynomial, a, b>::operator==(point const& p1) const
00198  {
00199     return !operator!=(p1);
00200   }
00201 
00202 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00203   std::ostream&
00204   operator<<(std::ostream& os, point<Polynomial, a, b> const& p1)
00205   {
00206     if (p1.is_zero())
00207       os << "O";
00208     else
00209       os << '(' << p1.get_x() << ", " << p1.get_y() << ')';
00210     return os;
00211   }
00212 
00213 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00214   void
00215   point<Polynomial, a, b>::print_on(std::ostream& os) const
00216  {
00217     if (M_zero)
00218       os << "O";
00219     else
00220       os << '(' << M_x << ", " << M_y << ')';
00221   }
00222 
00223 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00224   point<Polynomial, a, b>&
00225   point<Polynomial, a, b>::operator=(point<Polynomial, a, b> const& p1)
00226   {
00227     M_zero = p1.M_zero;
00228     if (!M_zero)
00229     {
00230       M_x = p1.M_x;
00231       M_y = p1.M_y;
00232     }
00233     return *this;
00234   }
00235 
00236 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00237   void
00238   point<Polynomial, a, b>::MULTIPLY_and_assign(point<Polynomial, a, b> const& pnt, mpz_class const& scalar)
00239   {
00240     point tmp(pnt);
00241     M_zero = true;
00242     unsigned long int p = 0;
00243     size_t end = mpz_sizeinbase(scalar.get_mpz_t(), 2);
00244     for (unsigned long int bit = mpz_scan1(scalar.get_mpz_t(), 0); bit < end; bit = mpz_scan1(scalar.get_mpz_t(), bit + 1))
00245     {
00246       for (; p < bit; ++p)
00247         tmp += tmp;
00248       *this += tmp;
00249     }
00250   }
00251 
00252 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00253   point<Polynomial, a, b>&
00254   point<Polynomial, a, b>::operator+=(point<Polynomial, a, b> const& p1)
00255   {
00256     if (!p1.M_zero)
00257     {
00258       if (M_zero)
00259       {
00260         M_x = p1.M_x;
00261         M_y = p1.M_y;
00262         M_zero = false;
00263       }
00264       else if (M_x != p1.M_x)
00265       {
00266         polynomial_type s = M_y + p1.M_y;
00267         s /= M_x + p1.M_x;
00268         bitset_digit_t s2buf[polynomial_type::square_digits];
00269         polynomial_type& new_x = s.square(s2buf);
00270         new_x += s + M_x;
00271         new_x += p1.M_x + a;
00272         M_y += s * (M_x + new_x) + new_x;
00273         M_x = new_x;
00274       }
00275       else if (M_y == p1.M_y && M_x.get_bitset().any())
00276       {
00277         polynomial_type s = M_x + M_y / M_x;
00278         bitset_digit_t s2buf[polynomial_type::square_digits];
00279         polynomial_type& new_x = s.square(s2buf);
00280         new_x += s + a;
00281         bitset_digit_t x2buf[polynomial_type::square_digits];
00282         polynomial_type& x2 = M_x.square(x2buf);
00283         M_y = x2 + new_x * (s + polynomial_type::unity());
00284         M_x = new_x;
00285       }
00286       else
00287         M_zero = true;
00288     }
00289     return *this;
00290   }
00291 
00292 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00293   mpz_class
00294   point<Polynomial, a, b>::order(order_algorithm algorithm) const
00295  {
00296     mpz_class n = 1;
00297     switch(algorithm)
00298     {
00299       case order_brute_force:
00300       {
00301         point nP(*this);
00302         while(!nP.M_zero && nP.M_x.get_bitset().any())
00303         {
00304           nP += *this;
00305           ++n;
00306         }
00307         if (!nP.M_zero)
00308           n += n;
00309         break;
00310       }
00311     }
00312     return n;
00313   }
00314 
00315 } // namespace libecc
00316 
00317 #endif // LIBECC_POINT_H
Copyright © 2002-2008 Carlo Wood.  All rights reserved.