TrustCore SDK NanoCrypto API reference  version 7.0
DH Overview

All the explanatory write-up was added after the 5.3.1 release, and should be eng-reviewed for accuracy and appropriateness.

About the DH Cipher

In the standard DH scenario, two participants publicly negotiate a Generator value and a Large Prime modulus value. In private, both participants then select a random number (their private key). Using these values, each participant generates a public key: the Generator raised to the power of the private key, modulo the Large Prime. (This calculation is presented in the table below.) Each participant then sends its public key to the other. Using these openly communicated values and their private keys, each participant can generate an identical shared secret value. (The calculation is presented in the table below.)

Using this shared secret value as a key, both parties can encrypt their subsequent communications using a symmetric cipher. The following table summarizes the standard DH protocol and how one uses the fundamental DigiCert TrustCore SDK DH API to implement that protocol. In this table, you will see references to a "client" and a "server." In this case, the client is the initiator of the negotiation, and the server is the responder to the initial request.

StepActionRole of Client and Server
1 Call DH_allocate(). Both client and server use this function to allocate and initialize a diffieHellmanContext structure, which is used by the DH API to maintain DH context information. For details, see the description of the diffieHellmanContext structure and its members.
2 Negotiate the Generator and the Large Prime. During this step of the protocol, the client should contact the server and negotiate the values for the Large Prime and the Generator. The security of the protocol depends on the Large Prime being truly large. For the Generator, agree on a primitive root of the Large Prime. To enhance security, choose a Generator that generates a large subgroup of the multiplicative group mod Large Prime; a single-digit prime number is the usual choice. To generate suitable Generator and Large Prime values for the negotiation, use the functions, DH_getP() and DH_getG().

When exchanging Generator and Large Prime values with a peer, use the ASN.1 object and identifiers specified in the RSA document, PKCS #3: Diffie-Hellman Key-Agreement Standard, a publication of RSA Laboratories. Section 9 of the publication defines the following:

dhKeyAgreement OBJECT IDENTIFIER ::= { pkcs-3 1

pkcs-3 OBJECT IDENTIFIER ::=
{ iso(1) member-body(2) US(840) rsadsi(113549)
pkcs(1) 3 }

DHParameter ::= SEQUENCE {
prime INTEGER, – p
base INTEGER, – g
privateValueLength INTEGER OPTIONAL }
3 Call DH_setPG(). Both the client and server use this function to add the Generator and the Large Prime to the context information stored in their respective diffieHellmanContext structures. The Generator and the Large Prime are stored under the members, dh_g and dh_p. The DH_setPG() function also selects the caller's Private Key, a random number. After selecting the caller's Private Key, this function calculates the caller's Public Key, using the formula:

DiffieHellmanEquationsY_Equation.png

Note
Using the DH_setPG() function, you do not directly access your Private Key. If you need to access the Private Key, read the dh_y member of the diffieHellmanContext structure, but keep in mind that this is the private key and that you must keep it private. Also, note that each exercise of this protocol makes its own call to DH_setPG(), and therefore the Private Key changes from exercise to exercise, which is required for the security of the DH protocol. Do not reuse the Private Key from one exercise to the next.
4 Send your Public Key to the peer. To obtain this Public Key, read the dh_f member of the diffieHellmanContext structure after a successful call to DH_setPG().

Note
Both client and server find their respective Public Key values in the dh_f member of their diffieHellmanContext structure. The dh_f member stores the local Public Key.
5 Receive the Public Key from the peer. Upon receiving the peer's Public Key, both client and server store it in the dh_e member of their respective diffieHellmanContext structures.

Note
Whether you are client or server, use the dh_e member to store the Public Key of the other.
6 Call DH_computeKeyExchange(). After the successful completion of a DH_computeKeyExchange() call, both client and server can find the shared secret in the dh_k member of their respective diffieHellmanContext structures.

DiffieHellmanSharedSecretFormula.png

Note
Internally, DH_computeKeyExchange() validates the public key that is received from the other. An invalid key could indicate manipulation by a man in the middle. In this case, you should stop any further processing of this protocol. Because the standard DH protocol does not include a means of authentication, it is susceptible to the man in the middle attack.
7 DH_freeDhContext() After you are done with the shared secret or have copied it to a secure location, use DH_freeDhContext() to free the diffieHellmanContext structure allocated by the call to DH_allocate().

Using DH_allocateClient() and DH_allocateServer()

Before negotiating with the server for the Generator and Large Prime values, the client calls DH_allocateClient(), which does the following: +# Allocates a diffieHellmanContext structure for the client. +# Chooses a Large Prime value, which it stores in diffieHellmanContext::dh_p member. +# Chooses a private key for the client, which it stores in diffieHellmanContext::dh_y member.

Calling DH_allocateClient() does not choose a Generator value. To get a Generator value for your negotiation with the server, call DH_getG(). After completing the negotiation with the server for the Generator and Large Prime, the client continues the protocol from step 3 in the table above.

After receiving a request from a client, the server calls DH_allocateServer(), which does the following:

  1. Allocates a diffieHellmanContext structure.
  2. Picks a Generator value, which it stores in diffieHellmanContext::dh_g.
  3. Picks a Large Prime value, which it stores in diffieHellmanContext::dh_p.
  4. Picks a Private Key, which it stores in diffieHellmanContext::dh_y.
  5. Generates the Public Key, which it stores in diffieHellmanContext::dh_f.

The DH_allocateServer() function's default operation assumes that the negotiation over the Generator and Large Prime modulus value consists of the server telling the client what the values will be. If that is the case, the server continues the protocol from step 4 in the table above. If that is not the case — that is, if the server truly negotiates these values with the client — the server picks up the protocol from step 3 in the table above.