Skip to content

Instantly share code, notes, and snippets.

@SysMan-One
Created November 7, 2019 10:41
Show Gist options
  • Save SysMan-One/099a60c22be7c4648f019cc9b30a8a1b to your computer and use it in GitHub Desktop.
Save SysMan-One/099a60c22be7c4648f019cc9b30a8a1b to your computer and use it in GitHub Desktop.
#define __MODULE__ "DHEXMPL"
#define __IDENT__ "X.00-01"
#ifdef __GNUC__
#ident __IDENT__
#endif
#pragma GCC diagnostic ignored "-Wparentheses"
#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
#pragma GCC diagnostic ignored "-Wmissing-braces"
#pragma GCC diagnostic ignored "-Wfdollars-in-identifiers"
/*
**++
**
** FACILITY: An example of Anonimous Diffie-Hellman
**
** ABSTRACT: An example of building encrypted channel by using keys' interchange base on Anonimpus Diffie-Hellman
** alghorytm
**
** DESCRIPTION:
**
**
** DESIGN ISSUE:
**
** Сервер Клиент
------------------------------------------------------------------------------------------------
Генерация p, q (не используется), g
PrivKserver - случайное число заданной длины (160 битов, то есть достаточно длинное)
PubKserver = f(PrivKserver, p, g)
PubKserver = (g^PrivKserver) mod p
----->>>> p, g, PubKserver
------------------------------------------------------------------------------
PrivKclient - как-то генерируется
PubKclient = f (p, g, PrivKclient)
PubKclient = (g^PrivKclient) mod p
SesssionKey = f(PubKserver, PrivKclient)
SesssionKey = PubKserver ^ PrivKclient
<<<<----- PubKclient
------------------------------------------------------------------------------------------------
SesssionKey = f(PrivKserver, PubKclient)
SesssionKey = PubKclient ^ PrivKserver
------------------------------------------------------------------------------------------------
обмен данными
GOST89
**
** AUTHORS: Ruslan R. Laishev (RRL)
**
** CREATION DATE: 05-NOV-2019
**
** USAGE:
**
** MODIFICATION HISTORY:
**
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <openssl/dh.h>
#include <openssl/bn.h>
#ifdef __x86_64__
#define __ARCH__NAME__ "x86_64"
#else
#ifdef __i386
#define __ARCH__NAME__ "i386"
#endif
#endif
#ifdef _WIN64
#define __ARCH__NAME__ "Win64"
#elifdef _WIN32
#define __ARCH__NAME__ "Win32"
#endif
/*
* Defines and includes for enable extend trace and logging
*/
#define __FAC__ "DHEXMPL"
#define __TFAC__ __FAC__ ": "
#include "utility_routines.h"
#define $SHOW_PTR(var) $SHOW_PARM(var, var, "%p")
#define $SHOW_STR(var) $SHOW_PARM(var, (var ? var : "UNDEF(NULL)"), "'%s'")
#define $SHOW_INT(var) $SHOW_PARM(var, ((int) var), "%d")
#define $SHOW_UINT(var) $SHOW_PARM(var, ((unsigned) var), "%u")
#define $SHOW_ULL(var) $SHOW_PARM(var, ((unsigned long long) var), "%llu")
#define $SHOW_UNSIGNED(var) $SHOW_PARM(var, var, "0x%08x")
#define $SHOW_BOOL(var) $SHOW_PARM(var, (var ? "ENABLED(TRUE)" : "DISABLED(FALSE)"), "%s");
typedef struct __rnd_seed__
{
struct timespec ts;
pid_t pid;
struct timespec ts2;
} RND_SEED;
#define DH$SZ_PRIME (20*8) /* 640 bits */
static int __dh_server_init (
BIGNUM *a,
BIGNUM *p,
BIGNUM *g,
BIGNUM *A
)
{
int status = STS$K_ERROR, rc, count;
BIGNUM *q, *h, *bn_res, *bn_gexp, *bn_minusone, *bn_one;
BN_CTX *bn_ctx; /* used internally by the bignum lib */
RND_SEED rnd_seed;
char errbuf[512];
/* Initialize context for random seeding */
if ( rc = clock_gettime(CLOCK_MONOTONIC, &rnd_seed.ts) )
return $LOG(STS$K_ERROR, "clock_gettime()->%d, errno=%d", rc, errno);
if ( rc = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &rnd_seed.ts2) )
return $LOG(STS$K_ERROR, "clock_gettime()->%d, errno=%d", status, errno);
rnd_seed.pid = getpid();
/* Performs random seeding or BN_generate_prime_ex may fail */
rc = RAND_seed(&rnd_seed, sizeof (rnd_seed) );
bn_ctx = BN_CTX_new();
/* Allocate area for bignumbers */
q = BN_new();
h = BN_new();
bn_res = BN_new();
bn_gexp = BN_new();
bn_minusone = BN_new(); BN_set_word (bn_minusone, -1);
bn_one = BN_new(); BN_set_word (bn_one, 1);
/* Generate p and g ... */
for (count = 0; ++count; )
{
// Calculate "p" = 2q + 1
if ( !(status = BN_generate_prime_ex (q, DH$SZ_PRIME, 1 /* safe */, NULL, NULL, NULL)) )
{
ERR_print_errors_fp(stdout);
break;
}
//$TRACE("q : %s", BN_bn2hex (q));
BN_lshift1(p, q); // p = p * 2
BN_add(p, p, bn_one); // p = p - 1
//$TRACE("p : %s", BN_bn2hex (p));
// 1: gExp = (p - 1) / q
// 2: h => 1 < h < (p - 1)
// 3: g = h^gExp mod p
BN_sub (bn_res, p, bn_minusone); // bn_res = p - 1
BN_div(bn_gexp, NULL, bn_res /*bn_res = p - 1 */, q, bn_ctx); // 1: gExp = (p - 1) / q
BN_pseudo_rand_range(h, bn_res /*bn_res = p - 1 */); // 2: h => 1 < h < (p - 1)
BN_mod_exp(g, h, bn_gexp, p, bn_ctx); // 3: g = h^gExp mod p
BN_mod_exp(bn_res, g, q, p, bn_ctx); // g^q mod p = 1, or it should
if ( (status = (!BN_is_one (bn_res))) )
break;
}
/* Generate private key random prime ... */
if ( !(status = BN_generate_prime_ex (a, DH$SZ_PRIME, 1 /* safe */, NULL, NULL, NULL)) )
ERR_print_errors_fp(stdout);
/* Compute publick key as : A("publick key") = g ^ a mod p */
BN_mod_exp(A, g, a, p, bn_ctx);
/* Release has been allocated resource unconditionaly */
BN_CTX_free(bn_ctx);
BN_free(h);
BN_free(bn_res);
BN_free(bn_gexp);
BN_free(bn_minusone);
BN_free(bn_one);
return status;
}
static int __dh_client_init (
BIGNUM *b,
BIGNUM *p,
BIGNUM *g,
BIGNUM *B
)
{
int status = STS$K_ERROR, rc;
BN_CTX *bn_ctx; /* used internally by the bignum lib */
RND_SEED rnd_seed;
char errbuf[512];
/* Initialize context for random seeding */
if ( rc = clock_gettime(CLOCK_MONOTONIC, &rnd_seed.ts) )
return $LOG(STS$K_ERROR, "clock_gettime()->%d, errno=%d", rc, errno);
if ( rc = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &rnd_seed.ts2) )
return $LOG(STS$K_ERROR, "clock_gettime()->%d, errno=%d", status, errno);
rnd_seed.pid = getpid();
/* Performs random seeding or BN_generate_prime_ex may fail */
RAND_seed(&rnd_seed, sizeof (rnd_seed) );
/* Generate private key random prime ... */
if ( !(status = BN_generate_prime_ex (b, DH$SZ_PRIME, 1 /* safe */, NULL, NULL, NULL)) )
ERR_print_errors_fp(stdout);
/* Compute publick key as : A("publick key") = g ^ a mod p */
bn_ctx = BN_CTX_new();
BN_mod_exp(B, g, b, p, bn_ctx);
BN_CTX_free(bn_ctx);
return status;
}
static int __dh_session_key(
BIGNUM *pubk,
BIGNUM *privk,
BIGNUM *p,
BIGNUM *skey
)
{
int status = STS$K_ERROR, rc;
BN_CTX *bn_ctx; /* used internally by the bignum lib */
/* Compute session key as: Session Key = PublickKey ^ PrivateKey mod p */
bn_ctx = BN_CTX_new();
BN_mod_exp(skey, pubk, privk, p, bn_ctx);
BN_CTX_free(bn_ctx);
}
int main (int argc, char **argv)
{
int status, rc;
char errbuf[512];
BIGNUM *cprivk, *cpubk, *sprivk, *spubk, *sskey, *cskey, *p, *g;
BN_CTX *bn_ctx; /* used internally by the bignum lib */
$LOG(STS$K_INFO, "Server context initialization ...");
p = BN_new();
g = BN_new();
sprivk = BN_new();
spubk = BN_new();
__dh_server_init(sprivk, p, g, spubk);
$LOG(STS$K_INFO, "Public p : %s", BN_bn2hex (p));
$LOG(STS$K_INFO, "Public g : %s", BN_bn2hex (g));
$LOG(STS$K_INFO, "Server DH private key: %s", BN_bn2hex (sprivk));
$LOG(STS$K_INFO, "Server DH public key : %s", BN_bn2hex (spubk));
/*
* Send to client: p, g, Server's publick key
* .....
*/
/* Generate client's keys with has been given from server: A (erver's public key), p, g */
$LOG(STS$K_INFO, "Client context initialization, input data (has been gotten from server) :");
$LOG(STS$K_INFO, "\tPublic p : %s", BN_bn2hex (p));
$LOG(STS$K_INFO, "\tPublic g : %s", BN_bn2hex (g));
$LOG(STS$K_INFO, "\tServer DH public key : %s", BN_bn2hex (spubk));
cprivk = BN_new();
cpubk = BN_new();
__dh_client_init(cprivk, p, g, cpubk);
$LOG(STS$K_INFO, "Client DH private key: %s", BN_bn2hex (sprivk));
$LOG(STS$K_INFO, "Client DH public key : %s", BN_bn2hex (spubk));
/* Compute Session key at server and client sides */
$LOG(STS$K_INFO, "Session keys generation ...");
sskey = BN_new();
cskey = BN_new();
__dh_session_key (cpubk, sprivk, p, sskey);
$LOG(STS$K_INFO, "Server DH session key: %s", BN_bn2hex (sskey));
__dh_session_key (spubk, cprivk, p, cskey);
$LOG(STS$K_INFO, "Client DH session key: %s", BN_bn2hex (cskey));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment