base for packet encryption

This commit is contained in:
study-faraphel 2024-11-20 15:24:14 +01:00
parent 523c86237c
commit e5c0418760
5 changed files with 87 additions and 67 deletions

View file

@ -49,7 +49,6 @@ add_executable(M2-PT-DRP
source/behavior/tasks/client/ClientTask.cpp
source/behavior/tasks/client/ClientTask.hpp
source/Context.hpp
source/utils/CacheMap.hpp
source/packets/search/SearchPacketData.hpp
source/packets/base/PacketContent.cpp
source/packets/base/PacketContent.hpp

View file

@ -1,6 +1,7 @@
#include "Packet.hpp"
#include <stdexcept>
#include <cstring>
#include "SecurityMode.hpp"
@ -49,23 +50,50 @@ GenericPacketContent decryptPacketContentAes(const GenericPacket& packet) {
*/
PacketContent Packet::getContent() const {
// TODO(Faraphel): implement RSA and AES
// additional "context" argument to hold cryptographic keys ?
inline Packet::Packet(
const Context& context,
const std::uint8_t channel,
SecurityMode securityMode,
const PacketContent& content
) {
this->channel = channel;
this->securityMode = static_cast<std::uint8_t>(securityMode);
switch (securityMode) {
case SecurityMode::PLAIN:
this->content = static_cast<auto>(content);
break;
case SecurityMode::RSA:
this->content = encryptRsa(context, content);
break;
case SecurityMode::AES:
this->content = encryptAes(context, content);
break;
default:
throw std::invalid_argument("Invalid security mode.");
}
}
PacketContent Packet::getContent(
const Context& context,
const sockaddr_storage& address,
socklen_t addressLength
) const {
PacketContent content {};
switch (static_cast<SecurityMode>(this->securityMode)) {
case SecurityMode::PLAIN:
return this->_content;
case SecurityMode::AES:
// return decryptPacketContentAes(packet);
throw std::runtime_error("Not implemented.");
std::memcpy(&content, &this->content, sizeof(PacketContent));
return content;
case SecurityMode::RSA:
throw std::runtime_error("Not implemented.");
content = decryptRsa(context, this->content, address, addressLength);
return content;
case SecurityMode::AES:
content = decryptAes(context, this->content);
return content;
default:
throw std::runtime_error("Unsupported security mode.");
throw std::invalid_argument("Invalid security mode.");
}
}

View file

@ -3,7 +3,9 @@
#include <array>
#include <cstdint>
#include "Context.hpp"
#include "PacketContent.hpp"
#include "SecurityMode.hpp"
namespace drp::packet::base {
@ -14,15 +16,26 @@ namespace drp::packet::base {
* @param channel the channel of the packet. Two system can be created inside a same network by using different
* channels value. "0" is used for "broadcast" message across networks.
* @param securityMode the type of security used in the packet.
* @param _content the content of the packet. It is encrypted accordingly to the securityMode.
* @param content the content of the packet. It is encrypted accordingly to the securityMode.
*/
struct Packet {
class Packet {
public:
explicit Packet(
const Context& context,
std::uint8_t channel,
SecurityMode securityMode,
const PacketContent& content
);
[[nodiscard]] PacketContent getContent(
const Context& context,
const sockaddr_storage& address,
socklen_t addressLength
) const;
private:
std::uint8_t channel;
std::uint8_t securityMode;
PacketContent _content;
[[nodiscard]] PacketContent getContent() const;
void setContent(const PacketContent& content);
std::array<std::uint8_t, sizeof(PacketContent)> content;
};

View file

@ -1,7 +1,10 @@
#include "PacketContent.hpp"
#include <stdexcept>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include "Context.hpp"
#include "Packet.hpp"
#include "SecurityMode.hpp"
@ -9,22 +12,34 @@
namespace drp::packet::base {
void Packet::setContent(const PacketContent &content) {
// TODO(Faraphel): implement RSA and AES
switch (static_cast<SecurityMode>(this->securityMode)) {
case SecurityMode::PLAIN:
this->_content = content;
return;
void PacketContent::encryptRsa(const std::array<std::uint8_t, 2048>& publicKey) {
BIO* bioPublicKey = BIO_new_mem_buf(publicKey.data(), static_cast<int>(publicKey.size()));
EVP_PKEY* evpPublicKey = PEM_read_bio_PUBKEY(bioPublicKey, nullptr, nullptr, nullptr);
case SecurityMode::AES:
throw std::runtime_error("Not implemented.");
const std::unique_ptr<EVP_PKEY_CTX, decltype(&EVP_PKEY_CTX_free)> evpContext(
EVP_PKEY_CTX_new(evpPublicKey, nullptr),
EVP_PKEY_CTX_free
);
if (evpContext == nullptr)
throw std::runtime_error("Failed to create EVP_PKEY_CTX");
case SecurityMode::RSA:
throw std::runtime_error("Not implemented.");
if (EVP_PKEY_encrypt_init(evpContext.get()) <= 0)
throw std::runtime_error("Failed to initialize EVP_PKEY_CTX");
if (EVP_PKEY_CTX_set_rsa_padding(evpContext.get(), RSA_PKCS1_PADDING) <= 0)
throw std::runtime_error("Failed to set RSA_PKCS1_PADDING");
std::vector<std::uint8_t> cipher(EVP_PKEY_size(evpPublicKey));
std::size_t cipherLength;
EVP_PKEY_encrypt(
evpContext.get(),
cipher.data(),
&cipherLength,
this,
sizeof(*this)
);
cipher.resize(cipherLength);
default:
throw std::runtime_error("Unsupported security mode.");
}
}

View file

@ -1,35 +0,0 @@
#pragma once
#include <functional>
#include <map>
namespace drp::util {
template<class Key, class Value, int limit, class Comparator = std::less<Value>>
class CacheMap : std::map<Key, Value> {
public:
void cache() {
// check if the limit have been reached.
if (this->size() <= limit)
return;
// apply the comparator on all the value to find the minimum.
auto minimum = this->begin();
for (const auto& it : this)
if (Comparator()(it.second, minimum))
minimum = it;
// delete this lowest value.
this->erase(minimum);
}
Value& operator[](const Key& key) {
const auto& value = std::map<Key, Value>::operator[](key);
this->cache();
return value;
}
};
}