Skip to content
Ashish.
All posts
Diagram illustrating the ECDH key exchange mechanism between Alice and Bob over an insecure channel.

Implementing Cryptographic Agreements in Identity: ECDH and Key Agreement Protocols

An examination of ECDH and key agreement protocols within elliptic curve cryptography for secure identity verification and TLS handshakes.

By Ashish SrivastavaPart 3 of Cryptographic Protocols Guide

Elliptic Curve Diffie-Hellman (ECDH) is not a transport protocol but a mathematical mechanism for deriving shared secrets from public keys. This analysis dissects the mechanism of point multiplication to demonstrate how identity systems and TLS utilize it to establish session keys without transmitting secrets over insecure channels.

The Mechanism of Scalar Multiplication

To understand how two strangers establish a shared secret, one must look past the "key agreement" label and examine the underlying mathematics. The mechanism relies on the properties of elliptic curve groups, specifically the difficulty of the Elliptic Curve Discrete Logarithm Problem (ECDLP). In this system, operations occur on a curve defined over a finite field. Consider the curve secp256r1, a standard curve defined by NIST standards.

Imagine two actors, Alice and Bob. They agree on a public base point G on the curve, which acts as the generator. Alice picks a random private integer a (her secret). She computes her public key A by performing scalar multiplication: A = a * G. This implies adding the point G to itself a times. Bob performs the same operation with his secret b, calculating B = b * G.

The mechanism enabling the agreement is that scalar multiplication is commutative within this group structure. If Alice calculates b * A, she effectively computes b * (a * G), which equals (b * a) * G. If Bob calculates a * B, he computes a * (b * G), which equals (a * b) * G. Since integer multiplication is commutative (a * b = b * a), both parties arrive at the exact same point S on the curve: S = ab * G.

Technical diagram showing Alice and Bob performing scalar multiplication on an elliptic curve. Alice has private key 'a' and public key 'A'. Bob has private key 'b' and public key 'B'. Both calculate the shared secret 'S' = ab*G. Style : clean vector illustration, blue and gre…

The security lies in the direction of trust and data flow. An eavesdropper, Eve, sees A, B, and G. She knows A = a * G and B = b * G. To find the shared secret S, she must determine a or b from A or B. This is the Discrete Logarithm Problem. Given a point P and a generator G, finding k such that P = k * G is computationally infeasible for large curves. Therefore, Eve cannot derive S without solving a problem that would take centuries with current hardware.

This mechanism is the bedrock of modern identity verification. It allows a client and a server to generate a unique session key for every connection, even if they have never met before, provided they can authenticate each other's long-term keys.

Ephemeral Keys in Identity Contexts

While the math above describes a static exchange, real-world identity systems like TLS 1.3 require "Ephemeral" ECDH (ECDHE). The distinction is critical for security posture. If Alice and Bob use their long-term private keys for the ECDH exchange, the system lacks Forward Secrecy. If Alice's long-term private key is stolen next year, an attacker who recorded all past traffic can retroactively compute the shared secrets for those sessions.

In a secure identity implementation, the private key used for ECDH must be ephemeral—generated fresh for every single handshake and discarded immediately after the session ends.

Consider a TLS 1.3 scenario between a browser (Client) and an API Gateway (Server). The Server has a long-term certificate containing a static public key CertPubKey, signed by a Certificate Authority (CA). This certificate authenticates the identity of the server. However, for the key agreement, the Server generates a new ephemeral key pair (d_s, Q_s) where Q_s = d_s * G. The Client also generates (d_c, Q_c).

The data flow here ensures that the long-term identity key only authenticates the ephemeral key, not the session key itself. The signature on the ephemeral key, bound to the handshake transcript, proves that the ephemeral key belongs to the holder of the private key associated with the certificate. The Server sends its ephemeral public key Q_s directly within the ServerHello message.

Architecture flowchart showing TLS 1.3 handshake. Top layer : Long-term Identity Certificate (CA Signed). Middle layer : Ephemeral Key Exchange (ECDHE). Bottom layer : Session Encryption. Arrows show identity binding to ephemeral keys. Style : technical schematic, dark mode, n…

This separation of concerns is the mechanism that protects identity. The CA-signed certificate proves "I am the Server." The ephemeral ECDH exchange proves "We are currently talking to each other."

The TLS Handshake Protocol Flow

