OpenSSL之Diffie-Hellman

// diffie_hellman.hpp
#pragma once
#include <openssl/dh.h>
#include <memory>
#include <vector>

namespace crypto {
    
    
	class diffie_hellman {
    
    
	public:
		diffie_hellman();
		~diffie_hellman() = default;

		bool create_p_g();
		bool set_p_g(const std::vector<std::uint8_t>& p, const std::vector<std::uint8_t>& g);

		std::vector<std::uint8_t> get_shared_p() const;
		std::vector<std::uint8_t> get_shared_g() const;
		std::vector<std::uint8_t> get_pub_key() const;
		std::vector<std::uint8_t> get_pri_key(const std::vector<std::uint8_t>& pub_key) const;

	private:
		std::unique_ptr<DH, decltype(&DH_free)> dh_;
	};
}

// diffie_hellman.cpp
#include "diffie_hellman.hpp"
#include <openssl/bn.h>

namespace crypto {
    
    
	namespace {
    
    
		std::vector<std::uint8_t> bignum_to_bytes(const BIGNUM* bn) {
    
    
			std::vector<std::uint8_t> result(BN_num_bytes(bn));
			BN_bn2bin(bn, result.data());

			return result;
		}

		std::unique_ptr<BIGNUM, decltype(&BN_free)> bytes_to_big_num(const std::vector<std::uint8_t>& uint8_ts) {
    
    
			return std::unique_ptr<BIGNUM, decltype(&BN_free)>{
    
     BN_bin2bn(uint8_ts.data(), uint8_ts.size(), nullptr), &BN_free };
		}
	}


	diffie_hellman::diffie_hellman() : dh_ {
    
     DH_new(), & DH_free } {
    
    
	}

	bool diffie_hellman::create_p_g() {
    
    
		constexpr int key_bits{
    
     512 };

		if (DH_generate_parameters_ex(dh_.get(), key_bits, DH_GENERATOR_2, nullptr) != 1)  {
    
    
			return false;
		}
		return DH_generate_key(dh_.get()) == 1;
	}

	bool diffie_hellman::set_p_g(const std::vector<std::uint8_t>& p, const std::vector<std::uint8_t>& g) {
    
    
		auto p_bn = BN_bin2bn(p.data(), p.size(), nullptr);
		auto g_bn = BN_bin2bn(g.data(), g.size(), nullptr);

		if (DH_set0_pqg(dh_.get(), p_bn, nullptr, g_bn) != 1) {
    
    
			return false;
		}
		return DH_generate_key(dh_.get()) == 1;
	}

	std::vector<std::uint8_t> diffie_hellman::get_shared_p() const {
    
    
		return bignum_to_bytes(DH_get0_p(dh_.get()));
	}

	std::vector<std::uint8_t> diffie_hellman::get_shared_g() const {
    
    
		return bignum_to_bytes(DH_get0_g(dh_.get()));
	}

	std::vector<std::uint8_t> diffie_hellman::get_pub_key() const {
    
    
		return bignum_to_bytes(DH_get0_pub_key(dh_.get()));
	}


	std::vector<std::uint8_t> diffie_hellman::get_pri_key(const std::vector<std::uint8_t>& pub_key) const {
    
    
		auto pub_key_bn{
    
     bytes_to_big_num(pub_key) };

		std::vector<std::uint8_t> result(DH_size(dh_.get()));
		const int ret = DH_compute_key(result.data(), pub_key_bn.get(), dh_.get());

		return ret < 0 ? std::vector<std::uint8_t>{
    
    } : result;
	}
}

// main.cpp
#include "diffie_hellman.hpp"
#include <cassert>

int main()
{
    
    
	crypto::diffie_hellman request;
	assert(request.create_p_g());
	auto p = request.get_shared_p();
	auto g = request.get_shared_g();
	auto&& pubkey_of_request = request.get_pub_key();

	crypto::diffie_hellman response;
	assert(response.set_p_g(p, g));
	auto&& pubkey_of_response = response.get_pub_key();

	auto&& key1 = request.get_pri_key(pubkey_of_response);
	auto&& key2 = response.get_pri_key(pubkey_of_request);

	assert(key1 == key2);

	return 0;
}

猜你喜欢

转载自blog.csdn.net/kpengk/article/details/121620934
今日推荐