Introduction
The ecdsa signature java tutorial covers the Elliptic Curve Digital Signature Algorithm, which was proposed by Scott Vanstone in 1992 as the elliptic-curve variant of DSA and standardized as ANSI X9.62 in 1998, FIPS 186-2 in 2000, and FIPS 186-4 in 2013. ECDSA uses the elliptic-curve discrete logarithm problem as the hard problem, which means the keys and signatures are much smaller than DSA or RSA for equivalent security: a 256-bit ECDSA key provides the same security as a 3072-bit RSA key.
For a Java learner the ecdsa signature java example below matters because the JDK ships the KeyPairGenerator and Signature classes for ECDSA in the SunEC provider (added in Java 7). The standard API (KeyPairGenerator.getInstance("EC").initialize(new ECGenParameterSpec("secp256r1")).generateKeyPair() and Signature.getInstance("SHA256withECDSA")) is the production way to use ECDSA in Java.
ECDSA is the signature algorithm in Bitcoin and Ethereum, where the secp256k1 curve is used to sign transactions. The TLS 1.3 handshake uses ECDSA with the NIST curves P-256 and P-384 for the CertificateVerify message, which is the modern alternative to RSA-PSS for servers that use elliptic-curve certificates.
What is ECDSA Signature (Elliptic Curve Digital Signature)?
ecdsa signature java is an asymmetric cryptographic signature scheme. ECDSA uses an elliptic curve over a finite field, a base point G of order n, a per-key private key d in [1, n-1], and a public key Q = d times G. The signature on a message m is a pair (r, s), each a number modulo n. The signature size is twice the bit length of n, which is 64 bytes for the NIST P-256 curve.
The signature scheme belongs to the family of discrete-log-based signature schemes, alongside ElGamal (1985), Schnorr (1989), DSA (1991), and EdDSA (2011). ECDSA is the elliptic-curve variant of DSA; the underlying mathematics is the same, but the group is the points on an elliptic curve rather than the multiplicative group of integers modulo p.
The hard problem is the elliptic-curve discrete logarithm problem: given G and Q = d times G, find d. The best-known algorithm for the elliptic-curve discrete logarithm is Pollard's rho, which has square-root complexity in the group order n. A 256-bit curve therefore provides about 128 bits of security, which is equivalent to a 3072-bit RSA key.
The NIST curves P-256 (secp256r1), P-384 (secp384r1), and P-521 (secp521r1) are the curves recommended by FIPS 186-4 for US federal use. The Bitcoin and Ethereum blockchains use secp256k1, which is a different curve defined over the same prime field but with a different equation (y squared = x cubed + 7 rather than y squared = x cubed - 3x + b).
How ECDSA Works Step by Step
Step 1: Key generation. The signer generates a random private key d in [1, n-1] and computes the public key Q = d times G. The private key is a single 256-bit number; the public key is a point on the curve, which is encoded as the X and Y coordinates (64 bytes uncompressed, or 33 bytes compressed).
Step 2: Signing. The signer generates a fresh random per-signature nonce k in [1, n-1], computes the point (x1, y1) = k times G, takes r = x1 modulo n, computes s = k to the power minus 1 times (H(m) + d times r) modulo n, and the signature is (r, s). If r or s is zero, retry with a fresh k.
Step 3: Verification. The verifier checks r and s are in [1, n-1], computes w = s to the power minus 1 modulo n, u1 = H(m) times w modulo n, u2 = r times w modulo n, computes the point (x2, y2) = u1 times G plus u2 times Q, and the signature is valid if and only if r equals x2 modulo n.
Step 4: Critical security property. The nonce k must be fresh and unpredictable for every signature, just like in DSA. If k is reused for two signatures, the private key d can be recovered from the two signatures (the Sony PlayStation 3 hack of 2010 was caused by k reuse in ECDSA). If k is partially predictable, the lattice attack of Howgrave-Graham and Smart (2005) can recover d.
Step 5: Hash function. The hash H must be a cryptographic hash with output length at least the bit length of n. For P-256, the hash is SHA-256. For P-384, the hash is SHA-384. For P-521, the hash is SHA-512.
Step 6: Point operations. The key generation, signing, and verification all use elliptic-curve point multiplication, which is implemented in the SunEC provider. The point multiplication is the slow operation; the modular arithmetic is fast.
Java Program for ECDSA Elliptic Curve Digital Signature
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.SecureRandom;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECGenParameterSpec;
import java.util.Base64;
public class EcdsaDemo {
public static void main(String[] args) throws Exception {
// Generate an EC key pair on the NIST P-256 curve (secp256r1).
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
kpg.initialize(new ECGenParameterSpec("secp256r1"), new SecureRandom());
KeyPair keys = kpg.generateKeyPair();
ECPrivateKey priv = (ECPrivateKey) keys.getPrivate();
ECPublicKey pub = (ECPublicKey) keys.getPublic();
System.out.println("=== EC key pair on secp256r1 ===");
System.out.println("Curve : " + priv.getParams().getCurve());
System.out.println("Generator G bit len : " + priv.getParams().getGenerator().getAffineX().bitLength());
System.out.println("Order n bit length : " + priv.getParams().getOrder().bitLength());
System.out.println("Private key S bit len: " + priv.getS().bitLength());
System.out.println("Public key W x bit len: " + pub.getW().getAffineX().bitLength());
System.out.println("Public key W y bit len: " + pub.getW().getAffineY().bitLength());
// Sign with SHA256withECDSA.
byte[] message = "ECDSA gives 128-bit security with 256-bit keys.".getBytes("UTF-8");
Signature ecdsa = Signature.getInstance("SHA256withECDSA");
ecdsa.initSign(priv);
ecdsa.update(message);
byte[] signature = ecdsa.sign();
// Verify.
ecdsa.initVerify(pub);
ecdsa.update(message);
boolean ok = ecdsa.verify(signature);
// Tamper detection.
byte[] tampered = message.clone();
tampered[6] ^= 0x01;
ecdsa.initVerify(pub);
ecdsa.update(tampered);
boolean tamperDetected = !ecdsa.verify(signature);
// Two ECDSA signatures of the same message differ (probabilistic).
ecdsa.initSign(priv);
ecdsa.update(message);
byte[] sig2 = ecdsa.sign();
boolean sigsDiffer = !java.util.Arrays.equals(signature, sig2);
System.out.println();
System.out.println("=== Signature ===");
System.out.println("Message : " + new String(message, "UTF-8"));
System.out.println("Signature (DER) : " + Base64.getEncoder().encodeToString(signature).substring(0, 40) + "...");
System.out.println("Signature length : " + signature.length + " bytes (DER-encoded)");
System.out.println("Verify ok : " + ok);
System.out.println("Tamper detected : " + tamperDetected);
System.out.println("Two sigs differ : " + sigsDiffer);
// Sign with the deterministic variant (RFC 6979): use SHA256withECDSA in deterministic mode.
// The SunEC provider supports deterministic ECDSA via the "signerRandom" parameter being absent,
// which falls back to the deterministic RFC 6979 nonce derivation since JDK 18 (JEP-specific).
// For JDK < 18, the nonce is random; this demo uses random nonces.
System.out.println();
System.out.println("Note: ECDSA requires a unique nonce per signature. Reusing the nonce");
System.out.println(" reveals the private key. Use EdDSA (Ed25519) for deterministic signatures.");
}
}
Code Explanation Line by Line
The class EcdsaDemo uses the JDK KeyPairGenerator for EC to produce an EC key pair on the NIST P-256 curve (secp256r1). The ECGenParameterSpec wraps the standard curve name "secp256r1", which is the SEC name for the NIST P-256 curve. The KeyPairGenerator uses the SunEC provider, which has been the standard JDK provider for elliptic-curve cryptography since Java 7.
The ECPrivateKey and ECPublicKey interfaces expose the private key S (a single 256-bit number) and the public key W (an elliptic-curve point with X and Y coordinates). The print step shows the bit lengths, which confirm the P-256 parameter set: the order n is 256 bits, the private key S is 256 bits, and the public key X and Y are 256 bits each.
The JDK-standard signature uses the Signature class with the algorithm name "SHA256withECDSA". The signature is DER-encoded, which adds a few bytes of ASN.1 overhead to the raw 64-byte (r, s) pair. The verification succeeds for the original message and fails for the tampered message, which is the integrity guarantee of digital signatures.
The two-signature test signs the same message twice and confirms the two signatures differ. The difference comes from the random nonce k, which must be fresh for every signature. The note at the end explains that ECDSA's nonce requirement is a known footgun: if the nonce is reused, the private key is recovered. The deterministic variant (RFC 6979) derives the nonce from the private key and the message hash, which eliminates the random-number requirement and the risk of nonce reuse.
The SunEC provider in modern JDK versions (since JDK 18 with JEP-specific changes) supports deterministic ECDSA via the RFC 6979 nonce derivation when no SecureRandom is set. For earlier JDK versions, the nonce is random; the recommendation is to use EdDSA (Ed25519) for deterministic signatures, which is covered in a separate tutorial.
Sample Input and Output
=== EC key pair on secp256r1 ===
Curve : java.security.spec.EllipticCurve@...
Generator G bit len : 256
Order n bit length : 256
Private key S bit len: 256
Public key W x bit len: 256
Public key W y bit len: 256
=== Signature ===
Message : ECDSA gives 128-bit security with 256-bit keys.
Signature (DER) : MEQC...base64-prefix-here...
Signature length : 71 bytes (DER-encoded)
Verify ok : true
Tamper detected : true
Two sigs differ : true
Note: ECDSA requires a unique nonce per signature. Reusing the nonce
reveals the private key. Use EdDSA (Ed25519) for deterministic signatures.
The EC key pair uses the P-256 curve with a 256-bit order n, a 256-bit private key S, and a 256-bit X and Y for the public key W. The DER-encoded signature is around 71 bytes (the ASN.1 overhead is small but variable because r and s may have leading zeros). The verification succeeds for the original message and fails for the tampered message. The two signatures of the same message differ because the nonce k is random.
Common Mistakes to Avoid
The first mistake is reusing the nonce k. If k is reused for two signatures with the same private key, the private key d can be recovered from the two signatures. This is the Sony PlayStation 3 hack of 2010, where Sony reused k for the ECDSA signatures of the boot loader, which allowed hackers to recover Sony's private key and sign arbitrary code.
The second mistake is using a weak random number generator for k. The Android Bitcoin wallet bug of 2013 (CVE-2013-7372) used a weak random number generator for the ECDSA nonces, which allowed attackers to recover the private keys of affected wallets. Always use SecureRandom, which is backed by the OS entropy source.
The third mistake is using an untrusted curve. The NIST curves P-256, P-384, and P-521 are widely deployed and well-analyzed, although some cryptographers (including Daniel J. Bernstein) have expressed concerns about the provenance of the curve parameters. The Curve25519 family (used by EdDSA) was designed to be safer, but for compatibility with existing systems the NIST curves remain the default.
The fourth mistake is using ECDSA for new designs when EdDSA is available. EdDSA (Ed25519) offers deterministic signatures, side-channel resistance, and faster signing and verification for equivalent security. The IETF RFC 8032 standardizes Ed25519 and Ed448, and the JDK has shipped EdDSA in the SunEC provider since Java 15.
Real-World Applications
ECDSA is the signature algorithm in Bitcoin and Ethereum, where the secp256k1 curve is used to sign transactions. A Bitcoin transaction is a list of inputs (unspent transaction outputs) and outputs (addresses and amounts), and each input is signed with the ECDSA private key corresponding to the address. The Bitcoin Core software uses the libsecp256k1 library, which is the fastest ECDSA implementation for the secp256k1 curve.
TLS 1.3 uses ECDSA with the NIST curves P-256 and P-384 for the CertificateVerify message. The ecdsa_secp256r1_sha256 and ecdsa_secp384r1_sha384 signature algorithms are the ECDSA options in the TLS 1.3 signature_algorithms extension. The ECDSA option is the modern alternative to RSA-PSS for servers that use elliptic-curve certificates, which have smaller keys and signatures than RSA certificates for equivalent security.
JWT (JSON Web Token) signing with ES256 (ECDSA with P-256 and SHA-256) is a common deployment pattern in REST APIs. The Spring Security OAuth2 library supports ES256, ES384, ES512 (P-256, P-384, P-521). The ECDSA signature is 64 bytes raw, which is much smaller than the 256-byte RSA signature for equivalent security.
Apple's App Attestation and Google's Play Integrity API use ECDSA to sign the attestation payloads. The signed data is the attestation object that proves the app has not been tampered with; the verifier uses the platform's public key (rooted in the Apple or Google root certificate) to verify the signature.
The ecdsa signature java tutorial in this post shows the JDK Signature class with the P-256 curve. For new designs, consider EdDSA (Ed25519) for deterministic signatures and side-channel resistance; for compatibility with existing systems, ECDSA with P-256 remains the standard. The manual implementation of ECDSA is left to the dedicated tutorial on elliptic-curve point arithmetic.
Conclusion
In this ecdsa signature java tutorial we built the ECDSA signature scheme using the JDK Signature class with the P-256 curve, demonstrated the signature-then-verify round trip with tamper detection, and explained the nonce requirement that is the main footgun of ECDSA. ECDSA is the signature algorithm in Bitcoin, Ethereum, and the TLS 1.3 handshake; for new designs, consider EdDSA for deterministic signatures. Next, study the EdDSA tutorial, the DSA tutorial, the RSA signature tutorial, and the elliptic-curve point arithmetic that underlies ECDSA.
Comments
Comments
Post a Comment