OpenVMS Source-Code Demos

DIFFIE_HELLMAN_DEMO_IN_C

//============================================================================
// title     : diffie_hellman_demo_in_c_xxx.c
// author    : Neil Rieck (http://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 will be horrified by this :-)
	    default:							//
		return;							//
    }									//
}									//