存档

文章标签 ‘DHE’

使用 openssl 进行 DH 密钥交换

2019/01/19 8,475

在我之前的博客中聊到了 DH 密钥交换的原理 . 这里来讨论如何使用 OPENSSL 进行 DH 密钥交换。

一 原理验证

OPENSSL 提供了一系列API, 可以在方便地进行大数计算。在这里我们先对 DH 密钥交换的原理 中讲到的原理进行代码级别的验证。对原理不感兴趣的可以跳过这一小节。
由于在 DH 密钥交换过程中,大部分的操作过程都是一样的,可以定义一个基类来抽象:

class DHBase {
public:
    DHBase() : m_pri_key(NULL) {}

    virtual ~DHBase() {
        if (m_pri_key)
            BN_free(m_pri_key);
    };

    const BIGNUM *GetSharedNum() {
        if (!m_pri_key)
            GenRandomData();

        BN_CTX *ctx = BN_CTX_new();
        const BIGNUM *g = DH_get0_g(m_dh);
        const BIGNUM *p = DH_get0_p(m_dh);
        BIGNUM *r = BN_new();

        // r = g ^ m_pri_key % p
        int rst = BN_mod_exp(r, g, m_pri_key, p, ctx);
        assert(rst == 1);
        BN_CTX_free(ctx);
        return r;
    }

    BIGNUM *GenKey(const BIGNUM *shared_num) {
        if (!m_pri_key)
            GenRandomData();

        BIGNUM *key = BN_new();
        BN_CTX *ctx = BN_CTX_new();

        // key = shared_num ^ m_pri_key % p
        int rst = BN_mod_exp(key, shared_num, m_pri_key, DH_get0_p(m_dh), ctx);
        assert(rst == 1);
        BN_CTX_free(ctx);

        std::cout << m_name << ": received shared num: " << GetNumString(shared_num) << std::endl;
        std::cout << m_name << ": generated KEY: " << GetNumString(key) << std::endl;
        return key;
    }

    std::string GetName() {
        return m_name;
    }

    static std::string GetNumString(const BIGNUM *num) {
        return BN_bn2hex(num);
    }

private:
    void GenRandomData() {
        assert(m_dh);
        m_pri_key = BN_new();
        int rst = BN_rand_range(m_pri_key, DH_get0_p(m_dh));
        assert(rst == 1);
        while (BN_is_zero(m_pri_key)) {
            BN_rand_range(m_pri_key, DH_get0_p(m_dh));
        }
        std::cout << m_name << ": generated the private num" << std::endl;
    }

protected:
    DH *m_dh;
    std::string m_name;

private:
    BIGNUM *m_pri_key;
};
  • m_pri_key 是双方生成的私密随机数。
  • GetSharedNum() 返回双方交换的中间变量 G^A mod P
  • GenKey() 即完成了密钥交换,返回交换成功后的密钥。

继续阅读