Diffie-Hellman (DH)

Index

Using Diffie-Hellman (DH) for key exchange

Diffie-Hellman is one of the oldest public-key cryptosystems. It is often called a key-agreement protocol, because it allows the establishment of a common secret key, that can be used to encrypt and decrypt messages.

Generate DH public key parameters

Generate the DH public key parameters and save them to a file (this may take a while to complete depending on the key size - you need to be patient).

openssl dhparam -out dhparams.pem 2048

Here are the parameters generated in base64.

-----BEGIN DH PARAMETERS-----
MIIBCAKCAQEA/J7CXLjNaOZoL9QNkhlPI8iGjuI1hVLHKCxdLP5LhLqqPfOiKLBE
8wU8LgiAOiH7jMW4BfohuoCRG7E8xWnplt1Rn1SAiiZzdeKKY4t08fiCAmO3EUHj
sxXPwV537IbbN2d2MRxIodCla9nIx/x906foXfhpr4mi3k+dfg5lv/2HOnjST0qR
NccwjqH+k3ye03bhuB6D9pEL2prRrDxn13q4UGoh0Uwp/wcxHQk1sy6ouvaaEJYm
OKemxWVZ19EPOpIVxvgVTa0e28z7zlDP/9+xN7fCu46Irv0SWVxa2JnAogP308rk
8xAgeRJA4lRKOAgFb2dJZSNT65w19SeBqwIBAg==
-----END DH PARAMETERS-----

To view the contents of the parameters of the file, please do:

openssl pkeyparam -in dhparams.pem -text

And you'll have access to the parameters created.

-----BEGIN DH PARAMETERS-----
MIIBCAKCAQEA/J7CXLjNaOZoL9QNkhlPI8iGjuI1hVLHKCxdLP5LhLqqPfOiKLBE
8wU8LgiAOiH7jMW4BfohuoCRG7E8xWnplt1Rn1SAiiZzdeKKY4t08fiCAmO3EUHj
sxXPwV537IbbN2d2MRxIodCla9nIx/x906foXfhpr4mi3k+dfg5lv/2HOnjST0qR
NccwjqH+k3ye03bhuB6D9pEL2prRrDxn13q4UGoh0Uwp/wcxHQk1sy6ouvaaEJYm
OKemxWVZ19EPOpIVxvgVTa0e28z7zlDP/9+xN7fCu46Irv0SWVxa2JnAogP308rk
8xAgeRJA4lRKOAgFb2dJZSNT65w19SeBqwIBAg==
-----END DH PARAMETERS-----
DH Parameters: (2048 bit)
    prime:
        00:fc:9e:c2:5c:b8:cd:68:e6:68:2f:d4:0d:92:19:
        4f:23:c8:86:8e:e2:35:85:52:c7:28:2c:5d:2c:fe:
        4b:84:ba:aa:3d:f3:a2:28:b0:44:f3:05:3c:2e:08:
        80:3a:21:fb:8c:c5:b8:05:fa:21:ba:80:91:1b:b1:
        3c:c5:69:e9:96:dd:51:9f:54:80:8a:26:73:75:e2:
        8a:63:8b:74:f1:f8:82:02:63:b7:11:41:e3:b3:15:
        cf:c1:5e:77:ec:86:db:37:67:76:31:1c:48:a1:d0:
        a5:6b:d9:c8:c7:fc:7d:d3:a7:e8:5d:f8:69:af:89:
        a2:de:4f:9d:7e:0e:65:bf:fd:87:3a:78:d2:4f:4a:
        91:35:c7:30:8e:a1:fe:93:7c:9e:d3:76:e1:b8:1e:
        83:f6:91:0b:da:9a:d1:ac:3c:67:d7:7a:b8:50:6a:
        21:d1:4c:29:ff:07:31:1d:09:35:b3:2e:a8:ba:f6:
        9a:10:96:26:38:a7:a6:c5:65:59:d7:d1:0f:3a:92:
        15:c6:f8:15:4d:ad:1e:db:cc:fb:ce:50:cf:ff:df:
        b1:37:b7:c2:bb:8e:88:ae:fd:12:59:5c:5a:d8:99:
        c0:a2:03:f7:d3:ca:e4:f3:10:20:79:12:40:e2:54:
        4a:38:08:05:6f:67:49:65:23:53:eb:9c:35:f5:27:
        81:ab
    generator: 2 (0x2)

