OpenSSL之Diffie-Hellman

互联网 2021/11/29 23:09:08

// 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::vecto…
// 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;
}
随时随地学软件编程-关注百度小程序和微信小程序
关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。
本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。
[OpenSSL之Diffie-Hellman]http://www.zyiz.net/tech/detail-263502.html

赞(0)
关注微信小程序
程序员编程王-随时随地学编程

扫描二维码或查找【程序员编程王】

可以随时随地学编程啦!

技术文章导航 更多>
扫一扫关注最新编程教程