ec
Functions
Whether every limb of a is zero (an OR-accumulate over all limbs, no early exit).
C | the curve traits. |
a | the value to test. |
true iff a == 0.
O(1) — kLimbs limb reads on a fixed-width value.
none.
Multi-limb unsigned compare, most-significant limb first.
C | the curve traits. |
a | left operand. |
b | right operand. |
true iff a >= b.
O(1) — at most kLimbs limb compares.
none.
r = a - b (mod 2^kBits), returns the borrow.
C | the curve traits. |
r | receives the difference. |
a | minuend. |
b | subtrahend. |
the final borrow: 1 iff a < b, else 0.
O(1) — one pass over kLimbs limbs.
none.
CheatahP256.VerifyKnownVectorr = a + b (mod 2^kBits), returns the carry.
C | the curve traits. |
r | receives the sum. |
a | first addend. |
b | second addend. |
the final carry out of the top limb (0 or 1).
O(1) — one pass over kLimbs limbs.
none.
CheatahP256.VerifyKnownVectorCIOS Montgomery multiplication: r = a*b*R^-1 mod m.
C | the curve traits. |
r | receives the product. |
a | first factor (Montgomery form). |
b | second factor (Montgomery form). |
M | the Montgomery context. |
O(1) — kLimbs^2 limb multiplies on a fixed-width value.
none.
CheatahP256.VerifyKnownVectorModular addition: r = a + b mod m (add, then one conditional subtract of m).
C | the curve traits. |
r | receives the sum. |
a | first addend. |
b | second addend. |
M | the Montgomery context (only its modulus is used). |
O(1).
none.
CheatahP256.VerifyKnownVectorModular subtraction: r = a - b mod m (subtract, then one conditional add of m on borrow).
C | the curve traits. |
r | receives the difference. |
a | minuend. |
b | subtrahend. |
M | the Montgomery context (only its modulus is used). |
O(1).
none.
CheatahP256.VerifyKnownVectorConvert a into Montgomery form: r = a*R mod m (one mont_mul by R^2).
C | the curve traits. |
r | receives the Montgomery form. |
a | the plain value. |
M | the Montgomery context. |
O(1) — one mont_mul.
none.
CheatahP256.VerifyKnownVectorConvert a out of Montgomery form: r = a*R^-1 mod m (one mont_mul by 1).
C | the curve traits. |
r | receives the plain value. |
a | the Montgomery-form value. |
M | the Montgomery context. |
O(1) — one mont_mul.
none.
CheatahP256.VerifyKnownVectorr = a^-1 mod m, via Fermat: a^(m-2).
(m is prime for both p and n.)
C | the curve traits. |
r | receives the inverse (Montgomery form). |
a | the value to invert (Montgomery form, nonzero). |
M | the Montgomery context. |
O(1) — a fixed kBits-step square-and-multiply ladder.
none.
CheatahP256.VerifyKnownVectora^-1 mod 2^64 (a odd), by Newton's iteration.
a | the odd value to invert. |
the inverse mod 2^64.
O(1) — five fixed Newton steps.
none.
CheatahP256.VerifyKnownVectorBuild the Montgomery context for modulus m — every constant (n0, R^2 mod m, R mod m) derived at startup, no hand-transcribed Montgomery magic.
C | the curve traits. |
m | the (odd, prime) modulus. |
the derived context.
O(1) — 2*kBits fixed doubling steps to derive R^2 mod m.
none.
CheatahP256.VerifyKnownVectorThe curve's field context: the Montgomery context for the prime P, built once per instantiation (function-local static).
C | the curve traits. |
the context mod C::P.
O(1) after the one-time static make_mont on first use.
none — static storage.
CheatahP256.VerifyKnownVectorThe curve's scalar context: the Montgomery context for the group order N, built once per instantiation (function-local static).
C | the curve traits. |
the context mod C::N.
O(1) after the one-time static make_mont on first use.
none — static storage.
CheatahP256.VerifyKnownVectorLoad kBytes big-endian bytes into a little-endian limb array.
C | the curve traits. |
b | pointer to kBytes bytes, most significant first. |
the value.
O(1) — kBytes byte reads.
none.
CheatahP256.VerifyKnownVectorStore a limb array as kBytes big-endian bytes (the inverse of be_to_fe).
C | the curve traits. |
out | receives kBytes bytes, most significant first. |
a | the value to serialize. |
O(1) — kBytes byte writes.
none.
CheatahP256.SignKnownVectorThe point at infinity (the group identity): Z = 0 with the explicit flag set.
C | the curve traits. |
the identity point.
O(1).
none.
Jacobian point doubling, r = 2q, using the a = -3 formulas (true of every NIST prime curve).
Branchy (early-returns on infinity): for PUBLIC data only — the secret path uses jac_double_ct.
C | the curve traits. |
r | receives the doubled point. |
q | the point to double. |
O(1) — a fixed count of field operations.
none.
CheatahP256.VerifyKnownVectorJacobian point addition, r = a + b, with branchy special cases (either operand infinity, a == b -> double, a == -b -> infinity).
For PUBLIC data only — the secret path uses jac_add_ct.
C | the curve traits. |
r | receives the sum. |
a | first point. |
b | second point. |
O(1) — a fixed count of field operations.
none.
void jac_double_mul(Jac< C > &r, const fe< C > &u1, const Jac< C > &A, const fe< C > &u2, const Jac< C > &B)
source#
Strauss-Shamir: u1*A + u2*B with ONE doubling chain (kBits doublings total) instead of two separate scalar multiplications.
A 2-bit window over both scalars uses a 16-entry combined table [i*A + j*B] so it also halves the adds.
C | the curve traits. |
r | receives u1*A + u2*B. |
u1 | first (public) scalar. |
A | first point. |
u2 | second (public) scalar. |
B | second point. |
O(1) — kBits doublings plus at most kBits/2 adds.
none — the 16-entry window table lives on the stack.
CheatahP256.VerifyKnownVectorThe affine x-coordinate (normal form) of a Jacobian point: x = X / Z^2.
C | the curve traits. |
q | the point (not infinity: Z must be invertible). |
x out of Montgomery form.
O(1) — dominated by one mont_inv (a fixed Fermat ladder).
none.
CheatahP256.VerifyKnownVectorLift an affine point into Jacobian Montgomery form (Z = 1).
C | the curve traits. |
x | the affine x-coordinate (plain form). |
y | the affine y-coordinate (plain form). |
the Jacobian point.
O(1) — two to_mont conversions.
none.
CheatahP256.VerifyKnownVectorThe curve base point G, lifted to Jacobian form once (function-local static).
C | the curve traits. |
G.
O(1) after the one-time static lift on first use.
none — static storage.
CheatahP256.VerifyKnownVectorFixed-base comb for k*G.
G is constant, so we precompute (once) the 2^kLimbs-entry table T[s] = sum over set bits i of s of (2^(64*i) * G). Then k*G is just 64 doublings + 64 adds (vs kBits doublings for a generic window) — the big win for the per-message signing path. Selector at step j is bit j of each 64-bit limb.
C | the curve traits. |
the comb table.
O(1) after the one-time static build (kLimbs*64 doublings plus the subset sums).
none — the table is a function-local static std::array.
CheatahP256.SignKnownVectorBranch-free boolean-to-mask: false -> 0, true -> all-ones.
c | the condition. |
the 64-bit mask.
O(1).
none.
Constant-time conditional move over a field element: r = m ?
a : r, per limb, no branch.
C | the curve traits. |
r | the destination (kept when |
a | the source (copied when |
m | the ct_mask (0 or all-ones). |
O(1).
none.
Constant-time conditional move over a Jacobian point (all three coordinates via fe_cmov; the inf flag is recomputed from Z, which encodes infinity throughout the CT path).
C | the curve traits. |
r | the destination point. |
a | the source point. |
m | the ct_mask (0 or all-ones). |
O(1).
none.
Point doubling WITHOUT the is-infinity early return: the formula's Z3 = 2*Y*Z is already 0 when the input is infinity (Z==0), so it self-encodes infinity, and a prime-order curve has no finite 2-torsion point that could double TO infinity — so no branch is needed.
C | the curve traits. |
r | receives 2q. |
q | the point to double. |
O(1) — the same fixed field-operation count for every input.
none.
Point addition, branch-free.
It always computes the general add formula, then constant-time- selects the correct result over the special cases via masks: a==inf -> b, b==inf -> a, a==b -> double(a), a==-b -> infinity. Precedence is enforced by cmov ORDER (a==inf last / highest).
C | the curve traits. |
r | receives a + b. |
a | first point. |
b | second point. |
O(1) — the same fixed field-operation count for every input (the double is always computed).
none.
Constant-time table lookup: scan every entry, copying the one whose index == sel via a mask, so the memory-access pattern (and timing) is independent of the secret selector.
C | the curve traits. |
N | the table size. |
out | receives tbl[sel]. |
tbl | the table. |
sel | the (secret) index. |
O(N) — every entry is scanned by design.
none.
CheatahP256.SignKnownVectork*G for a SECRET scalar k, in constant time: 64 doublings + 64 unconditional adds over the fixed-base comb table.
The old form skipped the add when the window was zero and indexed the table by the secret selector — both leaked bits of k. Here every step does the same work (branch-free double, masked table select, unconditional branch-free add — add of the T[0]=infinity entry when the window is zero is a no-op via the CT add's masks).
C | the curve traits. |
r | receives k*G. |
k | the secret scalar. |
O(1) — exactly 64 CT doublings, 64 CT table scans, and 64 CT adds.
none.
CheatahP256.SignKnownVectorDifferential self-check for the constant-time point ops.
A TEMPLATE, instantiated ONLY by the p256/p384 test seam (so there is no such code in a production build), it confirms jac_add_ct / jac_double_ct agree with the branchy reference jac_add / jac_double on the general case AND every special case — a==b, a==-b, and infinity operands — which the signing path exercises rarely or never, so this both proves correctness and drives those branches for coverage.
C | the curve traits. |
true iff every CT result matches the branchy reference.
O(1) — a fixed handful of point operations.
none.
Reduce a scalar already known to be < 2n into [0, n): a single conditional subtraction of the group order n.
Used for the FIPS 186-4 hash truncation and for folding a curve x-coordinate (which lives in [0, p) < 2n) into a scalar.
C | the curve traits. |
v | the value, < 2n. |
v mod n.
O(1).
none.
CheatahP256.ReduceModNBoundaryReduce a big-endian hash to a scalar in [0, n).
A hash of at least kBytes keeps its leftmost kBytes (the FIPS 186-4 leftmost-bits truncation); a SHORTER hash is the whole value (X9.62 bits2int — right-aligned), e.g. a SHA-256 signature under a P-384 key.
C | the curve traits. |
h | the digest bytes. |
the scalar in [0, n).
O(1) — at most kBytes are copied regardless of the hash length.
none — a stack buffer.
Parse SEQUENCE{INTEGER r, INTEGER s} -> kBytes big-endian r and s.
Short-form lengths only: both curves' SEQUENCE stays under 128 bytes (P-384: <= ~104).
C | the curve traits. |
der | the DER-encoded signature. |
r | receives kBytes big-endian r. |
s | receives kBytes big-endian s. |
false on any malformed encoding.
O(1) — short-form DER caps the accepted input at 129 bytes (a longer der fails the exact-length check without being scanned).
none.
Is (x, y) on the curve y^2 = x^3 - 3x + b (mod p)?
Rejects an off-curve / invalid-curve public key — SP 800-56A / FIPS 186 point validation, which the plain coordinate-range check (x,y < p) does not catch.
C | the curve traits. |
x | the affine x-coordinate (plain form, < p). |
y | the affine y-coordinate (plain form, < p). |
true iff the point satisfies the curve equation.
O(1) — a fixed handful of field operations.
none.
bool verify_raw(const std::string &pubkey_xy, const std::string &msg_hash, const std::string &sig_raw)
source#
ECDSA verification over raw byte forms: pubkey = 2*kBytes X||Y, sig = 2*kBytes r||s.
C | the curve traits. |
pubkey_xy | the public key point, 2*kBytes X||Y big-endian. |
msg_hash | the message digest (truncated/reduced by hash_to_scalar). |
sig_raw | the signature, 2*kBytes r||s big-endian. |
true iff the signature verifies (range checks, on-curve check, and x == r all pass).
O(1) — two scalar multiplications, computed as one Strauss-Shamir double chain.
none.
bool verify_der(const std::string &pubkey_xy, const std::string &msg_hash, const std::string &sig_der)
source#
ECDSA verification of the DER form (SEQUENCE{INTEGER r, INTEGER s} — TLS/X.509).
C | the curve traits. |
pubkey_xy | the public key point, 2*kBytes X||Y big-endian. |
msg_hash | the message digest. |
sig_der | the DER-encoded signature. |
true iff the DER parses and the signature verifies.
O(1) — der_to_rs plus one verify_raw.
a temporary raw r||s signature string.
Encode a raw r||s signature (2*kBytes big-endian bytes) as the DER SEQUENCE{INTEGER r, INTEGER s} that TLS CertificateVerify and X.509 carry — the exact inverse of der_to_rs.
Integers are minimal-form: leading zero bytes are stripped and a 0x00 sign byte is prepended when the top bit is set, so the output round-trips through any strict DER parser. The outer length always fits short form (max 2*(kBytes+3) = 102 bytes at P-384).
C | the curve traits. |
sig_raw | the 2*kBytes r||s signature (e.g. sign_raw's output). |
the DER bytes, or "" if sig_raw has the wrong length or a zero integer (r = 0 / s = 0 is never a valid ECDSA signature).
O(kBytes).
the returned string plus the two integer temporaries.
