UltrafastSecp256k1 3.50.0
Ultra high-performance secp256k1 elliptic curve cryptography library
Loading...
Searching...
No Matches
point.hpp
Go to the documentation of this file.
1#ifndef SECP256K1_CT_POINT_HPP
2#define SECP256K1_CT_POINT_HPP
3
4// ============================================================================
5// Constant-Time Point Arithmetic
6// ============================================================================
7// Side-channel resistant elliptic curve point operations for secp256k1.
8// Uses secp256k1::fast::Point and FieldElement data types.
9//
10// Key differences from fast::Point:
11// 1. COMPLETE addition formula -- handles all cases (P+Q, P+P, P+O, O+Q,
12// P+(-P)) in a single codepath with NO branches on point values
13// 2. CT scalar multiplication -- fixed execution pattern:
14// - Always same number of doublings + additions
15// - CT table lookup (scans all entries)
16// - No early exit or conditional skip
17// 3. CT table lookup for precomputed multiples
18//
19// The complete Jacobian addition for a=0 (secp256k1: y^2=x^3+7) uses
20// the Renes-Costello-Bathalter (2016) formula adapted for a=0.
21// Cost: 12M + 2S (vs 11M + 5S for fast incomplete)
22// Advantage: No branch on P==Q, P==-Q, P==O
23// ============================================================================
24
25#include <cstdint>
26#include <cstddef>
27#include "secp256k1/field.hpp"
29#include "secp256k1/scalar.hpp"
30#include "secp256k1/point.hpp"
31#include "secp256k1/ct/ops.hpp"
34
35namespace secp256k1::ct {
36
40
41// FE type for CT internals: FieldElement52 on 5x52 platforms, FieldElement otherwise.
42#if defined(SECP256K1_FAST_52BIT)
44#else
46#endif
47
48// --- CT Jacobian Point (internal representation) -----------------------------
49// Uses uint64_t flag instead of bool for branchless operations
54 std::uint64_t infinity; // 0 = normal, 0xFFFF...F = infinity
55
56 static CTJacobianPoint from_point(const Point& p) noexcept;
57 Point to_point() const noexcept;
58 static CTJacobianPoint make_infinity() noexcept;
59};
60
61// --- CT Affine Point (for precomputed tables) --------------------------------
62// Compact representation with Z=1 implied. Used in precomputed tables
63// where mixed Jacobian+Affine addition saves ~4 field multiplications.
67 std::uint64_t infinity; // 0 = normal, 0xFFFF...F = infinity
68
69 static CTAffinePoint make_infinity() noexcept {
71#if defined(SECP256K1_FAST_52BIT)
72 r.x = FE52::zero();
73 r.y = FE52::zero();
74#else
75 r.x = FieldElement();
76 r.y = FieldElement();
77#endif
78 r.infinity = ~static_cast<std::uint64_t>(0);
79 return r;
80 }
81
82 static CTAffinePoint from_point(const Point& p) noexcept {
84 if (p.is_infinity()) {
85 r = make_infinity();
86 } else {
87#if defined(SECP256K1_FAST_52BIT)
88 r.x = FE52::from_fe(p.x());
89 r.y = FE52::from_fe(p.y());
90#else
91 r.x = p.x();
92 r.y = p.y();
93#endif
94 r.infinity = 0;
95 }
96 return r;
97 }
98};
99
100// --- Complete Addition -------------------------------------------------------
101// Brier-Joye unified addition/doubling for general Jacobian+Jacobian.
102// Handles ALL cases in a single branchless codepath:
103// P + Q, P + P (doubling), P + O, O + Q, P + (-P) = O
104// No secret-dependent branches. Cost: 11M + 6S.
105
107 const CTJacobianPoint& q) noexcept;
108
109// --- Mixed Jacobian+Affine Complete Addition ---------------------------------
110// Brier-Joye unified addition/doubling for Jacobian+Affine (Z2=1).
111// Cost: 7M + 5S (fixed, no branches)
113 const CTAffinePoint& q) noexcept;
114
115// --- CT Point Doubling -------------------------------------------------------
116// Libsecp-style 3M+4S+1half doubling (low magnitudes, handles identity via cmov)
118
119// --- Brier-Joye Unified Mixed Addition (Jacobian + Affine, a=0) -------------
120// Cost: 7M + 5S (vs 9M+8S for complete formula)
121// Unified: handles both addition and doubling in one codepath.
122// Precondition: b MUST NOT be infinity. a may be infinity.
123// When b might be infinity, use cmov after call to skip the result.
125 const CTAffinePoint& b) noexcept;
126
127// In-place variant: writes result directly into *out (avoids 128-byte copy).
128// out may alias &a (reads a first, then writes result).
130 const CTJacobianPoint& a,
131 const CTAffinePoint& b) noexcept;
132
133// --- CT Point Negation -------------------------------------------------------
135
136// --- CT Conditional Operations -----------------------------------------------
138 std::uint64_t mask) noexcept;
139
141 std::uint64_t mask) noexcept;
142
143// --- CT Table Lookup ---------------------------------------------------------
144// Always reads ALL table entries. Returns table[index].
145// table_size must equal the actual table array length.
147 std::size_t table_size,
148 std::size_t index) noexcept;
149
150// CT affine table lookup -- scans all entries, returns table[index].
152 std::size_t table_size,
153 std::size_t index) noexcept;
154
155// Signed-digit affine table lookup (Hamburg encoding).
156// Table stores odd multiples [1P, 3P, ..., (2^group_size-1)P].
157// n is a group_size-bit value interpreted as signed digit.
158// Result is NEVER infinity.
160 std::size_t table_size,
161 std::uint64_t n,
162 unsigned group_size) noexcept;
163
164// In-place variant: writes result directly into *out (avoids 88-byte copy).
166 const CTAffinePoint* table,
167 std::size_t table_size,
168 std::uint64_t n,
169 unsigned group_size) noexcept;
170
171// --- CT Batch Doubling -------------------------------------------------------
172// In-place batch N doublings -- modifies r directly, no return copy.
173void point_dbl_n_inplace(CTJacobianPoint* r, unsigned n) noexcept;
174
175// Return-by-value wrapper (kept for backward compatibility).
176CTJacobianPoint point_dbl_n(const CTJacobianPoint& p, unsigned n) noexcept;
177
178// CT conditional operations on affine points
180 std::uint64_t mask) noexcept;
181
182// --- CT Scalar Multiplication ------------------------------------------------
183// Hamburg signed-digit comb + GLV endomorphism (GROUP_SIZE=5).
184//
185// Method: Transform scalar via s = (k+K)/2, GLV split -> v1, v2 (129 bits each).
186// Process 26 groups of 5 bits, each yielding a guaranteed non-zero odd digit.
187// Table: 16 odd multiples per curve ([1P, 3P, ..., 31P], [1lambdaP, ..., 31lambdaP]).
188// Cost: 125 dbl + 52 unified_add + 52 signed_lookups(16).
189
190Point scalar_mul(const Point& p, const Scalar& k) noexcept;
191
192// CT generator multiplication: k * G
193// Hamburg signed-digit encoding: v = (k + 2^256 - 1)/2 mod n.
194// Every 4-bit window is guaranteed odd -> 8-entry table, no cmov skip.
195// Cost: 64 unified_add + 64 signed_lookups(8). No doublings.
196// Approximately 3x faster than generic scalar_mul(G, k).
197Point generator_mul(const Scalar& k) noexcept;
198
199// Initialize the precomputed generator table.
200// Called automatically on first generator_mul() call.
201// Can be called explicitly at startup to avoid first-call latency.
202void init_generator_table() noexcept;
203
204// --- CT GLV Endomorphism -----------------------------------------------------
205// Apply secp256k1 endomorphism: phi(P) = (beta*X, Y, Z) where beta^3 == 1 (mod p).
206// Constant-time (just one field multiplication, no branches).
208
209// CT affine endomorphism
211
212// CT affine negation
214
215// --- CT GLV Decomposition ----------------------------------------------------
216// Split scalar k = k1 + k2*lambda (mod n) where |k1|, |k2| ~= 128 bits.
217// Fully constant-time: no branches on scalar values.
219 Scalar k1; // |k1| ~= 128 bits (always positive after abs)
220 Scalar k2; // |k2| ~= 128 bits (always positive after abs)
221 std::uint64_t k1_neg; // all-ones if k1 was negated, 0 otherwise
222 std::uint64_t k2_neg; // all-ones if k2 was negated, 0 otherwise
223};
224
226
227// --- CT Verify (for ECDSA) --------------------------------------------------
228// Returns all-ones mask if point is on curve, else 0. CT.
229std::uint64_t point_is_on_curve(const Point& p) noexcept;
230
231// CT equality check
232std::uint64_t point_eq(const Point& a, const Point& b) noexcept;
233
234} // namespace secp256k1::ct
235
236#endif // SECP256K1_CT_POINT_HPP
static FieldElement zero()
std::uint64_t point_eq(const Point &a, const Point &b) noexcept
CTAffinePoint affine_neg(const CTAffinePoint &p) noexcept
CTJacobianPoint point_table_lookup(const CTJacobianPoint *table, std::size_t table_size, std::size_t index) noexcept
CTJacobianPoint point_add_mixed_complete(const CTJacobianPoint &p, const CTAffinePoint &q) noexcept
CTAffinePoint affine_table_lookup(const CTAffinePoint *table, std::size_t table_size, std::size_t index) noexcept
CTJacobianPoint point_neg(const CTJacobianPoint &p) noexcept
secp256k1::fast::FieldElement FieldElement
Definition field.hpp:33
Point scalar_mul(const Point &p, const Scalar &k) noexcept
CTJacobianPoint point_endomorphism(const CTJacobianPoint &p) noexcept
CTAffinePoint affine_endomorphism(const CTAffinePoint &p) noexcept
CTJacobianPoint point_select(const CTJacobianPoint &a, const CTJacobianPoint &b, std::uint64_t mask) noexcept
void point_add_mixed_unified_into(CTJacobianPoint *out, const CTJacobianPoint &a, const CTAffinePoint &b) noexcept
CTJacobianPoint point_dbl_n(const CTJacobianPoint &p, unsigned n) noexcept
CTAffinePoint affine_table_lookup_signed(const CTAffinePoint *table, std::size_t table_size, std::uint64_t n, unsigned group_size) noexcept
void init_generator_table() noexcept
void point_cmov(CTJacobianPoint *r, const CTJacobianPoint &a, std::uint64_t mask) noexcept
void point_dbl_n_inplace(CTJacobianPoint *r, unsigned n) noexcept
CTJacobianPoint point_add_complete(const CTJacobianPoint &p, const CTJacobianPoint &q) noexcept
void affine_table_lookup_signed_into(CTAffinePoint *out, const CTAffinePoint *table, std::size_t table_size, std::uint64_t n, unsigned group_size) noexcept
Point generator_mul(const Scalar &k) noexcept
CTJacobianPoint point_add_mixed_unified(const CTJacobianPoint &a, const CTAffinePoint &b) noexcept
CTGLVDecomposition ct_glv_decompose(const Scalar &k) noexcept
std::uint64_t point_is_on_curve(const Point &p) noexcept
CTJacobianPoint point_dbl(const CTJacobianPoint &p) noexcept
void affine_cmov(CTAffinePoint *r, const CTAffinePoint &a, std::uint64_t mask) noexcept
static CTAffinePoint make_infinity() noexcept
Definition point.hpp:69
static CTAffinePoint from_point(const Point &p) noexcept
Definition point.hpp:82
static CTJacobianPoint make_infinity() noexcept
static CTJacobianPoint from_point(const Point &p) noexcept
Point to_point() const noexcept