Created
January 23, 2021 08:37
-
-
Save digitalhuman/2a2b85d61672e4bf83596d41351723ba to your computer and use it in GitHub Desktop.
Visual Studio 2019 C/C++ Diffie and Hellman key exchange with PHP 7
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
#pragma warning(disable : 4996) | |
#include <stdio.h> | |
#include <iostream> | |
#include <string> | |
#include <sstream> | |
#include "openssl/dh.h" | |
#include "openssl/bn.h" | |
#include "openssl/pem.h"; | |
using namespace std; | |
DH *dhp = NULL; | |
static const std::string base64_chars = | |
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |
"abcdefghijklmnopqrstuvwxyz" | |
"0123456789+/"; | |
static inline bool is_base64(unsigned char c) { | |
return (isalnum(c) || (c == '+') || (c == '/')); | |
} | |
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) { | |
std::string ret; | |
int i = 0; | |
int j = 0; | |
unsigned char char_array_3[3]; | |
unsigned char char_array_4[4]; | |
while (in_len--) { | |
char_array_3[i++] = *(bytes_to_encode++); | |
if (i == 3) { | |
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; | |
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); | |
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); | |
char_array_4[3] = char_array_3[2] & 0x3f; | |
for (i = 0; (i < 4); i++) | |
ret += base64_chars[char_array_4[i]]; | |
i = 0; | |
} | |
} | |
if (i) | |
{ | |
for (j = i; j < 3; j++) | |
char_array_3[j] = '\0'; | |
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; | |
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); | |
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); | |
char_array_4[3] = char_array_3[2] & 0x3f; | |
for (j = 0; (j < i + 1); j++) | |
ret += base64_chars[char_array_4[j]]; | |
while ((i++ < 3)) | |
ret += '='; | |
} | |
return ret; | |
} | |
std::string base64_decode(std::string const& encoded_string) { | |
int in_len = encoded_string.size(); | |
int i = 0; | |
int j = 0; | |
int in_ = 0; | |
unsigned char char_array_4[4], char_array_3[3]; | |
std::string ret; | |
while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { | |
char_array_4[i++] = encoded_string[in_]; in_++; | |
if (i == 4) { | |
for (i = 0; i < 4; i++) | |
char_array_4[i] = base64_chars.find(char_array_4[i]); | |
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); | |
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); | |
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; | |
for (i = 0; (i < 3); i++) | |
ret += char_array_3[i]; | |
i = 0; | |
} | |
} | |
if (i) { | |
for (j = i; j < 4; j++) | |
char_array_4[j] = 0; | |
for (j = 0; j < 4; j++) | |
char_array_4[j] = base64_chars.find(char_array_4[j]); | |
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); | |
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); | |
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; | |
for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; | |
} | |
return ret; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
BIGNUM* priv_key = NULL; | |
BIGNUM* apub_key = NULL; | |
BIGNUM* p = NULL; | |
BIGNUM* g = NULL; | |
std::string userPubKey; | |
std::string prime; | |
std::string generator; | |
if (argc < 6) { | |
printf("%s", "Missing parameters: -p, -key -g"); | |
return -1; | |
} | |
//Process parameters | |
int count; | |
for (count = 1; count < argc; count+=2) | |
{ | |
std::string param = (string)argv[count]; | |
if (strcmpi(param.c_str(), "-p") == 0) { | |
prime = (string)argv[count+1]; | |
} | |
else if (strcmpi(param.c_str(), "-key") == 0) { | |
userPubKey = (string)argv[count + 1]; | |
} | |
else if (strcmpi(param.c_str(), "-g") == 0) { | |
generator = (string)argv[count+1]; | |
} | |
} | |
//Set public key of remote User | |
BN_hex2bn(&apub_key, userPubKey.c_str()); | |
DH *dhp = DH_new(); | |
if (dhp == NULL) { | |
return -1; | |
} | |
//Set Prime and Generator | |
BN_hex2bn(&p, prime.c_str()); | |
BN_dec2bn(&g, generator.c_str()); | |
DH_set0_pqg(dhp, p, NULL, g); | |
if (DH_generate_key(dhp) != 1) { | |
printf("%s", "Error generating keys."); | |
return -1; | |
} | |
//Print Public Key as Hex | |
const BIGNUM* exportPublic = DH_get0_pub_key(dhp); | |
printf("Public Key: %s\r\n", BN_bn2hex(exportPublic)); | |
//Print Private Key as Hex | |
const BIGNUM* exportPrivate = DH_get0_priv_key(dhp); | |
printf("Private Key: %s\r\n", BN_bn2hex(exportPrivate)); | |
//Calculate secret | |
char buf[256] = { 0 }; | |
unsigned char* abuf = NULL; | |
int alen = DH_size(dhp); | |
abuf = (unsigned char*)OPENSSL_malloc(alen); | |
int aout = DH_compute_key(abuf, apub_key, dhp); | |
printf("\r\nThe shared secret is:\r\n"); | |
std::string encoded = base64_encode(abuf, aout); | |
printf("%s\r\n", encoded.c_str()); | |
DH_free(dhp); | |
p = NULL; | |
g = NULL; | |
abuf = NULL; | |
} |
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
<?php | |
//This is our private key | |
$myPrivate = '-----BEGIN PRIVATE KEY----- | |
MIICJgIBADCCARcGCSqGSIb3DQEDATCCAQgCggEBANn6weB11zG7izhfzM4qsITZ | |
3q/ORkF6+h3RTn7sh8Ji1MpHt3zHcPfdYFvs7V5SJfNN5Xv9L62RN8GwgxwRWIJr | |
8VBHfL3LyZNMMgnGBGJR0qmoM48iNd8i2ggZYj+H8WVh2y6tGw1YsDI3AFHpZFkN | |
TvCT1JHl2JfNEgOgSryBO84KDEWLxWaN/4Nqa9x5R0fxKMLjpWNRzEBBKcVeEHIZ | |
gzl7VKVJEpYC336sjYJE19ZD0O/gWl+q4WeRpDazDi6LDLZgnoDrUgbNAXtDETKL | |
gKOnYq+iwRWCQicQmaQvGXntmgdriExVacrRnH8o09ioxcVdtPG8WuLeqJczCvsC | |
AQIEggEEAoIBAH1yv00aZkw/7IIAJL1fZUrpVeO3xKIQDl982HOKS32+o2mUJWbc | |
DuDMIOvqiUEltEnFQOqDaJue0ucseJdH5Q9JHlSIhuUQiPB/JfEcPlb2QYzXHuAE | |
fWS94X0wiSxYgKXIL0XceA3yg5bYhDSR3DntdJrbboyYHt/QGQ8WCWiYEa402ovI | |
x+r7k3BlGxah33HeuqhMCFAfFvWUhLaj85QEmjHTjVMKeeTlNfBS+nscbCcZvLXd | |
qanvRxYYGdOhgLTcJe/iUsxmAWVTiqrid8MEvtFrenanawTgnPXAp5WtYTCGcsiQ | |
TBG24ND/tnZpPoPz/Rwlpo1IL4IbvKGRsfU= | |
-----END PRIVATE KEY-----'; | |
//Copy/paste Public Key from C/C++ application below (hex format) | |
$remotePublic = hex2bin("29ECC536A85A4AFAD7D63E50545C68CE44A834396886E9A7BAC27E3A08A14C05259BA6E9940FDC512457155A60CAFACD8E43897E1B537A282D39697B75357197B5E3AD7F1826C0216604496AFAEF8999FBCE336C148166AE23E77EC66C0611235110FA8D6180A26425154959FACEC18FEE3EDA68E9355627820C14B44B486C9547ECE62BE72D56A7FAC4747AFCF201D8A4155F63A076234D6BC04DE27E7A7849BF8956E3DB6E51C043CB6FC66889ADE1F8DE756E9194838E8EF8A5CF9C0DD553282DE8A3130CA7752C22C191E5C352AC3BD77EF9270BF37BC807BBDB3F39AE7966B013723E71EAF41082A056D994F64B428183C5BAFEE9C7A41CABCEA868FC34"); | |
$pkey = openssl_get_privatekey($myPrivate); | |
$privateKeyInfo = openssl_pkey_get_details($pkey); | |
//Use this Public Key Hex output, as -key parameter in C/C++ application | |
echo "My public Key (hex):\r\n<br/>"; | |
echo bin2hex($privateKeyInfo["dh"]["pub_key"]); | |
echo "<br/><br/>"; | |
echo "Remote public Key (hex):\r\n<br/>"; | |
echo bin2hex($remotePublic); | |
echo "<br/><br/>"; | |
echo "My Shared Secret (hex):\r\n<br/>".DH::create_shared_secret($remotePublic, $pkey); | |
echo "<br/><br/>"; | |
echo "Remote Shared Secret (hex):\r\n<br/>"; | |
//Copy/paste base64 encoded shared secret from C/C++ application below for validation | |
echo bin2hex(base64_decode("sASZRPpdNvNk3QLmdd3lD4wtZ0gcXPD+LySNOD7sHTjCPV7SZE++8mdrzWzhSDYcqCYZyPk+EFBsuJ0KG9qg8LxvaM7w98ttl9Q+jdo8elxamOvSNCpgXOUw/UagYC0o1K/EjpIIjQvEIZTKhoKoUxf4Etgbhs0oTu1AXfL3aq6EzNVghW6KPQzk9ZE5S8oC64oZhOu0G7GXFPuLV5vK/TapBR1R0HX2YimJMonYoMkYv9Ii8XgDzFMtLPk7sqVnlTMjykCb6zI3+q6cb9/GcVlDJJU7rdB91HcO4J/Rn5AEVlTFcJ6SqmFLg1lML2KovDx+eG5UvBJZoKc3xw3UzA==")); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment