Basic Key Exchange with Diffie-Hellman in Cryptography

LinuxBeginner
Practice Now

Introduction

In this lab, you will explore the fundamentals of the Diffie-Hellman (DH) key exchange, a cornerstone of modern cryptography. The DH protocol allows two parties, who have no prior knowledge of each other, to jointly establish a shared secret key over an insecure communication channel. This shared secret can then be used to encrypt subsequent communications using a symmetric key cipher.

You will use the powerful openssl command-line tool to simulate the entire DH process. This includes generating the public parameters, creating private and public keys for two separate parties, and finally, deriving and verifying the shared secret. By the end of this lab, you will have a practical understanding of how this essential cryptographic handshake works.

Diffie-Hellman Key Exchange Principle

In this step, we will cover the theoretical principle of the Diffie-Hellman key exchange. There are no commands to execute in this step; the goal is to understand the concept before implementing it.

The process works as follows:

  1. Agreement on Public Parameters: Two parties, let's call them Alice and Bob, first agree on two public numbers: a large prime number p (the modulus) and a base g (the generator). These numbers are not secret and can be transmitted over an insecure channel.

  2. Private Key Generation:

    • Alice chooses a secret private integer a. She keeps this number to herself.
    • Bob chooses a secret private integer b. He keeps this number to himself.
  3. Public Key Calculation:

    • Alice calculates her public key A using the formula: A = g^a \mod p. She sends this public key A to Bob.
    • Bob calculates his public key B using the formula: B = g^b \mod p. He sends this public key B to Alice.
  4. Shared Secret Derivation:

    • Alice receives Bob's public key B and calculates the shared secret S using her own private key a: S = B^a \mod p.
    • Bob receives Alice's public key A and calculates the shared secret S using his own private key b: S = A^b \mod p.

Due to the properties of modular arithmetic, both Alice and Bob will arrive at the exact same value for S.

  • Alice's calculation: S = (g^b \mod p)^a \mod p = g^{ba} \mod p
  • Bob's calculation: S = (g^a \mod p)^b \mod p = g^{ab} \mod p

An eavesdropper on the channel can see p, g, A, and B, but cannot easily compute the private keys a or b. This difficulty is known as the discrete logarithm problem, which forms the basis of the security of the Diffie-Hellman exchange.

In the following steps, you will use openssl to perform these actions.

Generate Diffie-Hellman Parameters

In this step, you will generate the public DH parameters (p and g) that both parties will use. The openssl tool can handle the complex mathematics of finding a suitable prime and generator for you. All operations in this lab will be performed in the default ~/project directory.

Use the openssl dhparam command to generate the parameters. We will specify a key size of 2048 bits, which is a common and secure length for this purpose.

Execute the following command in your terminal:

openssl dhparam -out dhparam.pem 2048

Let's break down this command:

  • openssl dhparam: This invokes the DH parameter management tool in OpenSSL.
  • -out dhparam.pem: This flag specifies that the output should be saved to a file named dhparam.pem.
  • 2048: This is the desired bit length of the prime modulus p.

This command may take a minute to complete as it searches for a strong prime number. You will see an output similar to the following while it's working:

Generating DH parameters, 2048 bit long safe prime

Once finished, a file named dhparam.pem will be created in your current directory. This file contains the public parameters that both parties will use for the key exchange.

Generate Party A's Keys

In this step, you will simulate the actions of the first party, "Party A". Party A will use the shared DH parameters from the previous step to generate its own private key and then derive a corresponding public key.

First, generate Party A's private key. This key is the secret number a from our theoretical example. We will use the openssl genpkey command, which is a general-purpose key generation utility.

Execute the following command to generate the private key for Party A:

openssl genpkey -paramfile dhparam.pem -out a_private_key.pem
  • genpkey: The command to generate a private key.
  • -paramfile dhparam.pem: This tells genpkey to use the parameters from our dhparam.pem file to create a DH key.
  • -out a_private_key.pem: This saves the generated private key to the file a_private_key.pem.

Next, Party A needs to derive its public key from the private key. The public key is what will be shared with Party B.

Execute this command to extract the public key:

