Using the dh class
The dh class provides a simple Diffie-Hellman key exchange implementation.
Diffie-Hellman allows two parties to agree on a shared secret over an insecure channel. Both parties agree on a prime modulus and generator, then each generates their own key pair using generateKeys(). Each party shares their public key with the other using setPeerPublicKey(), then independently generates the same shared secret using generateSharedSecret().
The setPrimeModulus() and setGenerator() methods set the agreed-upon parameters. The generateKeys() method generates an ephemeral private/public key pair. The getPublicKey() and getPrivateKey() methods retrieve the generated keys. The setPeerPublicKey() method sets the other party's public key, and generateSharedSecret() computes the shared secret, which can be retrieved using getSharedSecret(). The clear() method resets the keys and shared secret while preserving the prime modulus and generator, and reset() clears everything.
The isSupported() method can be used to determine if Diffie-Hellman is available on the current platform.
The following example simulates a Diffie-Hellman key exchange between two parties (alice and bob) using a well-known 1024-bit prime modulus from RFC 2409.
#include <rudiments/dh.h>
#include <rudiments/stdio.h>
int main(int argc, const char **argv) {
dh alice;
dh bob;
// check whether dh is supported
if (!alice.isSupported()) {
stdoutput.write("dh is not supported\n");
return 1;
}
// both parties agree on a prime modulus and generator
// (a well-known 128-byte/1024-bit modular
// exponentiation group from RFC 2409)
const byte_t dhp[]={
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,
0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,
0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,
0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,
0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,
0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
0x49,0x28,0x66,0x51,0xEC,0xE6,0x53,0x81,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
const byte_t dhg[]={0x02};
alice.setPrimeModulus(dhp,sizeof(dhp));
alice.setGenerator(dhg,sizeof(dhg));
bob.setPrimeModulus(dhp,sizeof(dhp));
bob.setGenerator(dhg,sizeof(dhg));
// each party generates their own key pair
alice.generateKeys();
bob.generateKeys();
// each party shares their public key with the other
bob.setPeerPublicKey(alice.getPublicKey(),alice.getPublicKeySize());
alice.setPeerPublicKey(bob.getPublicKey(),bob.getPublicKeySize());
// each party independently generates the shared secret
alice.generateSharedSecret();
bob.generateSharedSecret();
// verify that both shared secrets match
stdoutput.printf("alice's shared secret: ");
for (uint64_t i=0; i<alice.getSharedSecretSize(); i++) {
stdoutput.printf("%02x",alice.getSharedSecret()[i]);
}
stdoutput.write('\n');
stdoutput.printf("bob's shared secret: ");
for (uint64_t i=0; i<bob.getSharedSecretSize(); i++) {
stdoutput.printf("%02x",bob.getSharedSecret()[i]);
}
stdoutput.write('\n');
}