mirror of
				https://github.com/ton-blockchain/ton
				synced 2025-03-09 15:40:10 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			138 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			138 lines
		
	
	
	
		
			3.8 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
 | |
| */
 | |
| #include "ellcurve/Montgomery.h"
 | |
| 
 | |
| #include <assert.h>
 | |
| #include <cstring>
 | |
| 
 | |
| namespace ellcurve {
 | |
| using namespace arith;
 | |
| 
 | |
| class MontgomeryCurve;
 | |
| 
 | |
| void MontgomeryCurve::init() {
 | |
|   assert(!((a_short + 2) & 3) && a_short >= 0);
 | |
| }
 | |
| 
 | |
| void MontgomeryCurve::set_order_cofactor(const Bignum& order, int cof) {
 | |
|   assert(order > 0);
 | |
|   assert(cof >= 0);
 | |
|   assert(cof == 0 || (order % cof) == 0);
 | |
|   Order = order;
 | |
|   cofactor = cofactor_short = cof;
 | |
|   if (cof > 0) {
 | |
|     L = order / cof;
 | |
|     assert(is_prime(L));
 | |
|   }
 | |
|   assert(!power_gen_xz(1).is_infty());
 | |
|   assert(power_gen_xz(Order).is_infty());
 | |
| }
 | |
| 
 | |
| // computes u(P+Q)*u(P-Q) as X/Z
 | |
| MontgomeryCurve::PointXZ MontgomeryCurve::add_xz(const MontgomeryCurve::PointXZ& P,
 | |
|                                                  const MontgomeryCurve::PointXZ& Q) const {
 | |
|   Residue u = (P.X + P.Z) * (Q.X - Q.Z);
 | |
|   Residue v = (P.X - P.Z) * (Q.X + Q.Z);
 | |
|   return MontgomeryCurve::PointXZ(sqr(u + v), sqr(u - v));
 | |
| }
 | |
| 
 | |
| // computes u(2P) as X/Z
 | |
| MontgomeryCurve::PointXZ MontgomeryCurve::double_xz(const MontgomeryCurve::PointXZ& P) const {
 | |
|   Residue u = sqr(P.X + P.Z);
 | |
|   Residue v = sqr(P.X - P.Z);
 | |
|   Residue w = u - v;
 | |
|   return PointXZ(u * v, w * (v + Residue(a_short, ring) * w));
 | |
| }
 | |
| 
 | |
| MontgomeryCurve::PointXZ MontgomeryCurve::power_gen_xz(const Bignum& n) const {
 | |
|   return power_xz(Gu, n);
 | |
| }
 | |
| 
 | |
| MontgomeryCurve::PointXZ MontgomeryCurve::power_xz(const Residue& u, const Bignum& n) const {
 | |
|   return power_xz(PointXZ(u), n);
 | |
| }
 | |
| 
 | |
| // computes u([n]P) in form X/Z
 | |
| MontgomeryCurve::PointXZ MontgomeryCurve::power_xz(const PointXZ& A, const Bignum& n) const {
 | |
|   assert(n >= 0);
 | |
|   if (n == 0) {
 | |
|     return PointXZ(ring);
 | |
|   }
 | |
| 
 | |
|   int k = n.num_bits();
 | |
|   PointXZ P(A);
 | |
|   PointXZ Q(double_xz(P));
 | |
|   for (int i = k - 2; i >= 0; --i) {
 | |
|     PointXZ PQ(add_xz(P, Q));
 | |
|     PQ.X *= A.Z;
 | |
|     PQ.Z *= A.X;
 | |
|     if (n[i]) {
 | |
|       P = PQ;
 | |
|       Q = double_xz(Q);
 | |
|     } else {
 | |
|       Q = PQ;
 | |
|       P = double_xz(P);
 | |
|     }
 | |
|   }
 | |
|   return P;
 | |
| }
 | |
| 
 | |
| bool MontgomeryCurve::PointXZ::export_point_y(unsigned char buffer[32]) const {
 | |
|   if ((X + Z).is_zero()) {
 | |
|     std::memset(buffer, 0xff, 32);
 | |
|     return false;
 | |
|   } else {
 | |
|     get_y().extract().export_lsb(buffer, 32);
 | |
|     return true;
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool MontgomeryCurve::PointXZ::export_point_u(unsigned char buffer[32]) const {
 | |
|   if (Z.is_zero()) {
 | |
|     std::memset(buffer, 0xff, 32);
 | |
|     return false;
 | |
|   } else {
 | |
|     get_u().extract().export_lsb(buffer, 32);
 | |
|     return true;
 | |
|   }
 | |
| }
 | |
| 
 | |
| MontgomeryCurve::PointXZ MontgomeryCurve::import_point_u(const unsigned char point[32]) const {
 | |
|   Bignum u;
 | |
|   u.import_lsb(point, 32);
 | |
|   u[255] = 0;
 | |
|   return PointXZ(Residue(u, ring));
 | |
| }
 | |
| 
 | |
| MontgomeryCurve::PointXZ MontgomeryCurve::import_point_y(const unsigned char point[32]) const {
 | |
|   Bignum y;
 | |
|   y.import_lsb(point, 32);
 | |
|   y[255] = 0;
 | |
|   return PointXZ(Residue(y, ring), true);
 | |
| }
 | |
| 
 | |
| const MontgomeryCurve& Curve25519() {
 | |
|   static const MontgomeryCurve Curve25519 = [] {
 | |
|     MontgomeryCurve res(486662, 9, Fp25519());
 | |
|     res.set_order_cofactor(hex_string{"80000000000000000000000000000000a6f7cef517bce6b2c09318d2e7ae9f68"}, 8);
 | |
|     return res;
 | |
|   }();
 | |
|   return Curve25519;
 | |
| }
 | |
| }  // namespace ellcurve
 |