aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralpine <[email protected]>2020-06-13 22:27:52 +0200
committeralpine <[email protected]>2020-06-13 22:27:52 +0200
commitbad7b4f2d19f95b278fdcb3056be01cae9af1dbb (patch)
tree5bef91f910a2c03d74df9693a077ee33b2fe7886
parentInitial commit (diff)
downloadloader-bad7b4f2d19f95b278fdcb3056be01cae9af1dbb.tar.xz
loader-bad7b4f2d19f95b278fdcb3056be01cae9af1dbb.zip
Client.
Message encryption. Packet handler. Disconnect event handler.
-rw-r--r--CMakeLists.txt4
-rw-r--r--client/src/client/client.cpp23
-rw-r--r--client/src/client/client.h29
-rw-r--r--client/src/client/packet.h65
-rw-r--r--client/src/include.h28
-rw-r--r--client/src/main.cpp17
-rw-r--r--client/src/util/xor.cpp41
-rw-r--r--client/src/util/xor.h14
-rw-r--r--server/src/client/client.cpp27
-rw-r--r--server/src/client/client.h57
-rw-r--r--server/src/main.cpp34
-rw-r--r--server/src/server/packet.h42
-rw-r--r--server/src/server/server.cpp106
-rw-r--r--server/src/server/server.h46
-rw-r--r--server/src/server/ssl.h59
-rw-r--r--server/src/util/xor.cpp39
-rw-r--r--server/src/util/xor.h12
17 files changed, 539 insertions, 104 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index facc157..95ff2a3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,5 +27,5 @@ add_subdirectory(client)
target_include_directories(server PRIVATE ${PROJECT_SOURCE_DIR}/shared ${OPENSSL_INCLUDE_DIR} ${CPR_INCLUDE_DIRS})
target_link_libraries(server PRIVATE spdlog ${OPENSSL_LIBRARIES} ${CPR_LIBRARIES})
-target_include_directories(client PRIVATE ${PROJECT_SOURCE_DIR}/shared)
-target_link_libraries(client PRIVATE spdlog)
+target_include_directories(client PRIVATE ${PROJECT_SOURCE_DIR}/shared ${OPENSSL_INCLUDE_DIR})
+target_link_libraries(client PRIVATE spdlog ${OPENSSL_LIBRARIES} )
diff --git a/client/src/client/client.cpp b/client/src/client/client.cpp
index 9fe2e36..71c9e11 100644
--- a/client/src/client/client.cpp
+++ b/client/src/client/client.cpp
@@ -2,15 +2,10 @@
#include "client.h"
bool tcp::client::start(const std::string_view server_ip,
- const uint16_t &port) {
-#ifdef WINDOWS
- WSADATA data;
- int res = WSAStartup(MAKEWORD(2, 2), &data);
- if (res != 0) {
- io::logger->error("failed to initialize WSA.");
- return false;
- }
-#endif
+ const uint16_t port) {
+ SSL_library_init();
+
+ m_ssl_ctx = SSL_CTX_new(TLS_client_method());
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_socket == -1) {
@@ -31,5 +26,15 @@ bool tcp::client::start(const std::string_view server_ip,
return false;
}
+ m_server_ssl = SSL_new(m_ssl_ctx);
+ SSL_set_fd(m_server_ssl, m_socket);
+
+ ret = SSL_connect(m_server_ssl);
+ if(ret != 1) {
+ ret = SSL_get_error(m_server_ssl, ret);
+ io::logger->error("failed to connect to server ssl. {}", ret);
+ return false;
+ }
+
return true;
}
diff --git a/client/src/client/client.h b/client/src/client/client.h
index 8f14071..7c1b8a7 100644
--- a/client/src/client/client.h
+++ b/client/src/client/client.h
@@ -1,6 +1,7 @@
#pragma once
#include "../util/io.h"
#include "../util/events.h"
+#include "packet.h"
namespace tcp {
@@ -14,33 +15,39 @@ class client {
int m_socket;
std::atomic<uint8_t> m_state;
- event<std::string> receive_event;
+ SSL *m_server_ssl;
+ SSL_CTX *m_ssl_ctx;
public:
+ event<packet_t &> receive_event;
+
client() : m_socket{-1}, m_state{0} {}
- bool start(const std::string_view server_ip, const uint16_t &port);
+ bool start(const std::string_view server_ip, const uint16_t port);
+
+ int write(void *data, size_t size) {
+ return SSL_write(m_server_ssl, data, size);
+ }
- bool send_message(const std::string_view msg) {
- int ret = send(m_socket, msg.data(), msg.size(), 0);
- return ret == msg.size();
+ int read(void *data, size_t size) {
+ return SSL_read(m_server_ssl, data, size);
}
int get_socket() { return m_socket; }
bool is_active() { return m_state == client_state::active; }
void set_state(const uint8_t &state) { m_state = state; }
- auto &on_recv() { return receive_event; }
- static void read(client &client) {
- std::array<char, 256> buf;
+ static void monitor(client &client) {
+ std::array<char, 4096> buf;
while (client.is_active()) {
- int ret = recv(client.get_socket(), &buf[0], buf.size(), 0);
+ int ret = client.read(&buf[0], buf.size());
if (ret <= 0) {
io::logger->error("connection lost.");
break;
}
-
std::string msg(buf.data(), ret);
- client.on_recv().call(msg);
+ packet_t packet(msg, packet_type::read);
+
+ client.receive_event.call(packet);
}
}
};
diff --git a/client/src/client/packet.h b/client/src/client/packet.h
index b61c4e2..3930243 100644
--- a/client/src/client/packet.h
+++ b/client/src/client/packet.h
@@ -1,45 +1,42 @@
#pragma once
+#include "../util/xor.h"
namespace tcp {
- constexpr size_t uid_len = 10;
- struct packet_t {
- std::string message;
- char action;
- std::array<char, uid_len> uid;
-
- // parse packet from server message after decryption
- bool parse(const std::string msg) {
- // first 10 bytes is the uid
- bool res = set_uid(msg.substr(0, uid_len));
- if(!res) {
- return false;
+constexpr size_t uid_len = 10;
+
+enum packet_type : int { write = 0, read };
+
+struct packet_t {
+ std::string message;
+ char action;
+ std::string uid;
+
+ packet_t() {}
+ packet_t(const std::string msg, const packet_type &type, std::string userid = "") {
+ if (type == read) {
+ std::string decrypted{msg};
+ enc::decrypt_message(decrypted);
+
+ if (decrypted.size() < uid_len) {
+ io::logger->error("client packet message invalid!");
+ return;
}
- action = msg[uid_len];
- const bool stream = static_cast<bool>(msg[uid_len + 1]);
- if(stream) {
- const size_t size = std::stoll(msg.substr(uid_len + 2));
+ uid = decrypted.substr(0, uid_len);
- // receive stream
+ action = decrypted[uid_len];
+ message = decrypted.substr(uid_len);
+ } else {
+ uid = userid;
- return true;
- }
+ message = fmt::format("{}{}", uid, msg);
- message = msg.substr(uid_len + 2);
- return true;
+ enc::encrypt_message(message);
}
- bool set_uid(const std::string_view uid_str) {
- const size_t uid_str_len = uid_str_len.size();
- if(uid_str_len != uid_len) {
- io::logger->error("packet uid len mismatch!");
- return false;
- }
+ }
- for(size_t i = 0; i < uid_len; ++i) {
- uid[i] = uid_str[i];
- }
-
- return true;
- }
- };
+ operator bool() const {
+ return !message.empty() && !uid.empty();
+ }
};
+}; // namespace tcp
diff --git a/client/src/include.h b/client/src/include.h
index e2c647b..fe46e5a 100644
--- a/client/src/include.h
+++ b/client/src/include.h
@@ -1,24 +1,5 @@
#pragma once
-#if defined(_WIN32) || defined(_WIN64)
-#define WINDOWS
-#endif
-
-#ifdef WINDOWS
-#define _CRT_SECURE_NO_WARNINGS
-#define _WINSOCK_DEPRECATED_NO_WARNINGS
-#define WIN32_LEAN_AND_MEAN
-#define NOMINMAX
-
-#include <windows.h>
-#include <stdio.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <iphlpapi.h>
-
-#pragma comment( lib, "ws2_32.lib" )
-#endif
-
#include <stdio.h>
#include <algorithm>
#include <array>
@@ -45,19 +26,16 @@
#include <future>
#include <any>
-#ifndef WINDOWS
-
-#define closesocket(socket) close(socket)
-
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
-#endif
#include <spdlog/fmt/fmt.h>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>
-#include <spdlog/sinks/stdout_color_sinks.h> \ No newline at end of file
+#include <spdlog/sinks/stdout_color_sinks.h>
+
+#include <openssl/ssl.h> \ No newline at end of file
diff --git a/client/src/main.cpp b/client/src/main.cpp
index 1dc9db2..13da109 100644
--- a/client/src/main.cpp
+++ b/client/src/main.cpp
@@ -3,23 +3,32 @@
#include "client/client.h"
int main(int argc, char *argv[]) {
+ io::init();
+
tcp::client client;
+
if (client.start("127.0.0.1", 6666)) {
io::logger->info("connected.");
client.set_state(tcp::client_state::active);
}
- client.on_recv().add([&](std::string msg) {
- io::logger->info(msg);
+ client.receive_event.add([&](tcp::packet_t &packet) {
+ if(!packet)
+ return;
+
+ io::logger->info(packet.message);
+ io::logger->info(packet.uid.data());
});
- std::thread t{tcp::client::read, std::ref(client)};
+ std::thread t{tcp::client::monitor, std::ref(client)};
while (client.is_active()) {
std::string p;
getline(std::cin, p);
- bool ret = client.send_message(p);
+ tcp::packet_t packet(p, tcp::packet_type::write, "1234567890");
+
+ bool ret = client.write(packet.message.data(), packet.message.size());
if (!ret) {
break;
}
diff --git a/client/src/util/xor.cpp b/client/src/util/xor.cpp
new file mode 100644
index 0000000..483c161
--- /dev/null
+++ b/client/src/util/xor.cpp
@@ -0,0 +1,41 @@
+#include "../include.h"
+#include "xor.h"
+
+char enc::gen_key() {
+ std::random_device r;
+
+ std::default_random_engine e1(r());
+ std::uniform_real_distribution<> uniform_dist(0, 255);
+ return static_cast<char>(uniform_dist(e1));
+}
+
+// XOR keys at the beginning of the message for clients
+void enc::encrypt_message(std::string &str) {
+ std::array<char, key_num> keys;
+ for (size_t i = 0; i < key_num; i++) {
+ char key = gen_key();
+ keys[i] = key;
+ str.insert(str.begin(), key);
+ }
+
+ for (auto &key : keys) {
+ for (size_t i = key_num; i < str.size(); i++) {
+ str[i] ^= key;
+ }
+ }
+}
+
+// XOR keys at the end of the message for server messages
+void enc::decrypt_message(std::string &str) {
+ if (str.size() <= 50) return;
+
+ std::string keys = str.substr(str.size() - key_num);
+
+ for (auto &key : keys) {
+ for (size_t i = 0; i < str.size() - key_num; i++) {
+ str[i] ^= key;
+ }
+ }
+
+ str.erase(str.end() - key_num, str.end());
+} \ No newline at end of file
diff --git a/client/src/util/xor.h b/client/src/util/xor.h
new file mode 100644
index 0000000..1ae1ce2
--- /dev/null
+++ b/client/src/util/xor.h
@@ -0,0 +1,14 @@
+#pragma once
+
+namespace enc {
+constexpr size_t key_num = 50;
+
+char gen_key();
+
+// XOR keys at the beginning of the message for clients
+void encrypt_message(std::string &str);
+
+// XOR keys at the end of the message for server messages
+void decrypt_message(std::string &str);
+
+} // namespace enc \ No newline at end of file
diff --git a/server/src/client/client.cpp b/server/src/client/client.cpp
new file mode 100644
index 0000000..4c458c8
--- /dev/null
+++ b/server/src/client/client.cpp
@@ -0,0 +1,27 @@
+#include "../include.h"
+#include "../util/io.h"
+#include "client.h"
+
+bool tcp::client::init_ssl(SSL_CTX *server_ctx) {
+ m_ssl = SSL_new(server_ctx);
+ if (!m_ssl) {
+ io::logger->error("failed to create ssl on client {}.", m_ip);
+ return false;
+ }
+
+ int ret = SSL_set_fd(m_ssl, m_socket);
+ if (ret <= 0) {
+ io::logger->error("failed to set descriptor on client {}.", m_ip);
+ return false;
+ }
+
+ ret = SSL_accept(m_ssl);
+ if (ret <= 0) {
+ int err = SSL_get_error(m_ssl, ret);
+ io::logger->error("client {} failed to accept ssl, return code {}", m_ip,
+ err);
+ return false;
+ }
+
+ return true;
+} \ No newline at end of file
diff --git a/server/src/client/client.h b/server/src/client/client.h
new file mode 100644
index 0000000..5242ae7
--- /dev/null
+++ b/server/src/client/client.h
@@ -0,0 +1,57 @@
+#pragma once
+#include "../server/packet.h"
+
+namespace tcp {
+constexpr uint8_t client_version = 0;
+
+class client {
+ int m_socket;
+ SSL *m_ssl;
+
+ time_t m_time;
+
+ std::string m_ip;
+ std::array<char, tcp::uid_len> m_uid;
+ public:
+ client() : m_socket{-1} {};
+ client(const int &socket, const std::string_view ip)
+ : m_socket{std::move(socket)}, m_ip{ip}, m_ssl{nullptr} {
+
+ }
+ ~client() = default;
+
+ bool init_ssl(SSL_CTX *server_ctx);
+
+ void cleanup() {
+ close(m_socket);
+ SSL_shutdown(m_ssl);
+ SSL_free(m_ssl);
+ }
+
+ int write(void *data, size_t size) {
+ return SSL_write(m_ssl, data, size);
+ }
+
+ int read(void *data, size_t size) {
+ return SSL_read(m_ssl, data, size);
+ }
+
+ bool set_uid(const std::string_view uid_str) {
+ const size_t uid_str_len = uid_str.size();
+ if (uid_str_len != tcp::uid_len) {
+ io::logger->error("packet uid len mismatch!");
+ return false;
+ }
+
+ for (size_t i = 0; i < uid_len; ++i) {
+ m_uid[i] = uid_str[i];
+ }
+
+ return true;
+ }
+
+ int &get_socket() { return m_socket; }
+ auto &get_ip() { return m_ip; }
+ auto &get_uid() { return m_uid; }
+};
+}; // namespace tcp \ No newline at end of file
diff --git a/server/src/main.cpp b/server/src/main.cpp
index f34c433..9db266f 100644
--- a/server/src/main.cpp
+++ b/server/src/main.cpp
@@ -2,13 +2,39 @@
#include "util/io.h"
#include "util/commands.h"
#include "server/server.h"
+#include "util/xor.h"
int main(int argc, char *argv[]) {
io::init(false);
- tcp::server server;
- server.start("6666");
- server.start("8981");
+ tcp::server server("6666");
- std::cin.get();
+ server.start();
+
+ server.connect_event.add([&](tcp::client &client) {
+ io::logger->info("{} connected.", client.get_ip());
+ });
+
+ server.disconnect_event.add([&](tcp::client &client) {
+ auto it = std::find_if(server.client_stack.begin(), server.client_stack.end(), [&](tcp::client &c) {
+ return client.get_socket() == client.get_socket();
+ });
+
+ server.client_stack.erase(it);
+ client.cleanup();
+
+ io::logger->info("{} disconnected.", client.get_ip());
+ });
+
+ server.receive_event.add([&](tcp::packet_t &packet, tcp::client &client) {
+ if (!packet) return;
+
+ io::logger->info("{} : {}", packet.uid.data(), packet.message);
+
+ tcp::packet_t resp("hello nigga", tcp::packet_type::write, "1234567890");
+ client.write(resp.message.data(), resp.message.size());
+ });
+
+ std::thread t{tcp::server::monitor, std::ref(server)};
+ t.join();
}
diff --git a/server/src/server/packet.h b/server/src/server/packet.h
index 02d90d1..3930243 100644
--- a/server/src/server/packet.h
+++ b/server/src/server/packet.h
@@ -1,10 +1,42 @@
#pragma once
+#include "../util/xor.h"
namespace tcp {
- constexpr uint8_t uid_len = 10;
+constexpr size_t uid_len = 10;
- struct packet_t {
- std::string message;
- std::array<char, uid_len> uid;
+enum packet_type : int { write = 0, read };
+
+struct packet_t {
+ std::string message;
+ char action;
+ std::string uid;
+
+ packet_t() {}
+ packet_t(const std::string msg, const packet_type &type, std::string userid = "") {
+ if (type == read) {
+ std::string decrypted{msg};
+ enc::decrypt_message(decrypted);
+
+ if (decrypted.size() < uid_len) {
+ io::logger->error("client packet message invalid!");
+ return;
+ }
+
+ uid = decrypted.substr(0, uid_len);
+
+ action = decrypted[uid_len];
+ message = decrypted.substr(uid_len);
+ } else {
+ uid = userid;
+
+ message = fmt::format("{}{}", uid, msg);
+
+ enc::encrypt_message(message);
+ }
+ }
+
+ operator bool() const {
+ return !message.empty() && !uid.empty();
}
-}
+};
+}; // namespace tcp
diff --git a/server/src/server/server.cpp b/server/src/server/server.cpp
index 2f684e1..b140665 100644
--- a/server/src/server/server.cpp
+++ b/server/src/server/server.cpp
@@ -2,8 +2,13 @@
#include "../util/io.h"
#include "server.h"
-bool tcp::server::start(const std::string_view port) {
- io::logger->info("starting server on port {}...", port.data());
+bool tcp::server::start() {
+ io::logger->info("starting server on port {}...", m_port.data());
+
+ ssl ctx("ssl/server.crt", "ssl/server.key", "ssl/rootCA.crt");
+ if (!ctx.init()) return false;
+
+ m_ctx = std::move(ctx.get_context());
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_socket < 0) {
@@ -19,7 +24,7 @@ bool tcp::server::start(const std::string_view port) {
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
- int ret = getaddrinfo(nullptr, port.data(), &hints, &addrinfo);
+ int ret = getaddrinfo(nullptr, m_port.data(), &hints, &addrinfo);
if (ret != 0) {
io::logger->critical("failed to get address info.");
close(m_socket);
@@ -37,16 +42,103 @@ bool tcp::server::start(const std::string_view port) {
ret = listen(m_socket, SOMAXCONN);
if (ret < 0) {
- io::logger->critical("failed to listen on port {}.", port.data());
+ io::logger->critical("failed to listen on port {}.", m_port.data());
close(m_socket);
return false;
}
- io::logger->info("listening on {}.", port.data());
+ io::logger->info("listening on {}.", m_port.data());
+
+ m_status = true;
return true;
}
+tcp::select_status tcp::server::peek() {
+ FD_ZERO(&m_server_set);
+ FD_SET(m_socket, &m_server_set);
+
+ int maxfd = m_socket;
+
+ for (auto &c : client_stack) {
+ const int s = c.get_socket();
+ FD_SET(s, &m_server_set);
+
+ maxfd = std::max(maxfd, s);
+ }
+
+ struct timeval tv;
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+
+ const int ret = select(maxfd + 1, &m_server_set, nullptr, nullptr, &tv);
+ if (ret < 0) {
+ io::logger->error("select error : {}", strerror(errno));
+ return tcp::select_status::error;
+ }
+
+ if (ret == 0) {
+ return tcp::select_status::standby;
+ }
+
+ return tcp::select_status::ready;
+}
+
+void tcp::server::accept_client() {
+ if (!FD_ISSET(m_socket, &m_server_set)) return;
+
+ struct sockaddr_in addr;
+ socklen_t len = sizeof(addr);
+ const int client_socket =
+ accept(m_socket, reinterpret_cast<sockaddr *>(&addr), &len);
+
+ const auto ip = inet_ntoa(addr.sin_addr);
+ if (client_socket < 0) {
+ io::logger->warn("{} failed to accept.", ip);
+ close(client_socket);
+ } else {
+ client cli(client_socket, ip);
+ if (!cli.init_ssl(m_ctx)) {
+ cli.cleanup();
+ return;
+ }
+
+ // check for an existing connection
+ auto it = std::find_if(client_stack.begin(), client_stack.end(),
+ [&](client &c) { return c.get_ip() == ip; });
+ if (it != client_stack.end()) {
+ io::logger->info("{} is already connected, dropping...", ip);
+ cli.cleanup();
+ return;
+ }
+
+ connect_event.call(cli);
+ client_stack.emplace_back(cli);
+ }
+}
+
+void tcp::server::receive() {
+ std::array<char, 4096> buf;
+ for (auto &c : client_stack) {
+ const int socket = c.get_socket();
+
+ if (!FD_ISSET(socket, &m_server_set)) continue;
+
+ buf.fill(0);
+
+ const int read = c.read(&buf[0], buf.size());
+ if (read > 0) {
+ std::string msg(buf.data(), read);
+
+ tcp::packet_t packet(msg, tcp::packet_type::read);
+
+ receive_event.call(packet, c);
+ } else {
+ disconnect_event.call(c);
+ }
+ }
+}
+
void tcp::server::stop() {
- io::logger->info("stopping server on port {}.", m_port);
- close(m_socket);
+ io::logger->info("stopping server on port {}.", m_port);
+ close(m_socket);
} \ No newline at end of file
diff --git a/server/src/server/server.h b/server/src/server/server.h
index f848ae2..39b9580 100644
--- a/server/src/server/server.h
+++ b/server/src/server/server.h
@@ -1,12 +1,54 @@
#pragma once
+#include "../client/client.h"
+#include "../util/events.h"
+#include "ssl.h"
namespace tcp {
+constexpr uint8_t server_version = 0;
+
+enum select_status : int { error = 0, standby, ready };
+
class server {
int m_socket;
-
+ std::string_view m_port;
+
+ fd_set m_server_set;
+ SSL_CTX *m_ctx;
+
+ std::atomic<bool> m_status = false;
+
public:
+ std::vector<tcp::client> client_stack;
+
- bool start(const std::string_view port);
+ event<client &> connect_event;
+ event<packet_t &, client &> receive_event;
+ event<client &> disconnect_event;
+
+ server(const std::string_view port) : m_port{port} {}
+ ~server() = default;
+
+ bool start();
+ select_status peek();
+ void accept_client();
+ void receive();
void stop();
+
+ bool running() { return m_status; }
+
+ static void monitor(server &srv) {
+ while (srv.running()) {
+ auto ret = srv.peek();
+ if (ret == select_status::ready) {
+ srv.accept_client();
+ srv.receive();
+ } else if (ret == select_status::standby) {
+ // check for timeout
+ } else {
+ break;
+ }
+ }
+ }
};
+
}; // namespace tcp
diff --git a/server/src/server/ssl.h b/server/src/server/ssl.h
index 7b9637e..06826be 100644
--- a/server/src/server/ssl.h
+++ b/server/src/server/ssl.h
@@ -1 +1,58 @@
-#pragma once \ No newline at end of file
+#pragma once
+
+class ssl {
+ std::string_view m_cert, m_key, m_ca;
+ std::string m_passphrase;
+ SSL_CTX* m_ctx;
+
+ public:
+ ssl(const std::string_view cert, const std::string_view key,
+ const std::string_view ca = "")
+ : m_cert{cert}, m_key{key}, m_ca{ca}, m_ctx{nullptr} {
+ SSL_library_init();
+ }
+ ~ssl() = default;
+
+ bool init() {
+ m_ctx = SSL_CTX_new(TLS_server_method());
+ if (!m_ctx) {
+ io::logger->error("failed to create ssl context.");
+ return false;
+ }
+
+ int res =
+ SSL_CTX_use_certificate_file(m_ctx, m_cert.data(), SSL_FILETYPE_PEM);
+ if (res != 1) {
+ io::logger->error("failed to load certificate.");
+ return false;
+ }
+
+ if (!m_passphrase.empty())
+ SSL_CTX_set_default_passwd_cb_userdata(m_ctx, m_passphrase.data());
+
+ res = SSL_CTX_use_PrivateKey_file(m_ctx, m_key.data(), SSL_FILETYPE_PEM);
+ if (res != 1) {
+ io::logger->error("failed to load private key.");
+ return false;
+ }
+
+ res = SSL_CTX_check_private_key(m_ctx);
+ if (res != 1) {
+ io::logger->error("failed to verify private key.");
+ return false;
+ }
+
+ res = SSL_CTX_load_verify_locations(m_ctx, m_ca.data(), nullptr);
+ if (res != 1) {
+ io::logger->error("failed to load root ca.");
+ return false;
+ }
+
+ SSL_CTX_set_verify(m_ctx, SSL_VERIFY_PEER, 0);
+
+ return true;
+ }
+
+ void set_passphrase(const std::string_view phrase) { m_passphrase = phrase; }
+ auto &get_context() { return m_ctx; }
+};
diff --git a/server/src/util/xor.cpp b/server/src/util/xor.cpp
new file mode 100644
index 0000000..a00ecc9
--- /dev/null
+++ b/server/src/util/xor.cpp
@@ -0,0 +1,39 @@
+#include "../include.h"
+#include "xor.h"
+
+char enc::gen_key() {
+ std::random_device r;
+
+ std::default_random_engine e1(r());
+ std::uniform_real_distribution<> uniform_dist(0, 255);
+ return static_cast<char>(uniform_dist(e1));
+}
+
+void enc::encrypt_message(std::string &str) {
+ std::array<char, key_len> keys;
+ for (size_t i = 0; i < key_len; i++) {
+ keys[i] = gen_key();
+ str.insert(str.end(), keys[i]);
+ }
+
+ for (auto &key : keys) {
+ for (size_t i = 0; i < str.size() - key_len; i++) {
+ str[i] ^= key;
+ }
+ }
+}
+
+void enc::decrypt_message(std::string &str) {
+ if (str.size() <= key_len) return;
+
+ std::string keys = str.substr(0, key_len);
+ std::reverse(keys.begin(), keys.end());
+
+ for (auto &key : keys) {
+ for (size_t i = key_len; i < str.size(); i++) {
+ str[i] ^= key;
+ }
+ }
+
+ str.erase(str.begin(), str.begin() + key_len);
+} \ No newline at end of file
diff --git a/server/src/util/xor.h b/server/src/util/xor.h
new file mode 100644
index 0000000..7180945
--- /dev/null
+++ b/server/src/util/xor.h
@@ -0,0 +1,12 @@
+#pragma once
+
+namespace enc {
+constexpr size_t key_len = 50;
+
+char gen_key();
+
+void encrypt_message(std::string &str);
+
+void decrypt_message(std::string &str);
+
+} // namespace enc \ No newline at end of file