mirror of
				https://github.com/ton-blockchain/ton
				synced 2025-03-09 15:40:10 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			145 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|     This file is part of TON Blockchain Library.
 | |
| 
 | |
|     TON Blockchain Library is free software: you can redistribute it and/or modify
 | |
|     it under the terms of the GNU Lesser General Public License as published by
 | |
|     the Free Software Foundation, either version 2 of the License, or
 | |
|     (at your option) any later version.
 | |
| 
 | |
|     TON Blockchain Library is distributed in the hope that it will be useful,
 | |
|     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|     GNU Lesser General Public License for more details.
 | |
| 
 | |
|     You should have received a copy of the GNU Lesser General Public License
 | |
|     along with TON Blockchain Library.  If not, see <http://www.gnu.org/licenses/>.
 | |
| 
 | |
|     Copyright 2017-2020 Telegram Systems LLP
 | |
| */
 | |
| #pragma once
 | |
| #include <vector>
 | |
| #include "common/refcnt.hpp"
 | |
| #include "openssl/residue.h"
 | |
| #include "ellcurve/Fp25519.h"
 | |
| 
 | |
| namespace ellcurve {
 | |
| using namespace arith;
 | |
| 
 | |
| class TwEdwardsCurve {
 | |
|  public:
 | |
|   struct SegrePoint {
 | |
|     Residue XY, X, Y, Z;  // if x=X/Z and y=Y/T, stores (xy,x,y,1)*Z*T
 | |
|     SegrePoint(td::Ref<ResidueRing> R) : XY(R), X(R), Y(R), Z(R) {
 | |
|     }
 | |
|     SegrePoint(const Residue& x, const Residue& y) : XY(x * y), X(x), Y(y), Z(y.ring_of().one()) {
 | |
|     }
 | |
|     SegrePoint(const TwEdwardsCurve& E, const Residue& y, bool x_sign);
 | |
|     SegrePoint(const SegrePoint& P) : XY(P.XY), X(P.X), Y(P.Y), Z(P.Z) {
 | |
|     }
 | |
|     SegrePoint& operator=(const SegrePoint& P) {
 | |
|       XY = P.XY;
 | |
|       X = P.X;
 | |
|       Y = P.Y;
 | |
|       Z = P.Z;
 | |
|       return *this;
 | |
|     }
 | |
|     bool is_zero() const {
 | |
|       return X.is_zero() && (Y == Z);
 | |
|     }
 | |
|     bool is_valid() const {
 | |
|       return (XY * Z == X * Y) && !(XY.is_zero() && X.is_zero() && Y.is_zero() && Z.is_zero());
 | |
|     }
 | |
|     bool is_finite() const {
 | |
|       return !Z.is_zero();
 | |
|     }
 | |
|     bool is_normalized() const {
 | |
|       return Z == Z.ring_of().one();
 | |
|     }
 | |
|     SegrePoint& normalize() {
 | |
|       auto f = inverse(Z);
 | |
|       XY *= f;
 | |
|       X *= f;
 | |
|       Y *= f;
 | |
|       Z = Z.ring_of().one();
 | |
|       return *this;
 | |
|     }
 | |
|     SegrePoint& zeroize() {
 | |
|       XY = X = Y = Z = Z.ring_of().zero();
 | |
|       return *this;
 | |
|     }
 | |
|     bool export_point(unsigned char buffer[32], bool need_x = true) const;
 | |
|     bool export_point_y(unsigned char buffer[32]) const {
 | |
|       return export_point(buffer, false);
 | |
|     }
 | |
|     bool export_point_u(unsigned char buffer[32]) const;
 | |
|     Residue get_y() const {
 | |
|       return Y * inverse(Z);
 | |
|     }
 | |
|     Residue get_x() const {
 | |
|       return X * inverse(Z);
 | |
|     }
 | |
|     Residue get_u() const {
 | |
|       return (Z + Y) * inverse(Z - Y);
 | |
|     }
 | |
|     void negate() {
 | |
|       XY.negate();
 | |
|       X.negate();
 | |
|     }
 | |
|   };
 | |
| 
 | |
|  private:
 | |
|   td::Ref<ResidueRing> ring;
 | |
|   Residue D;
 | |
|   Residue D2;
 | |
|   Residue Gy;
 | |
|   Bignum P_;
 | |
|   Bignum L;
 | |
|   Bignum Order;
 | |
|   Bignum cofactor;
 | |
|   int cofactor_short;
 | |
|   SegrePoint G;
 | |
|   SegrePoint O;
 | |
|   int table_lines;
 | |
|   std::vector<SegrePoint> table;
 | |
| 
 | |
|   void init();
 | |
| 
 | |
|  public:
 | |
|   TwEdwardsCurve(const Residue& _D, const Residue& _Gy, td::Ref<ResidueRing> _R);
 | |
|   ~TwEdwardsCurve();
 | |
|   const Residue& get_gen_y() const {
 | |
|     return Gy;
 | |
|   }
 | |
|   const Bignum& get_ell() const {
 | |
|     return L;
 | |
|   }
 | |
|   const Bignum& get_order() const {
 | |
|     return Order;
 | |
|   }
 | |
|   td::Ref<ResidueRing> get_base_ring() const {
 | |
|     return ring;
 | |
|   }
 | |
|   const Bignum& get_p() const {
 | |
|     return P_;
 | |
|   }
 | |
|   const SegrePoint& get_base_point() const {
 | |
|     return G;
 | |
|   }
 | |
| 
 | |
|   void set_order_cofactor(const Bignum& order, int cof);
 | |
|   bool recover_x(Residue& x, const Residue& y, bool x_sign) const;
 | |
| 
 | |
|   void add_points(SegrePoint& R, const SegrePoint& P, const SegrePoint& Q) const;
 | |
|   SegrePoint add_points(const SegrePoint& P, const SegrePoint& Q) const;
 | |
|   void double_point(SegrePoint& R, const SegrePoint& P) const;
 | |
|   SegrePoint double_point(const SegrePoint& P) const;
 | |
|   SegrePoint power_point(const SegrePoint& A, const Bignum& n, bool uniform = false) const;
 | |
|   SegrePoint power_gen(const Bignum& n, bool uniform = false) const;
 | |
|   int build_table();
 | |
| 
 | |
|   SegrePoint import_point(const unsigned char point[32], bool& ok) const;
 | |
| };
 | |
| 
 | |
| std::ostream& operator<<(std::ostream& os, const TwEdwardsCurve::SegrePoint& P);
 | |
| const TwEdwardsCurve& Ed25519();
 | |
| }  // namespace ellcurve
 |