First commit
This commit is contained in:
commit
36983fab17
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
dh
|
191
dh.c
Normal file
191
dh.c
Normal file
@ -0,0 +1,191 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <string.h>
|
||||
#include "dh.h"
|
||||
|
||||
|
||||
// gcc -Wall -o dh dh.c -lcrypto && ./dh
|
||||
|
||||
|
||||
static int generatePrimeNumber(unsigned long long int p){
|
||||
for (int i = 2; i < p; i++){
|
||||
if ((unsigned long long int)p % i == 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static BIGNUM *generatePrivateKey(){
|
||||
BIGNUM *bn = NULL;
|
||||
char n[CHAR_SIZE];
|
||||
unsigned long long int r = rand() % (PRIVATEKEY_MAX - PRIVATEKEY_MIN) + PRIVATEKEY_MIN;
|
||||
sprintf(n, "%lld", r);
|
||||
BN_dec2bn(&bn, n);
|
||||
return bn;
|
||||
}
|
||||
static void dumpBN(const char *s, BIGNUM *bn){
|
||||
char *n = BN_bn2dec(bn);
|
||||
printf("%s: %s\n", s, n);
|
||||
OPENSSL_free(n);
|
||||
}
|
||||
static int combineKey(BIGNUM **pubKey, BIGNUM *e, BIGNUM *x, BIGNUM *bnP, BN_CTX *ctx){
|
||||
if (ctx == NULL)
|
||||
ctx = BN_CTX_new();
|
||||
|
||||
if (*pubKey == NULL)
|
||||
*pubKey = BN_new();
|
||||
|
||||
BIGNUM *exp = BN_new();
|
||||
int res = BN_exp(exp, e, x, ctx);
|
||||
|
||||
//dumpBN("publicKey", exp);
|
||||
if (res == 0){
|
||||
BN_free(exp);
|
||||
return 0;
|
||||
}
|
||||
res = BN_mod(*pubKey, exp, bnP, ctx);
|
||||
|
||||
BN_free(exp);
|
||||
return 1;
|
||||
}
|
||||
static BIGNUM *generateP(){
|
||||
BIGNUM *bnP = NULL;
|
||||
unsigned long long int p = rand() % (500 - 200) + 500;
|
||||
char nP[CHAR_SIZE];
|
||||
int res = 0;
|
||||
|
||||
// First, we need to find a prime number of p
|
||||
while (!generatePrimeNumber(p++));
|
||||
|
||||
sprintf(nP, "%lld", p);
|
||||
res = BN_dec2bn(&bnP, nP);
|
||||
if (res == 0)
|
||||
return NULL;
|
||||
return bnP;
|
||||
}
|
||||
static int charToDec(const char *s){
|
||||
int dec = 0;
|
||||
size_t l = strlen(s);
|
||||
int pos = 1;
|
||||
for (int i = 0; i < l; i++){
|
||||
dec += (s[i] - '0') * pos;
|
||||
pos *= 10;
|
||||
}
|
||||
return dec;
|
||||
}
|
||||
static BIGNUM *generateG(const char *nP){
|
||||
BIGNUM *bnG = NULL;
|
||||
char nG[CHAR_SIZE];
|
||||
int res = 0;
|
||||
int p = charToDec(nP); // Convert char* to int
|
||||
unsigned long long int g = rand() % (p - 1);
|
||||
sprintf(nG, "%lld", g);
|
||||
res = BN_dec2bn(&bnG, nG);
|
||||
if (res == 0)
|
||||
return NULL;
|
||||
return bnG;
|
||||
}
|
||||
static void cleanDH(struct bn_dh *dh){
|
||||
if (dh->bnPrivateKey != NULL)
|
||||
BN_free(dh->bnPrivateKey);
|
||||
if (dh->bnPublicKey != NULL)
|
||||
BN_free(dh->bnPublicKey);
|
||||
if (dh->bnPublicKeyPeer != NULL)
|
||||
BN_free(dh->bnPublicKeyPeer);
|
||||
if (dh->bnPublicEphemeralKey != NULL)
|
||||
BN_free(dh->bnPublicEphemeralKey);
|
||||
if (dh->ctx != NULL)
|
||||
BN_CTX_free(dh->ctx);
|
||||
}
|
||||
int main(void){
|
||||
char *nP;
|
||||
struct bn_dh dhA = {NULL};
|
||||
struct bn_dh dhB = {NULL};
|
||||
BIGNUM *bnP, *bnG = NULL;
|
||||
|
||||
// Init rand()
|
||||
srand(time(NULL));
|
||||
|
||||
// First, we need to generate p, a prime number
|
||||
bnP = generateP();
|
||||
if (bnP == NULL)
|
||||
exit(-1);
|
||||
|
||||
// Generate g, g must be between 1 and p - 1
|
||||
nP = BN_bn2dec(bnP);
|
||||
bnG = generateG(nP);
|
||||
|
||||
if (bnG == NULL){
|
||||
cleanDH(&dhA);
|
||||
cleanDH(&dhB);
|
||||
BN_free(bnP);
|
||||
exit(-1);
|
||||
}
|
||||
OPENSSL_free(nP);
|
||||
|
||||
dumpBN("p", bnP);
|
||||
dumpBN("g", bnG);
|
||||
|
||||
// We generate the private key for both A and B
|
||||
dhA.bnPrivateKey = generatePrivateKey();
|
||||
|
||||
if (dhA.bnPrivateKey == NULL){
|
||||
cleanDH(&dhA);
|
||||
cleanDH(&dhB);
|
||||
BN_free(bnP);
|
||||
BN_free(bnG);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Generate private keyB
|
||||
dhB.bnPrivateKey = generatePrivateKey();
|
||||
if (dhB.bnPrivateKey == NULL){
|
||||
cleanDH(&dhA);
|
||||
cleanDH(&dhB);
|
||||
BN_free(bnP);
|
||||
BN_free(bnG);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
dumpBN("Private keyA", dhA.bnPrivateKey);
|
||||
dumpBN("Private keyB", dhB.bnPrivateKey);
|
||||
|
||||
// We are going to combine keys
|
||||
combineKey(&dhA.bnPublicKey, bnG, dhA.bnPrivateKey, bnP, dhA.ctx);
|
||||
dumpBN("Public keyA", dhA.bnPublicKey);
|
||||
|
||||
combineKey(&dhB.bnPublicKey, bnG, dhB.bnPrivateKey, bnP, dhB.ctx);
|
||||
dumpBN("Public keyB", dhB.bnPublicKey);
|
||||
|
||||
// Send public key to the other
|
||||
dhA.bnPublicKeyPeer = BN_new();
|
||||
dhB.bnPublicKeyPeer = BN_new();
|
||||
|
||||
if(BN_copy(dhA.bnPublicKeyPeer, dhB.bnPublicKey) == NULL) {
|
||||
printf("Failed to copy the public key\n");
|
||||
cleanDH(&dhA);
|
||||
cleanDH(&dhB);
|
||||
BN_free(bnP);
|
||||
BN_free(bnG);
|
||||
}
|
||||
if(BN_copy(dhB.bnPublicKeyPeer, dhA.bnPublicKey) == NULL){
|
||||
printf("Failed to copy the public key\n");
|
||||
cleanDH(&dhA);
|
||||
cleanDH(&dhB);
|
||||
BN_free(bnP);
|
||||
BN_free(bnG);
|
||||
}
|
||||
|
||||
// For the ephemeral shared key: public keyB ** private keyA % p
|
||||
combineKey(&dhA.bnPublicEphemeralKey, dhA.bnPublicKeyPeer, dhA.bnPrivateKey, bnP, dhA.ctx);
|
||||
dumpBN("Public ephemeral keyA", dhA.bnPublicEphemeralKey);
|
||||
combineKey(&dhB.bnPublicEphemeralKey, dhB.bnPublicKeyPeer, dhB.bnPrivateKey, bnP, dhB.ctx);
|
||||
dumpBN("Public ephemeral keyB", dhB.bnPublicEphemeralKey);
|
||||
|
||||
cleanDH(&dhA);
|
||||
cleanDH(&dhB);
|
||||
BN_free(bnP);
|
||||
BN_free(bnG);
|
||||
return 0;
|
||||
}
|
24
dh.h
Normal file
24
dh.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef H_DH
|
||||
#define H_DH
|
||||
|
||||
#define CHAR_SIZE 128
|
||||
#define PRIVATEKEY_MAX 500
|
||||
#define PRIVATEKEY_MIN 100
|
||||
|
||||
struct bn_dh{
|
||||
BIGNUM *bnPrivateKey;
|
||||
BIGNUM *bnPublicKey;
|
||||
BIGNUM *bnPublicKeyPeer;
|
||||
BIGNUM *bnPublicEphemeralKey;
|
||||
BN_CTX *ctx;
|
||||
};
|
||||
static int generatePrimeNumber(unsigned long long int p);
|
||||
static BIGNUM *generatePrivateKey();
|
||||
static void dumpBN(const char *s, BIGNUM *bn);
|
||||
static int combineKey(BIGNUM **pubKey, BIGNUM *e, BIGNUM *x, BIGNUM *bnP, BN_CTX *ctx);
|
||||
static BIGNUM *generateP();
|
||||
static int charToDec(const char *s);
|
||||
static BIGNUM *generateG(const char *nP);
|
||||
static void cleanDH(struct bn_dh *dh);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user