github.com/ledgerwatch/erigon-lib@v1.0.0/pedersen_hash/elliptic_curve_constants.h (about) 1 #ifndef STARKWARE_CRYPTO_ELLIPTIC_CURVE_CONSTANTS_H_ 2 #define STARKWARE_CRYPTO_ELLIPTIC_CURVE_CONSTANTS_H_ 3 4 #include <array> 5 #include <utility> 6 #include <vector> 7 8 #include "big_int.h" 9 #include "elliptic_curve.h" 10 #include "prime_field_element.h" 11 12 namespace starkware { 13 14 /* 15 Contains a set of constants that go along with an elliptic curve. 16 17 FieldElementT is the underlying field of the curve. 18 The equation of the elliptic curve is y^2 = x^3 + k_alpha * x + k_beta. 19 k_order is the size of the group. 20 k_points are points on the curve that were generated independently in a "nothing up my sleeve" 21 manner to ensure that no one knows their discrete log. 22 */ 23 template <typename FieldElementT> 24 struct EllipticCurveConstants { 25 public: 26 using ValueType = typename FieldElementT::ValueType; 27 28 const FieldElementT k_alpha; 29 const FieldElementT k_beta; 30 const ValueType k_order; 31 const std::vector<EcPoint<FieldElementT>> k_points; 32 33 constexpr EllipticCurveConstants( 34 const FieldElementT& k_alpha, const FieldElementT& k_beta, const ValueType& k_order, 35 std::vector<EcPoint<FieldElementT>> k_points) noexcept 36 : k_alpha(k_alpha), k_beta(k_beta), k_order(k_order), k_points(std::move(k_points)) {} 37 38 constexpr EllipticCurveConstants( 39 const ValueType& k_alpha, const ValueType& k_beta, const ValueType& k_order, 40 std::initializer_list<std::pair<ValueType, ValueType>> k_points) noexcept 41 : EllipticCurveConstants( 42 FieldElementT::FromBigInt(k_alpha), FieldElementT::FromBigInt(k_beta), k_order, 43 ECPointsVectorFromPairs(std::move(k_points))) {} 44 45 private: 46 static std::vector<EcPoint<FieldElementT>> ECPointsVectorFromPairs( 47 std::initializer_list<std::pair<ValueType, ValueType>> k_points) { 48 std::vector<EcPoint<FieldElementT>> res; 49 res.reserve(k_points.size()); 50 51 for (const auto& p : k_points) { 52 res.emplace_back(FieldElementT::FromBigInt(p.first), FieldElementT::FromBigInt(p.second)); 53 } 54 return res; 55 } 56 }; 57 58 /* 59 This elliptic curve over the prime field PrimeFieldElement was chosen in a "nothing up my sleeve" 60 manner to show that we don't know any special properties of this curve (other than being of prime 61 order). 62 63 alpha was chosen to be 1 because any elliptic curve has an isomorphic curve with a small alpha, 64 but we didn't want a zero alpha because then the discriminant is small. 65 66 beta was generated in the following way: 67 1) Take beta to be the integer whose digits are the first 76 decimal digits of pi (76 is the 68 number of digits required to represent a field element). 69 2) While [y^2 = x^3 + alpha * x + beta] is not a curve of prime order, increase beta by 1. 70 71 The points were generated by the following steps: 72 1) Take the decimal digits of pi and split them into chunks of 76 digits (the number of decimal 73 digits of the modulus). 74 75 2) Each chunk of 76 digits is the seed for generating a point, except for the first chunk 76 which was used for generating the curve. 77 78 3) For each such seed x: 79 80 3.1) while (x^3 + alpha * x + beta) is not a square in the prime field: 81 increase x by 1. 82 83 3.2) (x, square_root(x^3 + alpha * x + beta)) is a point on the elliptic curve (for square_root 84 the smaller root). 85 86 87 4) The first two points are taken as-is, as they will be used as the shift point and the 88 ECDSA generator point. 89 90 5) Each subsequent point P is expanded to 248 or 4 points alternatingly, by taking the set 91 {2^i P : 0 <= i < 248} or {2^i P : 0 <= i < 3}. 248 is chosen to be the largest multiple of 8 92 lower than 251. 93 94 This is a sage code that implements these steps: 95 96 R = RealField(400000) 97 long_pi_string = '3' + str(R(pi))[2:] 98 p = 2^251 + 17 * 2^192 + 1 99 beta = GF(p)(long_pi_string[:76]) + 379 100 ec = EllipticCurve(GF(p), [1, beta]) 101 points = [] 102 for i in range(1, 13): 103 x = GF(p)(int(long_pi_string[i * 76 : (i+1) * 76])) 104 while not is_square(x^3 + x + beta): 105 x += 1 106 P = ec((x, sqrt(x^3 + x + beta))) 107 if i <= 2: 108 points.append(P.xy()) 109 continue 110 for j in range(248 if i%2==1 else 4): 111 points.append(P.xy()) 112 P *= 2 113 print "".join("{0x%x_Z,0x%x_Z},\n" % p for p in points) 114 */ 115 const EllipticCurveConstants<PrimeFieldElement>& GetEcConstants(); 116 117 } // namespace starkware 118 119 #endif // STARKWARE_CRYPTO_ELLIPTIC_CURVE_CONSTANTS_H_