mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 19:50:36 +00:00
120 lines
4.3 KiB
C
120 lines
4.3 KiB
C
|
#ifndef STARKWARE_CRYPTO_ELLIPTIC_CURVE_CONSTANTS_H_
|
||
|
#define STARKWARE_CRYPTO_ELLIPTIC_CURVE_CONSTANTS_H_
|
||
|
|
||
|
#include <array>
|
||
|
#include <utility>
|
||
|
#include <vector>
|
||
|
|
||
|
#include "big_int.h"
|
||
|
#include "elliptic_curve.h"
|
||
|
#include "prime_field_element.h"
|
||
|
|
||
|
namespace starkware {
|
||
|
|
||
|
/*
|
||
|
Contains a set of constants that go along with an elliptic curve.
|
||
|
|
||
|
FieldElementT is the underlying field of the curve.
|
||
|
The equation of the elliptic curve is y^2 = x^3 + k_alpha * x + k_beta.
|
||
|
k_order is the size of the group.
|
||
|
k_points are points on the curve that were generated independently in a "nothing up my sleeve"
|
||
|
manner to ensure that no one knows their discrete log.
|
||
|
*/
|
||
|
template <typename FieldElementT>
|
||
|
struct EllipticCurveConstants {
|
||
|
public:
|
||
|
using ValueType = typename FieldElementT::ValueType;
|
||
|
|
||
|
const FieldElementT k_alpha;
|
||
|
const FieldElementT k_beta;
|
||
|
const ValueType k_order;
|
||
|
const std::vector<EcPoint<FieldElementT>> k_points;
|
||
|
|
||
|
constexpr EllipticCurveConstants(
|
||
|
const FieldElementT& k_alpha, const FieldElementT& k_beta, const ValueType& k_order,
|
||
|
std::vector<EcPoint<FieldElementT>> k_points) noexcept
|
||
|
: k_alpha(k_alpha), k_beta(k_beta), k_order(k_order), k_points(std::move(k_points)) {}
|
||
|
|
||
|
constexpr EllipticCurveConstants(
|
||
|
const ValueType& k_alpha, const ValueType& k_beta, const ValueType& k_order,
|
||
|
std::initializer_list<std::pair<ValueType, ValueType>> k_points) noexcept
|
||
|
: EllipticCurveConstants(
|
||
|
FieldElementT::FromBigInt(k_alpha), FieldElementT::FromBigInt(k_beta), k_order,
|
||
|
ECPointsVectorFromPairs(std::move(k_points))) {}
|
||
|
|
||
|
private:
|
||
|
static std::vector<EcPoint<FieldElementT>> ECPointsVectorFromPairs(
|
||
|
std::initializer_list<std::pair<ValueType, ValueType>> k_points) {
|
||
|
std::vector<EcPoint<FieldElementT>> res;
|
||
|
res.reserve(k_points.size());
|
||
|
|
||
|
for (const auto& p : k_points) {
|
||
|
res.emplace_back(FieldElementT::FromBigInt(p.first), FieldElementT::FromBigInt(p.second));
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
This elliptic curve over the prime field PrimeFieldElement was chosen in a "nothing up my sleeve"
|
||
|
manner to show that we don't know any special properties of this curve (other than being of prime
|
||
|
order).
|
||
|
|
||
|
alpha was chosen to be 1 because any elliptic curve has an isomorphic curve with a small alpha,
|
||
|
but we didn't want a zero alpha because then the discriminant is small.
|
||
|
|
||
|
beta was generated in the following way:
|
||
|
1) Take beta to be the integer whose digits are the first 76 decimal digits of pi (76 is the
|
||
|
number of digits required to represent a field element).
|
||
|
2) While [y^2 = x^3 + alpha * x + beta] is not a curve of prime order, increase beta by 1.
|
||
|
|
||
|
The points were generated by the following steps:
|
||
|
1) Take the decimal digits of pi and split them into chunks of 76 digits (the number of decimal
|
||
|
digits of the modulus).
|
||
|
|
||
|
2) Each chunk of 76 digits is the seed for generating a point, except for the first chunk
|
||
|
which was used for generating the curve.
|
||
|
|
||
|
3) For each such seed x:
|
||
|
|
||
|
3.1) while (x^3 + alpha * x + beta) is not a square in the prime field:
|
||
|
increase x by 1.
|
||
|
|
||
|
3.2) (x, square_root(x^3 + alpha * x + beta)) is a point on the elliptic curve (for square_root
|
||
|
the smaller root).
|
||
|
|
||
|
|
||
|
4) The first two points are taken as-is, as they will be used as the shift point and the
|
||
|
ECDSA generator point.
|
||
|
|
||
|
5) Each subsequent point P is expanded to 248 or 4 points alternatingly, by taking the set
|
||
|
{2^i P : 0 <= i < 248} or {2^i P : 0 <= i < 3}. 248 is chosen to be the largest multiple of 8
|
||
|
lower than 251.
|
||
|
|
||
|
This is a sage code that implements these steps:
|
||
|
|
||
|
R = RealField(400000)
|
||
|
long_pi_string = '3' + str(R(pi))[2:]
|
||
|
p = 2^251 + 17 * 2^192 + 1
|
||
|
beta = GF(p)(long_pi_string[:76]) + 379
|
||
|
ec = EllipticCurve(GF(p), [1, beta])
|
||
|
points = []
|
||
|
for i in range(1, 13):
|
||
|
x = GF(p)(int(long_pi_string[i * 76 : (i+1) * 76]))
|
||
|
while not is_square(x^3 + x + beta):
|
||
|
x += 1
|
||
|
P = ec((x, sqrt(x^3 + x + beta)))
|
||
|
if i <= 2:
|
||
|
points.append(P.xy())
|
||
|
continue
|
||
|
for j in range(248 if i%2==1 else 4):
|
||
|
points.append(P.xy())
|
||
|
P *= 2
|
||
|
print "".join("{0x%x_Z,0x%x_Z},\n" % p for p in points)
|
||
|
*/
|
||
|
const EllipticCurveConstants<PrimeFieldElement>& GetEcConstants();
|
||
|
|
||
|
} // namespace starkware
|
||
|
|
||
|
#endif // STARKWARE_CRYPTO_ELLIPTIC_CURVE_CONSTANTS_H_
|