mal-packet-weaver
C++20 packet serialization/deserialization library.
Loading...
Searching...
No Matches
diffie-hellman.hpp
Go to the documentation of this file.
1#pragma once
2
3#ifdef MAL_PACKET_WEAVER_HAS_OPENSSL
5{
10 class DiffieHellmanHelper : non_copyable_non_movable
11 {
12 public:
16 DiffieHellmanHelper()
17 {
18 EVP_PKEY_WRAPPER params;
19 {
20 EVP_PKEY_CTX_WRAPPER pkey_ctx_{ EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL) };
21 AlwaysAssert(pkey_ctx_ != nullptr, "Error generating DH parameters");
22 AlwaysAssert(EVP_PKEY_paramgen_init(pkey_ctx_.get()) == 1, "Error generating DH parameters.");
23 AlwaysAssert(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pkey_ctx_.get(), NID_X9_62_prime256v1) == 1,
24 "Error generating DH parameters.");
25 EVP_PKEY *params_val = nullptr;
26 AlwaysAssert(EVP_PKEY_paramgen(pkey_ctx_.get(), &params_val) == 1, "Error generating DH parameters.");
27 params.reset(params_val);
28 }
29
30 EVP_PKEY_CTX_WRAPPER keygen_ctx_ = nullptr;
31 keygen_ctx_.reset(EVP_PKEY_CTX_new(params.get(), NULL));
32
33 AlwaysAssert(keygen_ctx_ != nullptr, "Error initializing PKEY context.");
34 AlwaysAssert(EVP_PKEY_keygen_init(keygen_ctx_.get()) == 1, "Error generating DH key");
35 EVP_PKEY *pubkey = nullptr;
36 AlwaysAssert(EVP_PKEY_keygen(keygen_ctx_.get(), &pubkey) == 1, "Error generating DH key");
37 pubkey_.reset(pubkey);
38 }
39
44 ByteArray get_public_key() const
45 {
46 BIO_WRAPPER bio{ BIO_new(BIO_s_mem()) };
47 AlwaysAssert(bio != nullptr, "BIO_new_file() failed");
48 AlwaysAssert(PEM_write_bio_PUBKEY(bio.get(), pubkey_.get()) > 0, "PEM_write_bio_PrivateKey() failed");
49 unsigned char *key_data;
50 unsigned long key_size = BIO_get_mem_data(bio.get(), &key_data);
51
52 ByteArray public_key;
53 public_key.resize(key_size);
54 std::copy_n(key_data, key_size, public_key.as<unsigned char>());
55 return public_key;
56 }
57
63 ByteArray get_shared_secret(const ByteView peer_key_bytes) const
64 {
65 EVP_PKEY_WRAPPER peer_key;
66 {
67 BIO_WRAPPER bio{ BIO_new_mem_buf(peer_key_bytes.data(), static_cast<int>(peer_key_bytes.size())) };
68 AlwaysAssert(bio != nullptr, "BIO_new_file() failed");
69 peer_key.reset(PEM_read_bio_PUBKEY(bio.get(), nullptr, nullptr, nullptr));
70 AlwaysAssert(peer_key != nullptr, "PEM_read_bio_PUBKEY() failed");
71 }
72
73 EVP_PKEY_CTX_WRAPPER ctx{ EVP_PKEY_CTX_new(pubkey_.get(), NULL) };
74 AlwaysAssert(ctx != nullptr, "Error initializing PKEY context.");
75 AlwaysAssert(EVP_PKEY_derive_init(ctx.get()) == 1, "Error initializing PKEY context.");
76 AlwaysAssert(EVP_PKEY_derive_set_peer(ctx.get(), peer_key.get()) == 1, "Error initializing PKEY context.");
77
78 size_t len;
79 AlwaysAssert(EVP_PKEY_derive(ctx.get(), NULL, &len) == 1, "Error initializing PKEY context.");
80 ByteArray shared_secret;
81 shared_secret.resize(len);
82 AlwaysAssert(EVP_PKEY_derive(ctx.get(), shared_secret.as<unsigned char>(), &len) == 1,
83 "Error initializing PKEY context.");
84 shared_secret.resize(len);
85
86 return shared_secret;
87 }
88
89 private:
90 EVP_PKEY_WRAPPER pubkey_;
91 };
92} // namespace mal_packet_weaver::crypto
93#endif
void AlwaysAssert(bool value, std::string_view message="Assert failed", std::source_location location=std::source_location::current())
Always asserts a condition with customizable behavior.