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