2011年7月27日 星期三

[C++] Diffie-Hellman Key Exchange (Client API)

DHKeyCrypt.h


#if !defined(dhkeycrypt_include)

#define dhkeycrypt_include

#include
#include
#include

/*
* Example:
*
* // initial steps
* const char *p, *g, *public_key;
* char *buf;
* int buf_size;
* DHKeyCrypt *key = new DHKeyCrypt(256); // mean generate 256 bits prime
*
* // p, g, public_key will point to the hex representation string
* key->GenerateKey(&p, &g, &public_key);
*
* // use the 3rd party public key to compute session key
* key->ComputeKey(other_pubkey);
*
* // usage
* key->Encode(buf, buf_size); // encode buf
*
*/
class DHKeyCrypt
{
private:
char *m_g[2];
DH *m_dh;
char *m_p;
char *m_pubkey;
unsigned char *m_session_key;

int m_key_len;
int m_gindex;

public:
DHKeyCrypt(int size);
void GenerateKey(const char **p, const char **g, const char **public_key);
int ComputeKey(const char *pubkey_3rd);
void Encode(char *buf, int buf_len);
~DHKeyCrypt();
};

#endif

DHKeyCrypt.cpp


#include "DHKeyCrypt.h"
#include
#include

/*
* generate size bits prime
*/
DHKeyCrypt::DHKeyCrypt(int size) : m_session_key(NULL)
{
m_g[0] = strdup("2");
m_g[1] = strdup("5");
m_gindex = time(NULL) & 1;
m_dh = DH_generate_parameters(size, m_g[m_gindex][0] - '0', NULL, NULL);
DH_generate_key(m_dh);
m_p = BN_bn2hex(m_dh->p);
m_pubkey = BN_bn2hex(m_dh->pub_key);
}

void DHKeyCrypt::GenerateKey(const char **p, const char **g, const char **public_key)
{
*p = m_p;
*g = m_g[m_gindex];
*public_key = m_pubkey;
}

int DHKeyCrypt::ComputeKey(const char *pubkey_3rd)
{
BIGNUM *bn = NULL;

if(!BN_hex2bn(&bn, pubkey_3rd))
return -1;
m_session_key = new (std::nothrow) unsigned char [DH_size(m_dh)];
if(!m_session_key) return -1;
m_key_len = DH_compute_key(m_session_key, bn, m_dh);
if(m_key_len == -1) return -1;
/*
printf("SessionKey: ");
for(int i=0; i < m_key_len; i++)
printf("%02X", m_session_key[i]);
printf("\n");
*/
return 0;
}

void DHKeyCrypt::Encode(char *buf, int buf_len)
{
for(int i=0; i < buf_len; i++)
buf[i] = buf[i] ^ m_session_key[i % m_key_len];
}

DHKeyCrypt::~DHKeyCrypt()
{
OPENSSL_free(m_p);
OPENSSL_free(m_pubkey);
free(m_g[0]);
free(m_g[1]);
delete [] m_session_key;
DH_free(m_dh);
}