Generate the DH private and public keys

Using the DH public parameters that were created in the previous step, it is now necessary to create the public and private keys of both entities that need to communicate (again Alice and Bob).

So, both Alice and Bob, need to have the dhparams.pem file created in the previous step.

Now, Alice can do the following to create its private key:

openssl genpkey -paramfile dhparams.pem -out alice_private.dh

Let’s look at the content of Alice private key:

openssl pkey -in alice_private.dh -text -noout

This is the contents of the private key:

DH Private-Key: (2048 bit)
    private-key:
        68:fd:1e:8b:01:a1:6b:b1:80:2d:a5:9d:19:f5:74:
        5c:5a:9f:d2:ea:a0:64:69:3e:99:e4:e0:85:fc:e5:
        d0:cc:f5:f9:76:61:07:22:4c:1f:2b:7b:f2:9a:6b:
        0c:dc:11:1c:70:7c:29:ff:e9:13:48:7b:01:b2:11:
        e9:13:92:a1:a9:59:22:2c:de:66:55:d5:c2:12:93:
        cf:d4:ed:d8:46:45:2b:86:32:c8:06:ff:33:58:43:
        02:a5:df:f1:8d:19:a9:d6:26:c2:04:71:54:65:55:
        67:d3:8f:e2:48:ba:e7:58:f2:58:18:f3:56:5a:ca:
        b2:ae:3a:08:a1:d2:fc:6e:95:31:7e:d3:94:cf:72:
        66:2c:58:5e:3f:16:b2:3b:a3:0a:d4:00:b7:e4:e3:
        34:5f:91:e6:60:75:3c:7f:ae:a9:37:37:2b:e4:e2:
        f4:82:0a:28:5a:18:b2:56:f8:26:81:76:8e:1f:07:
        9d:f0:de:a6:6c:34:34:44:ce:20:d2:fb:55:7c:07:
        28:f9:cd:02:81:7d:0d:bd:57:7b:13:a9:1d:fd:f6:
        15:39:d1:ce:03:ff:ef:5b:32:6d:5c:f5:2d:66:76:
        ae:70:5b:a8:f3:f0:34:fd:b6:cc:09:32:a7:02:78:
        e1:9c:0d:cd:c5:43:59:db:36:fc:ae:f3:61:4f:27:
        18
    public-key:
        75:e6:9b:4b:d2:6a:f3:6e:07:e2:0f:10:50:e9:fd:
        a2:4c:99:8b:88:59:85:e3:5a:a4:f6:82:72:c3:55:
        bc:94:b3:6c:08:d9:30:e8:15:33:42:cd:bb:7d:3b:
        8f:0f:82:b8:94:b9:de:60:34:cd:f0:61:00:3f:01:
        6a:19:04:f9:04:63:9d:06:94:5c:22:22:62:86:b8:
        21:5b:c4:2c:be:00:6a:ad:e3:a7:13:57:31:04:9c:
        a1:df:01:20:11:af:83:2e:2e:cd:9c:7b:06:2f:a4:
        ae:c5:31:01:8a:39:b5:e1:80:53:b0:fe:0c:00:6d:
        76:0c:9c:69:09:0c:44:98:c8:b5:7e:d1:ed:58:db:
        39:05:b8:c0:71:20:64:1f:71:3b:b3:69:5b:9b:3c:
        11:3d:ce:db:dc:2f:72:2d:ee:4d:75:8c:e5:07:f1:
        ad:e1:08:a9:62:25:ba:67:13:83:00:85:97:d2:74:
        be:ea:1e:cd:11:4e:bb:4c:e1:01:99:3f:5a:86:69:
        5e:23:ec:6f:a8:ce:58:f7:3d:cf:50:7f:7d:08:0c:
        b7:74:47:f7:5e:76:89:fb:97:44:05:53:16:98:2a:
        d7:ca:38:c1:b2:a1:3d:6e:32:38:46:95:f2:fd:6e:
        6f:a9:be:47:78:68:04:37:52:b8:4f:b0:a7:f3:8d:
        9c
    prime:
        00:fc:9e:c2:5c:b8:cd:68:e6:68:2f:d4:0d:92:19:
        4f:23:c8:86:8e:e2:35:85:52:c7:28:2c:5d:2c:fe:
        4b:84:ba:aa:3d:f3:a2:28:b0:44:f3:05:3c:2e:08:
        80:3a:21:fb:8c:c5:b8:05:fa:21:ba:80:91:1b:b1:
        3c:c5:69:e9:96:dd:51:9f:54:80:8a:26:73:75:e2:
        8a:63:8b:74:f1:f8:82:02:63:b7:11:41:e3:b3:15:
        cf:c1:5e:77:ec:86:db:37:67:76:31:1c:48:a1:d0:
        a5:6b:d9:c8:c7:fc:7d:d3:a7:e8:5d:f8:69:af:89:
        a2:de:4f:9d:7e:0e:65:bf:fd:87:3a:78:d2:4f:4a:
        91:35:c7:30:8e:a1:fe:93:7c:9e:d3:76:e1:b8:1e:
        83:f6:91:0b:da:9a:d1:ac:3c:67:d7:7a:b8:50:6a:
        21:d1:4c:29:ff:07:31:1d:09:35:b3:2e:a8:ba:f6:
        9a:10:96:26:38:a7:a6:c5:65:59:d7:d1:0f:3a:92:
        15:c6:f8:15:4d:ad:1e:db:cc:fb:ce:50:cf:ff:df:
        b1:37:b7:c2:bb:8e:88:ae:fd:12:59:5c:5a:d8:99:
        c0:a2:03:f7:d3:ca:e4:f3:10:20:79:12:40:e2:54:
        4a:38:08:05:6f:67:49:65:23:53:eb:9c:35:f5:27:
        81:ab
    generator: 2 (0x2)

