Skip to main content

secp256r1 (P-256)

zisklib functions for secp256r1 (NIST P-256) base/scalar field arithmetic, curve membership and scalar multiplication, and ECDSA signature verification.

Overview

secp256r1 (NIST P-256) is the short-Weierstrass curve y² = x³ − 3x + b defined over the prime field Fp with p = 2²⁵⁶ − 2²²⁴ + 2¹⁹² + 2⁹⁶ − 1. The group has prime order n (cofactor 1) and is the curve used for ECDSA in TLS certificates, WebAuthn/passkeys, and the EVM RIP-7212 precompile at address 0x100.

The page is organized bottom-up:

SectionProvidesDepends on
Base field (Fp)Arithmetic for every coordinate computation.
Scalar field (Fn)Arithmetic for signature components and exponents.
CurveOn-curve check, scalar mul, and double-scalar mul with G.Fp, Fn
ECDSASignature verification.Fn, Curve

Base field (Fp)

The prime field Fp where curve coordinates live, with p = 2²⁵⁶ − 2²²⁴ + 2¹⁹² + 2⁹⁶ − 1. Elements are 4 little-endian u64 limbs (256 bits). The Curve section ultimately reduces to these Fp primitives for evaluating y² = x³ − 3x + b and for the coordinate arithmetic inside scalar multiplication.

Addition in the secp256r1 base field Fp.

pub fn add_fp_secp256r1(x: &[u64; 4], y: &[u64; 4]) -> [u64; 4]

Parameters

NameTypeDescription
x&[u64; 4]First Fp operand as 4 LE limbs.
y&[u64; 4]Second Fp operand as 4 LE limbs.

Returns

TypeDescription
[u64; 4]x + y mod p in the secp256r1 base field.

Example

let sum = zisklib::add_fp_secp256r1(&x_limbs, &y_limbs);

Scalar field (Fn)

The prime field Fn of integers modulo the curve order n, where exponents and signature components live. Elements are 4 little-endian u64 limbs (256 bits). Scalar multiplications on the curve consume Fn elements, and ECDSA verification relies on Fn arithmetic to reconstruct u₁ = z·s⁻¹ and u₂ = r·s⁻¹ before the curve multi-scalar step.

Reduces a 256-bit integer modulo the secp256r1 curve order n.

pub fn reduce_fn_secp256r1(x: &[u64; 4]) -> [u64; 4]

Parameters

NameTypeDescription
x&[u64; 4]256-bit integer as 4 LE limbs.

Returns

TypeDescription
[u64; 4]x mod n in the secp256r1 scalar field.

Example

let reduced = zisklib::reduce_fn_secp256r1(&scalar);

Curve

The group of Fp-rational points on y² = x³ − 3x + b, including the point at infinity. Affine points are [u64; 8] (x ++ y). Point arithmetic consumes Fp elements for coordinates and Fn elements for scalars; the double_scalar_mul_with_g_secp256r1 primitive in this section is the building block reused by ECDSA verification.

Returns true if the affine point p satisfies the secp256r1 curve equation y² = x³ + a·x + b.

warning

Assumes p is not the point at infinity.

pub fn is_on_curve_secp256r1(p: &[u64; 8]) -> bool

Parameters

NameTypeDescription
p&[u64; 8]Affine point encoded as x ++ y, each 4 LE limbs. Non-infinity.

Returns

TypeDescription
booltrue if p satisfies the secp256r1 curve equation, false otherwise.

Example

assert!(zisklib::is_on_curve_secp256r1(&point));

ECDSA

ECDSA signature verification on secp256r1 (P-256), the algorithm used by TLS, WebAuthn and the EVM precompile at 0x100. Verification computes u₁·G + u₂·Q via the curve's multi-scalar primitive and compares the resulting x-coordinate against r mod n. Inputs are limbs: the public key is an affine point, while r, s and z are Fn-sized 4-limb values.

Verifies a secp256r1 (P-256) ECDSA signature (r, s) over message hash z using public key pk. Validates that r, s ∈ [1, n-1], that pk is not the identity, that both coordinates of pk lie in [0, p-1], and that pk is on the curve.

pub fn ecdsa_verify_secp256r1(
pk: &[u64; 8],
z: &[u64; 4],
r: &[u64; 4],
s: &[u64; 4],
) -> bool

Parameters

NameTypeDescription
pk&[u64; 8]Public key as affine x ++ y, 4 LE limbs each.
z&[u64; 4]Message hash as 4 LE limbs.
r&[u64; 4]Signature component r as 4 LE limbs.
s&[u64; 4]Signature component s as 4 LE limbs.

Returns

TypeDescription
booltrue if the signature is valid, false otherwise.

Example

let ok = zisklib::ecdsa_verify_secp256r1(&pk, &z, &r, &s);