/* 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 . Copyright 2017-2019 Telegram Systems LLP */ #pragma once #include #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 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 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 table; void init(); public: TwEdwardsCurve(const Residue& _D, const Residue& _Gy, td::Ref _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 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