Let's trace the data flow in a TLS 1.3 handshake using ECDHE, focusing on the artifact exchange. We will use the x25519 curve for this example as it is the most common modern implementation, though the logic holds for secp256r1.

  1. ClientHello: The client sends a list of supported groups (e.g., x25519, secp256r1). It also includes its own ephemeral public key client_key (let's call it Q_c).

    ClientHello: {
      supported_groups: [x25519, secp256r1],
      key_share: {
        group: x25519,
        key_exchange: <Q_c_bytes>
      }
    }
  2. ServerHello: The server selects a group (say, x25519) and sends its ephemeral public key Q_s directly within the ServerHello message. Crucially, the server signs this ephemeral key along with the handshake transcript using its long-term private key to bind it to its identity. There is no separate ServerKeyExchange message in TLS 1.3.

    ServerHello: {
      selected_group: x25519,
      key_share: {
        group: x25519,
        key_exchange: <Q_s_bytes>
      },
      server_signature: <Signature(Handshake_Transcript || ...)>
    }
  3. Key Derivation: Both parties now possess Q_c and Q_s.

    • Client computes: shared_secret = ECDH(client_private, server_public)
    • Server computes: shared_secret = ECDH(server_private, client_public)

    This shared_secret is raw bytes. It is not yet a key. It must be processed through a Key Derivation Function (KDF), specifically HKDF (HMAC-based Key Derivation Function) as defined in RFC 8446. The KDF takes the shared_secret along with the transcript of all previous messages (the handshake_hash) to ensure the key is bound to the specific context of this session.

    # Conceptual pseudocode for the derivation
    master_secret = HKDF-Expand(shared_secret, "master_secret", HashLen)
    handshake_traffic_key = HKDF-Expand(master_secret, "client_handshake_traffic_secret", HashLen)
  4. Verification: The client sends a Finished message encrypted with the derived handshake_traffic_key. The server decrypts it. If the decryption succeeds and the MAC matches, the server knows the client computed the same master secret, confirming the integrity of the ECDH exchange. Note that this verifies the computation of the shared secret, but does not inherently authenticate the client's identity unless a ClientCertificate was explicitly requested and exchanged during the handshake.

The direction of trust flows from the CA-signed certificate (Identity) to the ephemeral exchange (Confidentiality). The ECDH mechanism provides the confidentiality; the signature provides the identity binding.

Tradeoffs and Implementation Risks

Implementing ECDH correctly is notoriously difficult due to side-channel vulnerabilities. The scalar multiplication operation a * G is not a single atomic CPU instruction; it involves a sequence of point doublings and additions. If the timing of these operations depends on the bits of the secret scalar a, an attacker can measure the time taken to recover a.

For example, a naive implementation might skip an addition step if a bit is zero, making the operation faster. This timing difference leaks information. Secure implementations use "constant-time" algorithms, ensuring the sequence of operations is identical regardless of the secret key's value. This often involves "Montgomery Ladders" or specific curve-specific algorithms like the Bernstein-Lange ladder for x25519.

Furthermore, the choice of curve matters. Older curves like secp160r1 are deprecated because the key space is too small for modern brute-force capabilities. Modern implementations should default to x25519 or secp256r1 (P-256). x25519 is often preferred in new systems because its implementation is simpler and less prone to subtle bugs compared to generic curve implementations.

In the context of identity, if the ephemeral key generation is weak (e.g., using a predictable pseudo-random number generator), the entire security model collapses. The mathematical hardness of the discrete log problem is irrelevant if the private key a is predictable. The random number generator (RNG) must be cryptographically secure (CSPRNG).

Finally, there is the issue of key reuse. Some legacy systems attempt to reuse the same ephemeral key across multiple sessions. This violates the forward secrecy guarantee. If the long-term private key is compromised later, the attacker can compute all past session keys. The protocol must enforce that d_s and d_c are unique per handshake.

The mechanism of ECDH is secure, but its implementation is fragile. It requires strict adherence to constant-time execution, high-quality randomness, and correct protocol sequencing to maintain the integrity of the identity and the confidentiality of the data.

Conclusion

ECDH provides the mathematical foundation for establishing shared secrets over insecure channels, but its utility in identity systems depends entirely on the ephemeral nature of the keys and the rigorous application of protocol standards like TLS 1.3. By separating long-term identity authentication from short-term session key generation, systems achieve forward secrecy. However, the complexity of constant-time implementation and the critical need for high-quality randomness mean that developers must rely on well-audited libraries rather than rolling their own cryptographic primitives.

Common Pitfalls

Developers frequently encounter specific failure modes when integrating ECDH into production systems.

  1. Timing Attacks: Implementing scalar multiplication without constant-time guarantees allows attackers to infer private key bits based on execution time variations. Even microsecond differences can leak the entire secret key over many requests.
  2. Weak Random Number Generation: Using standard pseudo-random number generators (PRNGs) instead of Cryptographically Secure Pseudo-Random Number Generators (CSPRNGs) for ephemeral keys can result in predictable secrets, rendering the mathematical security of the curve moot.
  3. Key Reuse: Accidentally reusing an ephemeral key across multiple sessions breaks Forward Secrecy. If the long-term private key is compromised later, all past session keys can be reconstructed.

Practical Takeaways

To implement ECDH securely, adhere to these mental models and rules:

  1. Always Use Ephemeral Keys: Never use static ECDH for session key establishment in modern protocols. Always generate fresh key pairs for every handshake to ensure Forward Secrecy.
  2. Verify Constant-Time Libraries: Do not implement cryptographic primitives yourself. Rely on established libraries (e.g., OpenSSL, libsodium, BoringSSL) that have been audited for constant-time execution and side-channel resistance.
  3. Enforce CSPRNG: Ensure your environment's entropy source is robust. Validate that the RNG used for generating ephemeral keys is cryptographically secure and seeded with sufficient entropy.

FAQ

Q: Does TLS 1.3 still support static ECDH? A: No, TLS 1.3 has removed support for static ECDH key exchange. It mandates the use of ephemeral keys (ECDHE) to ensure Forward Secrecy for all connections.

Q: What is the difference between ECDH and ECDHE? A: ECDH refers to the general key agreement mechanism. ECDHE specifies that the keys used in the ECDH exchange are ephemeral (temporary), generated fresh for each session, whereas static ECDH uses long-term keys.

Q: Why is the signature in TLS 1.3 different from TLS 1.2? A: In TLS 1.2, the server's signature was often sent in a separate ServerKeyExchange message. In TLS 1.3, the signature is bound directly to the handshake transcript and sent within the ServerHello message alongside the key share, simplifying the flow and reducing round trips.

Related posts