OpenVMS Source Code Demos
DIFFIE_HELLMAN_DEMO_IN_C
//============================================================================
// title : diffie_hellman_demo_in_c_xxx.c
// author : Neil Rieck (https://neilrieck.net)
// : Waterloo, Ontario, Canada.
// created : 2012-07-22
// platform : HP-C on OpenVMS-8.4 (Alpha)
// purpose : demonstrates Diffie-Hellman key exchange employing the usual
// actors: Bob and Alice (who want to communicate privately) and
// Eve (who wishes to Evesdrop)
// references: https://en.wikipedia.org/wiki/Diffie-Hellman_key_exchange
// : http://asecuritysite.com/encryption/diffie (uses JavaScript with BigInt)
// Caveats : 1) This program demonstrates key-exchange concepts but is
// limited to 64-bit math. If you choose values which cause
// g^a1 (or g^b1) to require more than 19 decimal digits, then
// this program will throw an "integer overflow" error.
// 2) This c program employs the mod() function (found in <math>)
// employing the "double float" data type which limits precision
// to 16 digits. It would not be too difficult to write a mod()
// function based upon "long long" but that would only increase
// precision to 19 digits.
// 3) The diffie-hellman algorithm is only secure when P is a prime
// number over 1000 bits in size
// 4) all the other input numbers must be smaller than P
// history :
// ver who when what
// --- --- ------ ------------------------------------------------------------
// 100 NSR 120722 1. original effort
// NSR 140418 2. renamed variable y to g; changed the defaults
//============================================================================
#include <stdio> //
#include <errno> //
#include <stdlib> //
#include <string> //
#include <math> //
//
void nsr_fgets(char* a, int b, FILE* c); //
void remove_trailing_ws(char* a); //
//
// declare Alice's data
//
unsigned long long a1,
a2,
a3;
//
// declare Bob's data
//
unsigned long long b1,
b2,
b3;
//
// declare common data
//
unsigned long long g, // generator
p; // prime
char keyboard[132];
//
// main()
//
void main() {
printf("diffie-hellman-100\n"); //
printf("==================\n"); //
printf("Caveats:\n");
printf("1) This demo program employs 64-bit signed integers. If you choose values\n");
printf(" which cause g^a1 (or g^b1) to require more than 19 decimal digits, then\n");
printf(" this program will throw an 'integer overflow' error.\n");
printf("2) This demo program employs the mod() function found in <math> which means\n");
printf(" precision will be limited to 16 decimal digits\n");
printf("3) The actual algorithm is not secure unless p is a prime number larger\n");
printf(" than 1000 bits (~ 300 decimal digits)\n\n");
//
// in a production program, some of these numbers would be
// picked randomly at the beginning of each communication
// session
//
p = 29;
printf("enter prime 'p'? (default=%lld) ",p); //
keyboard[0] = '\0'; //
nsr_fgets(keyboard,sizeof(keyboard), stdin); //
if (strlen(keyboard)>0){ //
p=atoi(keyboard);
}
printf("note: all future inputs must be less than prime\n\n");
//
g = 3; //
printf("enter generator 'g'? (default=%lld) ",g); //
keyboard[0] = '\0'; //
nsr_fgets(keyboard,sizeof(keyboard), stdin); //
if (strlen(keyboard)>0){
g=atoi(keyboard);
}
a1 = 4; //
printf("enter Alice's guess? (default=%lld) ",a1); //
keyboard[0] = '\0'; //
nsr_fgets(keyboard,sizeof(keyboard), stdin); //
if (strlen(keyboard)>0){
a1=atoi(keyboard);
}
b1 = 5; //
printf("enter Bob's guess? (default=%lld) ",b1); //
keyboard[0] = '\0'; //
nsr_fgets(keyboard,sizeof(keyboard), stdin); //
if (strlen(keyboard)>0){
b1=atoi(keyboard);
}
//
// Alice's calc #1 (private guess >> public key)
//
a2 = pow(g, a1); //
a2 = a2 % p; // a2 will be sent to Bob
//
// Bob's calc #1 (private guess >> public key)
//
b2 = pow(g, b1); //
b2 = b2 % p; // b2 will be sent to Alice
//
// <<< a handshake occurs (exchanging public keys) >>>
//
// Alice's calc #2 (using Bob's public key)
//
a3 = pow(b2, a1); //
a3 = a3 % p; // Alice's computed key
//
// Bob's calc #2 (using Alice's public key)
//
b3 = pow(a2, b1); //
b3 = b3 % p; // Bob's computed key
//
// All done
//
printf("Data sent across the channel (Eve can see it):\n");
printf(" public Prime P: %lld\n",p);
printf(" public Generator G: %lld\n",g);
printf("Randomly generated private data (never sent)\n");
printf(" Alice's private number a1: %lld\n",a1);
printf(" Bob's private number b1: %lld\n",b1);
printf("Computed data sent across the channel (Eve can see it):\n");
printf(" Alice's public number a2: %lld\n",a2);
printf(" Bob's public number b2: %lld\n",b2);
printf("Computed private data (never sent)\n");
printf(" Alice's computed key a3: %lld\n",a3);
printf(" Bob's computed key b3: %lld\n",b3);
printf("Notes:\n");
printf("1. Alice and Bob can now communicate privately using\n");
printf(" computed symmetric key %lld to encrypt/decrpyt\n",a3);
printf("2. If this exchange was encrypted it would be even more secure\n");
}
//----------------------------------------------------------------------------
// my fgets (read a string;
// don't overflow the variable; don't store trailing paper command)
//----------------------------------------------------------------------------
void nsr_fgets(char* a, int b, FILE* c) {
int x;
fgets(a,b,c); //
x = strlen(a); //
switch (a[x-1]) { //
case '\r': // carriage return
case '\n': // line-feed
a[x-1] = '\0'; //
default: //
} //
} //
//----------------------------------------------------------------------------
// remove trailing white space
//----------------------------------------------------------------------------
void remove_trailing_ws(char* a) {
int x = strlen(a); //
loop: //
if (x==0) return; //
switch (a[x-1]) { // test last character
case '\r': // carriage return
case '\n': // line-feed
case '\t': // tab
a[x-1] = '\0'; //
x--; //
goto loop; // c-programmers horrified
default: //
return; //
} //
} //