/* dhtest - Diffie-Hellman key exchange ** ** To build: ** cc -Wall -I/usr/local/include dhtest.c -s -L/usr/local/lib -lcrypto -o dhtest ** ** To use: ** ** Choose a modulus p and a base g. p should be a large prime number, ** say 2048 bits. g should be a primitive root modulo p, which is ** a complicated topic but it's fine to use: 2. Distribute p and g ** to the client and the server. ** ** Do the first phase on the client side: ** dhtest -1 p g ** This gives you two numbers, a and A. Keep a and send A to the ** server side. ** ** Do the second phase on the server side: ** dhtest -2 p g A ** This gives you two numbers, B and s. s is the shared secret. ** Send B back to the client side. ** ** Do the third phase on the client side, using the number you ** saved from the first phase: ** dhtest -3 p g a B ** This gives you s, the shared secret, on the client side too. ** ** This all runs pretty fast. On my system with a 2048-bit modulus, ** each phase takes about 0.05 seconds. ** ** ** Copyright © 2016 by Jef Poskanzer . ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions ** are met: ** 1. Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** 2. Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in the ** documentation and/or other materials provided with the distribution. ** ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. ** ** For commentary on this license please see http://acme.com/license.html */ #include #include #include #include #include static char* argv0; static void usage( void ); int main( int argc, char** argv ) { int phase; BN_CTX* ctx; BIGNUM* p; BIGNUM* g; BIGNUM* littlea; BIGNUM* bigA; BIGNUM* littleb; BIGNUM* bigB; BIGNUM* s; /* Figure out the program's name. */ argv0 = strrchr( argv[0], '/' ); if ( argv0 != (char*) 0 ) ++argv0; else argv0 = argv[0]; ctx = BN_CTX_new(); p = BN_new(); g = BN_new(); littlea = BN_new(); bigA = BN_new(); littleb = BN_new(); bigB = BN_new(); s = BN_new(); if ( argc < 4 ) usage(); phase = - atoi( argv[1] ); BN_dec2bn( &p, argv[2] ); BN_dec2bn( &g, argv[3] ); switch ( phase ) { case 1: if ( argc != 4 ) usage(); BN_rand_range( littlea, p ); (void) printf( "a = %s\n", BN_bn2dec( littlea ) ); BN_mod_exp( bigA, g, littlea, p, ctx ); (void) printf( "A = %s\n", BN_bn2dec( bigA ) ); break; case 2: if ( argc != 5 ) usage(); BN_dec2bn( &bigA, argv[4] ); BN_rand_range( littleb, p ); BN_mod_exp( bigB, g, littleb, p, ctx ); (void) printf( "B = %s\n", BN_bn2dec( bigB ) ); BN_mod_exp( s, bigA, littleb, p, ctx ); (void) printf( "s = %s\n", BN_bn2dec( s ) ); break; case 3: if ( argc != 6 ) usage(); BN_dec2bn( &littlea, argv[4] ); BN_dec2bn( &bigB, argv[5] ); BN_mod_exp( s, bigB, littlea, p, ctx ); (void) printf( "s = %s\n", BN_bn2dec( s ) ); break; default: usage(); } BN_free( p ); BN_free( g ); BN_free( littlea ); BN_free( bigA ); BN_free( littleb ); BN_free( bigB ); BN_free( s ); BN_CTX_free(ctx); exit( EX_OK ); } static void usage( void ) { (void) fprintf( stderr, "usage: %s -1

\n", argv0 ); (void) fprintf( stderr, " %s -2

\n", argv0 ); (void) fprintf( stderr, " %s -3

\n", argv0 ); exit( EX_USAGE ); }