Diffie-Hellman算法
2017-10-20 本文已影响0人
flycloud_hz
0x0 Diffie-Hellman介绍
Diffie-Hellman简称DH算法,用于密钥交换,两端使用相同p,g参数,生成一对公私钥,一端私钥和另一端公钥生成一个key(prime_len参数为key的字节 * 8,比如key需要24个字节,那么prime_len为192),key可以作为AES密钥做加解密。
0x1 代码实现
生成的key为24字节,可以作为AES 192bits key
h文件
class DHCrypt {
public:
DHCrypt();
~DHCrypt();
public:
bool Init();
std::string getP();
std::string getG();
std::string getPubKey();
bool ComputeKey(const std::string& input, std::string& output);
private:
bool initialized_;
DH* dh_;
std::string param_p_;
std::string param_g_;
std::string public_key_;
};
cpp文件
DHCrypt::DHCrypt()
: initialized_(false), dh_(NULL){
}
DHCrypt::~DHCrypt() {
if (dh_) {
DH_free(dh_);
dh_ = NULL;
}
}
bool DHCrypt::Init() {
if (initialized_) {
LOGE("init already done");
return true;
}
dh_ = DH_new();
if (dh_&& DH_generate_parameters_ex(dh_, 192, DH_GENERATOR_2, NULL) != 0) {
const BIGNUM* p = NULL;
const BIGNUM* g = NULL;
DH_get0_pqg(dh_, &p, NULL, &g);
if (p) {
int len = BN_num_bytes(p);
unsigned char* buf = new unsigned char[len];
int l = BN_bn2bin(p, buf);
param_p_ = std::string((char*)buf, l);
delete[] buf;
}
if (g) {
int len = BN_num_bytes(g);
unsigned char* buf = new unsigned char[len];
int l = BN_bn2bin(g, buf);
param_g_ = std::string((char*)buf, l);
delete[] buf;
}
if (DH_generate_key(dh_) != 0) {
const BIGNUM* pub_key = NULL;
const BIGNUM* pri_key = NULL;
DH_get0_key(dh_, &pub_key, &pri_key);
if (pub_key) {
int len = BN_num_bytes(pub_key);
unsigned char* buf = new unsigned char[len];
int l = BN_bn2bin(pub_key, buf);
public_key_ = std::string((char*)buf, l);
delete[] buf;
}
}
initialized_ = true;
} else {
LOGE("DH_generate_parameters_ex error");
}
return initialized_;
}
std::string DHCrypt::getP() {
return param_p_;
}
std::string DHCrypt::getG() {
return param_g_;
}
std::string DHCrypt::getPubKey() {
return public_key_;
}
bool DHCrypt::ComputeKey(const std::string& input, std::string& output) {
if (!initialized_) {
LOGE("init not done");
return false;
}
bool result = false;
if (dh_) {
int size = DH_size(dh_);
unsigned char* buf = (unsigned char*)OPENSSL_malloc(size);
if (buf) {
BIGNUM* bn = BN_bin2bn((const unsigned char*)input.c_str(), input.length(), NULL);
if (bn) {
int len = DH_compute_key(buf, bn, dh_);
if (len > 0) {
output = std::string((char*)buf, len);
result = true;
} else {
LOGE("DH_compute_key error");
}
BN_free(bn);
} else {
LOGE("BN_bin2bn error");
}
OPENSSL_free(buf);
}
}
return result;
}