openssl pkey -in a_private_key.pem -pubout -out a_public_key.pem
  • pkey: A command for managing public and private keys.
  • -in a_private_key.pem: Specifies the input private key.
  • -pubout: This flag instructs the command to output the public part of the key.
  • -out a_public_key.pem: Saves the resulting public key to a_public_key.pem.

Now you have two new files: a_private_key.pem, which Party A must keep secret, and a_public_key.pem, which Party A would send to Party B over the insecure channel.

Generate Party B's Keys

In this step, you will perform the same actions for the second party, "Party B". Party B operates independently of Party A but uses the same public DH parameters from dhparam.pem.

First, generate Party B's private key. This corresponds to the secret number b in our theoretical example.

Execute the following command:

openssl genpkey -paramfile dhparam.pem -out b_private_key.pem

This command is identical in structure to the one for Party A, but we are saving the output to b_private_key.pem to distinguish it.

Next, just like Party A, Party B must derive its public key from its new private key.

Execute this command to extract Party B's public key:

openssl pkey -in b_private_key.pem -pubout -out b_public_key.pem

At this point in a real-world exchange, Party A would have Party B's public key (b_public_key.pem), and Party B would have Party A's public key (a_public_key.pem). Both parties have kept their respective private keys secret. You have now successfully simulated the key generation and exchange portion of the protocol.

Compute Shared Secret

This is the final and most important step. Here, both parties will use their own private key and the other party's public key to independently compute the shared secret. If the protocol is successful, they will both arrive at the exact same secret value.

First, let's compute the shared secret from Party A's perspective. Party A uses its private key (a_private_key.pem) and Party B's public key (b_public_key.pem).

Run the following command:

openssl pkeyutl -derive -inkey a_private_key.pem -peerkey b_public_key.pem -out a_shared_secret.bin
  • pkeyutl: A utility for performing public key operations.
  • -derive: This action tells the utility to derive a shared secret.
  • -inkey a_private_key.pem: Specifies Party A's own private key.
  • -peerkey b_public_key.pem: Specifies the public key of the other party (the "peer").
  • -out a_shared_secret.bin: Saves the resulting binary secret to a file.

Next, compute the shared secret from Party B's perspective. Party B uses its private key (b_private_key.pem) and Party A's public key (a_public_key.pem).

Run the following command:

openssl pkeyutl -derive -inkey b_private_key.pem -peerkey a_public_key.pem -out b_shared_secret.bin

Now, you have two files, a_shared_secret.bin and b_shared_secret.bin. To verify the success of the key exchange, these two files must be identical. You can use the cmp (compare) command to check this.

cmp a_shared_secret.bin b_shared_secret.bin

If the files are identical, this command will produce no output and exit silently. This silence signifies success!

For a more visual confirmation, you can also compute the cryptographic hash of both files. The hashes must match.

sha256sum *.bin

You should see an output where both files have the exact same SHA256 hash. The actual hash values will vary between runs, but they must be identical for both files:

e3705a4ab5ae5d86f59dfe968f0177b49d5144e2d731dbd8d41b2eda318412ec  a_shared_secret.bin
e3705a4ab5ae5d86f59dfe968f0177b49d5144e2d731dbd8d41b2eda318412ec  b_shared_secret.bin

(Note: Your hash values will be different from this example, but the important thing is that the hashes for a_shared_secret.bin and b_shared_secret.bin must be identical, proving both parties derived the same shared secret.)

Congratulations, you have successfully performed a Diffie-Hellman key exchange!

Summary

In this lab, you have successfully simulated a complete Diffie-Hellman key exchange using the openssl command-line tool. You have gained hands-on experience with the fundamental steps of this critical cryptographic protocol.

You learned how to:

  • Generate shared public DH parameters (openssl dhparam).
  • Create private and public key pairs for two separate parties based on those parameters (openssl genpkey and openssl pkey).
  • Derive a shared secret from one's own private key and a peer's public key (openssl pkeyutl -derive).
  • Verify that both parties independently computed the exact same secret, proving the success of the exchange.

This process is a foundational building block for secure communication systems like TLS/SSL, which protect data across the internet. You now have a practical understanding of how two parties can establish a secure channel for communication, even when starting on an insecure network.