Now Bob, needs to do the same thing:

openssl genpkey -paramfile dhparams.pem -out bob_private.dh

After this, Bob and Alice need to exchange their public keys. These need to get extracted from their private key files generated in the previous step.

So, Alice does:

openssl pkey -in alice_private.dh -pubout -out alice_public.dh

And Bob, does:

openssl pkey -in bob_private.dh -pubout -out bob_public.dh

Now, Alice can send alice_public.dh to Bob, and Bob can send bob_public.dh to Alice.

Finally, both Alice and Bob, can compute a common secret key that can be used to exchange encrypted information. Alice, needs to derive its key:

openssl pkeyutl -derive -inkey alice_private.dh -peerkey bob_public.dh -out alice_common_key.dh

And Bob, can do the same:

openssl pkeyutl -derive -inkey bob_private.dh -peerkey alice_public.dh -out bob_common_key.dh

If we compare them both, they are equal.

diff alice_common_key.dh bob_common_key.dh

And you can look at the content of the files... using hexdump utility.

hexdump -C alice_common_key.dh

Here are the contents of the key:

00000000  c7 5f cf 8d 1e 00 6f 54  7b cc 7d 0c 85 d0 99 15  |�_�...oT{�}..�..|
00000010  78 47 bc 32 fa 09 67 73  15 b5 9e 42 e6 e0 13 3c  |xG�2�.gs.�.B��.<|
00000020  d7 d3 1c 17 a1 ef 45 1f  4b 2f 65 b0 d0 87 f9 d0  |��..��E.K/e��.��|
00000030  2e 99 fe 66 91 fe e3 c1  01 2a b0 e2 d5 e1 a7 4e  |..�f.���.*����N|
00000040  b8 8c 97 e1 c4 ec 29 58  41 06 77 50 f4 95 23 fb  |�..���)XA.wP�.#�|
00000050  13 29 01 43 22 05 8a db  38 1a f8 21 30 8c f8 f7  |.).C"..�8.�!0.��|
00000060  22 25 7b 88 89 7a 05 0c  b5 fa 30 ce 61 2c c6 e4  |"%{..z..��0�a,��|
00000070  24 ca 23 e2 78 05 13 b3  2e 13 a9 2c e4 19 d7 eb  |$�#�x..�..�,�.��|
00000080  be 8a 61 b4 d1 20 df ed  9e a2 31 89 4b b0 d5 6b  |�.a�� ��.�1.K��k|
00000090  ac d8 8a 01 46 1a cc b9  fc aa e0 68 6d 82 35 52  |��..F.̹��hm.5R|
000000a0  45 c5 10 6d bd 07 ac a1  a9 4f 3f 23 12 e3 d8 4e  |E�.m�.���O?#.��N|
000000b0  0e e9 18 04 68 da b4 93  5d e0 86 c0 ad 1f d6 fc  |.�..hڴ.]�.��.��|
000000c0  d7 e1 70 64 77 96 6b 83  57 77 47 5a 60 1d 45 92  |��pdw.k.WwGZ`.E.|
000000d0  70 46 67 4d 3a f8 64 d7  ad f9 db a4 0d 92 cf e6  |pFgM:�d׭�ۤ..��|
000000e0  d0 43 86 be b6 2e 65 08  95 dc 7d d9 6d 0c 03 b9  |�C.��.e..�}�m..�|
000000f0  cb 2a 46 5e 6a 78 36 2f  51 ff ba b5 7a 17 45 33  |�*F^jx6/Q���z.E3|
00000100

As an alternative for the creation of keys we could use the following examples. In these examples, we create the common DH key and after that we create an SHA-256 hash of the key. This way, we end-up with a raw 256-bit key that can be used directly. This key is store on the alice_common_key.dh and bob_common_key.dh.

So Alice does:

openssl pkeyutl -derive -inkey alice_private.dh -peerkey bob_public.dh | openssl dgst -sha256 -binary > alice_common_key.dh

For the case of Bob:

openssl pkeyutl -derive -inkey bob_private.dh -peerkey alice_public.dh | openssl dgst -sha256 -binary > bob_common_key.dh

In this case, we end up with this key (dd7fa8bee81aa373924fcf68348fff7c8cdf4eb2078b0000ebf1f7899802c48f).

Looking at the files:

hexdump alice_common_key.dh

hexdump bob_common_key.dh

They both contain the same information:

0000000 dd7f a8be e81a a373 924f cf68 348f ff7c
0000010 8cdf 4eb2 078b 0000 ebf1 f789 9802 c48f
0000020

This key can be used as secret key to cipher and decipher data, as we can see in the next section.

Encrypt and decrypt with DH

Now that we have a common key between Alice and Bob, this key can be used to do symmetric cryptography between the two parties communicating. Consider the plain.txt and cipher.txt below, two examples of files that are going to be encrypted or decrypted.

To encrypt data in Alice, we can use:

openssl aes-256-ecb -base64 -kfile alice_common_key.dh -e -in plain.txt -out cipher.txt -pbkdf2

To decrypt data in the Bob side, we can do:

openssl aes-256-ecb -base64 -kfile bob_common_key.dh -d -in cipher.txt -out clear.txt -pbkdf2

Another possibility is to use the raw key that we've created before. To encrypt data Alice can do the following:

openssl aes-256-ecb -base64 -e -in plain.txt -out cipher.txt -K dd7fa8bee81aa373924fcf68348fff7c8cdf4eb2078b0000ebf1f7899802c48f

Bob to decrypt data does the following:

openssl aes-256-ecb -base64 -d -in cipher.txt -out clear.txt -K dd7fa8bee81aa373924fcf68348fff7c8cdf4eb2078b0000ebf1f7899802c48f

Last updated