A public key lets someone check a signature without learning the private key. ECDSA builds that check from elliptic-curve point arithmetic and a message hash. It signs a message; it does not encrypt it.

Signer
d, k
Sign
m, (r, s)
Verifier
Q = dG
Verify

Agree on the group

The signer and verifier share the curve parameters ⁠, including base point GG and its prime order nn. The signer holds a private scalar dd and publishes Q=dGQ=dG. The verifier must obtain the right public key for the identity or account being checked.

Let zz be the integer derived from the message hash. If the hash is longer than the bit length of nn, ECDSA takes its leftmost bits to that length. Coordinate arithmetic uses the field modulus pp; signature scalars use nn.

Make a signature

The signer chooses a secret scalar kk between 11 and n−1n-1, then computes:

R=kG,r=xR mod n,R=kG,\qquad r=x_R\bmod n, s=k−1(z+rd) mod n.s=k^{-1}(z+rd)\bmod n.

The signature is (r,s)(r,s). If either value is zero, signing retries with another kk. See FIPS 186-5, §6.4.

The example below uses the tiny curve y2=x3+2x+2(mod17)y^2=x^3+2x+2\pmod{17} with G=(5,1)G=(5,1) of order 1919. It exposes dd and kk for learning and takes z=11z=11 directly, without hashing a message. Change kk or change the digest presented to the verifier.

Sign

d = 7 · z = 11
R = 3G = (10, 6)
r = xR mod 19 = 10
s = k⁻¹(z + rd) mod 19 = 8

Verify

Q = (0, 6) · z′ = 11
u₁ = 18 · u₂ = 6
V = u₁G + u₂Q = (10, 6)
xV mod 19 = r
Signature (10, 8) · accepted

These small numbers offer no security. Some choices of kk produce an invalid signature; the diagram leaves that failure visible instead of silently replacing the nonce.

Check the signature

After validating the public key and checking 1≤r,s<n1\le r,s<n, the verifier computes:

u1=zs−1 mod n,u2=rs−1 mod n,u_1=zs^{-1}\bmod n,\qquad u_2=rs^{-1}\bmod n,

V=u1G+u2Q.V=u_1G+u_2Q.

Reject if V=OV=O. Otherwise accept when xV mod n=rx_V\bmod n=r. The verifier uses the message, public key and signature; it does not need dd or kk. Public-key validation checks the curve and subgroup as well as rejecting the point at infinity. See SEC 1, §§3.2.2 and 4.1.4.

Why it works

For an honestly generated signature, substitute Q=dGQ=dG and the signing equation:

V=zs−1G+rs−1(dG)=s−1(z+rd)G=kG=R.\begin{aligned} V&=zs^{-1}G+rs^{-1}(dG)\\ &=s^{-1}(z+rd)G\\ &=kG=R. \end{aligned}

The reconstructed point has the same horizontal coordinate, so the check succeeds. This proves correctness of the calculation; resistance to forgery also relies on the chosen group, hash and implementation. Tiny teaching groups can have accidental matches after a digest change.

Protect the nonce

If an attacker learns kk from a valid signature, rearranging the equation reveals the private key:

d=(sk−z)r−1 mod n.d=(sk-z)r^{-1}\bmod n.

Reusing the same kk for two different digest values is also dangerous. Subtracting the two signing equations can reveal kk, then dd.

The two signatures below use the same teaching key. Switch off nonce reuse: the two equations no longer yield one shared kk.

mod 19
z₁ = 11
(r₁, s₁) = (10, 8)
8k₁ ≡ 11 + 10d
z₂ = 12
(r₂, s₂) = (10, 2)
2k₂ ≡ 12 + 10d
k₁ = k₂
k = (z₁ − z₂)(s₁ − s₂)⁻¹ = 3
d = (s₁k − z₁)r⁻¹ = 7

A nonce can come from a suitable cryptographic random generator or a specified deterministic construction. RFC 6979 derives it from the private key and message hash; deterministic does not mean publicly predictable. A timestamp is not a substitute.

Three different inputs

ValuePurposeSecret?
Curve-generation seedHelps construct shared curve parametersNo
Private scalar ddDetermines a user's public keyYes
Signing nonce kkDetermines the point used for a signatureYes

P-256 and secp256k1 can both be used with ECDSA. Passkeys ⁠ commonly use the former; Ethereum EOA transactions ⁠ use the latter. Their groups and encodings are not interchangeable.

Recovering a public curve seed's origin is therefore a different task from recovering a signing key. Curve Origins ⁠ follows that investigation.