Created
November 7, 2019 10:41
-
-
Save SysMan-One/099a60c22be7c4648f019cc9b30a8a1b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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