20purify_fe to_core(
const FieldElement& value) {
21 return purify_fe{detail::FieldElementAccess::raw(value)};
24FieldElement from_core(
const purify_fe& value) {
25 return detail::FieldElementAccess::from_raw(value.
value);
33 return JacobianPoint{from_core(point.
x), from_core(point.
y), from_core(point.
z), point.
infinity != 0};
41 return AffinePoint{from_core(point.
x), from_core(point.
y), point.
infinity != 0};
44UInt256 uint256_from_core(
void (*fill)(uint64_t*)) {
46 fill(out.limbs.data());
50UInt320 uint320_from_core(
void (*fill)(uint64_t*)) {
52 fill(out.limbs.data());
56UInt512 uint512_from_core(
void (*fill)(uint64_t*)) {
58 fill(out.limbs.data());
62FieldElement field_from_core(
void (*fill)(
purify_fe*)) {
65 return from_core(out);
68purify_curve make_core_curve(
const FieldElement& a,
const FieldElement& b,
const UInt256& n) {
72 std::copy(n.limbs.begin(), n.limbs.end(), out.n);
81 return from_core(out);
85 : a_(std::move(a)), b_(std::move(b)), n_(std::move(n)) {}
92 return from_core(out);
99 return from_core(out);
115 return from_core(out);
123 return from_core(out);
132 return from_core(out);
141 return from_core(out);
149 return from_core(out);
158 "EllipticCurve::mul_secret_affine:purify_curve_mul_secret_affine");
160 return from_core(out);
164 return Bytes(input.begin(), input.end());
168 lhs.insert(lhs.end(), rhs.begin(), rhs.end());
172std::uint64_t
ceil_div(std::uint64_t lhs, std::uint64_t rhs) {
173 return (lhs + rhs - 1) / rhs;
183 constexpr std::size_t hash_len = 32;
184 Bytes zero_salt(hash_len, 0);
188 for (std::size_t i = 0; i <
ceil_div(length, hash_len); ++i) {
190 input.insert(input.end(), info.begin(), info.end());
191 input.push_back(
static_cast<unsigned char>(i + 1));
193 okm.insert(okm.end(), t.begin(), t.end());
274 return from_core(out);
280 assert(point_result.
has_value() &&
"generator1() hash_to_curve should not exhaust");
282 assert(
curve1().mul(point,
order_n1()).infinity &&
"generator1() subgroup order check failed");
291 assert(point_result.
has_value() &&
"generator2() hash_to_curve should not exhaust");
293 assert(
curve2().mul(point,
order_n2()).infinity &&
"generator2() subgroup order check failed");
327 return std::make_pair(first, second);
336 return std::make_pair(first, second);
350 return from_core(out);
Minimal elliptic-curve arithmetic over the Purify base field.
JacobianPoint mul(const JacobianPoint &point, const UInt256 &scalar) const
Multiplies a point by a scalar using double-and-add.
AffinePoint affine(const JacobianPoint &point) const
Converts a Jacobian point to affine coordinates.
JacobianPoint add_mixed(const JacobianPoint &lhs, const AffinePoint &rhs) const
Adds an affine point to a Jacobian point.
JacobianPoint negate(const JacobianPoint &point) const
Negates a point without changing its projective scale.
bool is_x_coord(const FieldElement &x) const
Returns true if the supplied x-coordinate lifts to a curve point.
std::optional< JacobianPoint > lift_x(const FieldElement &x) const
Lifts an x-coordinate to a Jacobian point when a square root exists.
Result< AffinePoint > mul_secret_affine(const JacobianPoint &point, const UInt256 &scalar) const
Multiplies a public point by a secret scalar using exception-free complete formulas.
EllipticCurve(FieldElement a, FieldElement b, UInt256 n)
Constructs a curve from its Weierstrass coefficients and subgroup order.
JacobianPoint add(const JacobianPoint &lhs, const JacobianPoint &rhs) const
Adds two Jacobian points.
JacobianPoint double_point(const JacobianPoint &point) const
Doubles a Jacobian point.
Purify result carrier that either holds a value or an error.
bool has_value() const noexcept
Field element modulo the backend scalar field used by this implementation.
void purify_curve_half_n1(uint64_t out[4])
int purify_curve_is_x_coord(const purify_curve *curve, const purify_fe *x)
void purify_curve_jacobian_infinity(purify_jacobian_point *out)
void purify_curve_pack_public(uint64_t out[8], const uint64_t x1[4], const uint64_t x2[4])
int purify_curve_is_valid_public_key(const uint64_t value[8])
void purify_curve_order_n2(uint64_t out[4])
void purify_curve_packed_public_key_space_size(uint64_t out[8])
void purify_curve_order_n1(uint64_t out[4])
void purify_curve_packed_secret_key_space_size(uint64_t out[8])
int purify_curve_unpack_public(uint64_t first[4], uint64_t second[4], const uint64_t value[8])
void purify_curve_double(purify_jacobian_point *out, const purify_curve *curve, const purify_jacobian_point *point)
int purify_curve_key_to_bits(int *out_bits, size_t out_len, const uint64_t value[4], const uint64_t max_value[4])
void purify_curve_field_a(purify_fe *out)
void purify_curve_two_p(uint64_t out[5])
void purify_curve_negate(purify_jacobian_point *out, const purify_jacobian_point *point)
void purify_curve_half_n2(uint64_t out[4])
int purify_curve_lift_x(purify_jacobian_point *out, const purify_curve *curve, const purify_fe *x)
int purify_curve_is_valid_secret_key(const uint64_t value[8])
void purify_curve_combine(purify_fe *out, const purify_fe *x1, const purify_fe *x2)
void purify_curve_field_di(purify_fe *out)
void purify_curve_field_d(purify_fe *out)
int purify_curve_hash_to_curve(purify_jacobian_point *out, const purify_curve *curve, const unsigned char *data, size_t data_len)
void purify_curve_field_b(purify_fe *out)
int purify_curve_mul_secret_affine(purify_affine_point *out, const purify_curve *curve, const purify_jacobian_point *point, const uint64_t scalar[4])
void purify_curve_mul(purify_jacobian_point *out, const purify_curve *curve, const purify_jacobian_point *point, const uint64_t scalar[4])
void purify_curve_add(purify_jacobian_point *out, const purify_curve *curve, const purify_jacobian_point *lhs, const purify_jacobian_point *rhs)
void purify_curve_add_mixed(purify_jacobian_point *out, const purify_curve *curve, const purify_jacobian_point *lhs, const purify_affine_point *rhs)
void purify_curve_affine(purify_affine_point *out, const purify_curve *curve, const purify_jacobian_point *point)
void purify_curve_prime_p(uint64_t out[4])
int purify_curve_unpack_secret(uint64_t first[4], uint64_t second[4], const uint64_t value[8])
Elliptic-curve helpers, fixed parameters, and hash-to-curve utilities for Purify.
Bytes hmac_sha256(const Bytes &key, const Bytes &data)
Computes an HMAC-SHA256 digest using the secp bridge implementation.
Status validate_secret_key(const UInt512 &z)
Validates the packed secret-key encoding range.
FieldElement field_di()
Returns the inverse of the twist factor in the field.
const UInt256 & half_n1()
Returns floor(order_n1 / 2).
constexpr Unexpected< Error > unexpected_error(ErrorCode code, const char *context=nullptr)
Constructs an unexpected Error value from a machine-readable code.
const UInt256 & prime_p()
Returns the Purify base-field modulus.
Result< std::vector< int > > key_to_bits(UInt256 n, const UInt256 &max_value)
Encodes a scalar into the signed 3-bit window bit schedule used by the circuit.
Result< std::pair< UInt256, UInt256 > > unpack_public(const UInt512 &packed)
Splits a packed public key into its two x-coordinates.
const UInt256 & half_n2()
Returns floor(order_n2 / 2).
BigUInt< 8 > UInt512
512-bit unsigned integer used for private and packed public keys.
Bytes bytes_from_ascii(std::string_view input)
Encodes an ASCII string as a byte vector.
std::uint64_t ceil_div(std::uint64_t lhs, std::uint64_t rhs)
Computes ceiling division for unsigned 64-bit values.
Bytes hkdf(std::size_t length, const Bytes &ikm, const Bytes &salt={}, const Bytes &info={})
Expands input key material using HKDF-SHA256.
const UInt256 & order_n2()
Returns the subgroup order for the second curve.
Status validate_public_key(const UInt512 &packed)
Validates the packed public-key encoding range.
bool is_valid_public_key(const UInt512 &packed)
Returns true when a packed public key is encoded canonically.
const UInt320 & two_p()
Returns 2 * prime_p() as a widened integer for hash-to-curve sampling.
FieldElement field_a()
Returns the shared Weierstrass a coefficient used by Purify.
const EllipticCurve & curve1()
Returns the first Purify curve instance.
std::vector< unsigned char > Bytes
Dynamically sized byte string used for messages, serialized witnesses, and proofs.
const JacobianPoint & generator1()
Returns the fixed generator for the first curve.
UInt512 pack_public(const UInt256 &x1, const UInt256 &x2)
Packs two x-coordinates into the reference 512-bit public-key encoding.
const UInt512 & packed_secret_key_space_size()
Returns the size of the packed secret-key encoding space.
Result< std::pair< UInt256, UInt256 > > unpack_secret(const UInt512 &z)
Splits a packed private key into its two per-curve secret scalars.
FieldElement field_d()
Returns the twist factor used to derive the second curve.
Result< JacobianPoint > hash_to_curve(const Bytes &data, const EllipticCurve &curve)
Hashes arbitrary data onto the supplied curve by rejection sampling x-coordinates.
BigUInt< 5 > UInt320
320-bit unsigned integer used during hash-to-curve sampling.
FieldElement field_b()
Returns the shared Weierstrass b coefficient used by Purify.
bool is_valid_secret_key(const UInt512 &z)
Returns true when a packed secret is encoded canonically.
const EllipticCurve & curve2()
Returns the second Purify curve instance.
const JacobianPoint & generator2()
Returns the fixed generator for the second curve.
const UInt256 & order_n1()
Returns the subgroup order for the first curve.
FieldElement combine(const FieldElement &x1, const FieldElement &x2)
Applies the Purify curve-combination map to two x-coordinates.
const UInt512 & packed_public_key_space_size()
Returns the size of the packed public-key encoding space.
BigUInt< 4 > UInt256
256-bit unsigned integer used for field elements and curve orders.
Bytes operator+(Bytes lhs, const Bytes &rhs)
Concatenates two byte vectors.
void purify_hmac_sha256(unsigned char output32[32], const unsigned char *key, size_t key_len, const unsigned char *data, size_t data_len)
Computes HMAC-SHA256 over a byte string.
Affine point representation used for serialization and lookup tables.
std::size_t bit_length() const
Returns the index of the highest set bit plus one.
std::array< std::uint64_t, Words > limbs
Jacobian point representation used for curve arithmetic.
static JacobianPoint infinity_point()
Returns the point at infinity in Jacobian coordinates.