From 5a0c50b55eea216328431175569c86d7bde7801a Mon Sep 17 00:00:00 2001 From: mrbesen Date: Thu, 23 Nov 2023 21:36:16 +0100 Subject: [PATCH] add crypt class --- .gitmodules | 3 ++ Makefile | 9 ++-- inc/crypt.h | 22 +++++++++ inc/tgtui.h | 4 ++ src/crypt.cpp | 118 ++++++++++++++++++++++++++++++++++++++++++++++++ src/tgtui.cpp | 7 +-- thirdparty/liby | 1 + 7 files changed, 158 insertions(+), 6 deletions(-) create mode 100644 inc/crypt.h create mode 100644 src/crypt.cpp create mode 160000 thirdparty/liby diff --git a/.gitmodules b/.gitmodules index f07350a..b3f7c70 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "thirdparty/Log"] path = thirdparty/Log url = https://git.mrbesen.de/MrBesen/Log.git +[submodule "thirdparty/liby"] + path = thirdparty/liby + url = ssh://gitea@git.mrbesen.de:2222/ygerlach/liby.git diff --git a/Makefile b/Makefile index 5999bfc..b681ac6 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,10 @@ TDLIBAF = $(TDLIBF)lib/ # TDLIBA = $(shell find $(TDLIBF)lib/ -type f -name "*.a") TDLIBA = $(TDLIBF)lib/libtdclient.a $(TDLIBF)lib/libtdcore.a $(TDLIBF)lib/libtdapi.a $(TDLIBF)lib/libtddb.a $(TDLIBF)lib/libtdactor.a $(TDLIBF)lib/libtdsqlite.a $(TDLIBF)lib/libtdnet.a $(TDLIBF)lib/libtdutils.a -INCLUDES = -I$(LOGF) $(addprefix -I, $(INCFS)) -I$(TDLIBF)include +LIBYF = ./thirdparty/liby/ +LIBYA = $(LIBYF)liby.a + +INCLUDES = -I$(LOGF) $(addprefix -I, $(INCFS)) -I$(TDLIBF)include -I$(LIBYF)include LDFLAGS = -pthread -lz -lssl -lcrypto -lncurses -lcdk SRCFILES = $(shell find $(SRCF) -name "*.cpp") @@ -42,7 +45,7 @@ INCLUDES += $(addprefix -I, $(SOURCEDIRS)) all: $(NAME) runtest -$(NAME): $(BUILDDIRS) $(DEPF) $(OBJFILES) $(TDLIBA) +$(NAME): $(BUILDDIRS) $(DEPF) $(OBJFILES) $(TDLIBA) $(LIBYA) @echo "Linking $@" @$(CXX) $(CFLAGS) -o $@ $(filter %.o, $^) $(filter %.a, $^) $(LDFLAGS) @@ -68,7 +71,7 @@ clean: $(RM) -r $(NAME) $(BUILDDIR) $(NAMETEST) $(NAME)_strip $(MAKE) -C $(LOGF) $@ -$(NAMETEST): $(BUILDDIRS) $(DEPF) $(TESTF)*.cpp $(OBJFILESTEST) $(TDLIBA) +$(NAMETEST): $(BUILDDIRS) $(DEPF) $(TESTF)*.cpp $(OBJFILESTEST) $(TDLIBA) $(LIBYA) @echo "Compiling tests" @$(CXX) -o $@ $(filter %.o, $^) $(filter %.cpp, $^) $(filter %.a, $^) $(CFLAGS) -I$(SRCF) $(INCLUDES) $(LDFLAGS) diff --git a/inc/crypt.h b/inc/crypt.h new file mode 100644 index 0000000..6ccd06d --- /dev/null +++ b/inc/crypt.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +class Crypt { +public: + Crypt(); + + void setKey(int64_t chatid, const std::string& keyfingerprint); + + std::string encryptForChat(int64_t chat, const std::string& message); + + std::string decryptFromChat(int64_t chat, const std::string& message); + + void save(); + void load(); + +private: + std::map chatKeyMap; + bool dirty = true; +}; diff --git a/inc/tgtui.h b/inc/tgtui.h index f45d190..8762d17 100644 --- a/inc/tgtui.h +++ b/inc/tgtui.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include "slimchat.h" @@ -8,6 +9,8 @@ #include +class Crypt; + class TgTUI { public: @@ -28,6 +31,7 @@ private: void handleChatMessages(const std::vector>& msgs); TGClient tgclient; + std::unique_ptr crypt; std::vector chats; std::vector chatsItemList; diff --git a/src/crypt.cpp b/src/crypt.cpp new file mode 100644 index 0000000..601c4dd --- /dev/null +++ b/src/crypt.cpp @@ -0,0 +1,118 @@ +#include "crypt.h" + +#include +#include + +#define Y_FEATURES (Y_FEATURE_SUBPROCES | Y_FEATURE_STRING) + +#include +#include +#include +#include + +static const std::string ConfigFile("./assignment.conf"); +static const std::string Header("-----BEGIN PGP MESSAGE-----\n\n"); +static const std::string Footer("\n-----END PGP MESSAGE-----"); +static const std::string MyHeader("gpg: "); + +Crypt::Crypt() {} + +void Crypt::setKey(int64_t chatid, const std::string& keyfingerprint) { + chatKeyMap[chatid] = keyfingerprint; + dirty = true; +} + +std::string Crypt::encryptForChat(int64_t chat, const std::string& message) { + std::map::iterator it = chatKeyMap.find(chat); + if(it == chatKeyMap.end()) { + // no key found + return ""; + } + + Y::SubProcess::Builder builder("gpg"); + builder + .setArgs({"-e", "--armor", "-r", it->second}) + .setFDMode(Y::SubProcess::FD::ALL, Y::SubProcess::FDMode::Pipe) + ; + + std::unique_ptr proc = builder.start(); + + std::string out; + Y::PipeFeeder feeder(&message, proc->getInFD()); + Y::PipeReader reader(&out, proc->getOutFD()); + + feeder.start(); + reader.start(); + + proc->waitFor(std::chrono::seconds(4)); + + out.resize(out.size() - Footer.size()); + return MyHeader + out.substr(Header.size()); +} + +std::string Crypt::decryptFromChat(int64_t chat, const std::string& message) { + if(!Y::Str::startsWith(message, MyHeader)) { + // not a gpg message + return message; + } + + /* + // needed for verification + std::map::iterator it = chatKeyMap.find(chat); + if(it == chatKeyMap.end()) { + // no key found + return ""; + } + */ + + std::string prefixed = Header + message.substr(MyHeader.size()) + Footer; + + Y::SubProcess::Builder builder("gpg"); + builder + .setArgs({"-d"}) + .setFDMode(Y::SubProcess::FD::ALL, Y::SubProcess::FDMode::Pipe) + ; + + std::unique_ptr proc = builder.start(); + + std::string out; + Y::PipeFeeder feeder(&prefixed, proc->getInFD()); + Y::PipeReader reader(&out, proc->getOutFD()); + + feeder.start(); + reader.start(); + + proc->waitFor(std::chrono::seconds(4)); + + return out; +} + +void Crypt::save() { + if(!dirty) { + return; + } + + std::ofstream out(ConfigFile); + for(std::map::const_iterator it = chatKeyMap.begin(); it != chatKeyMap.end(); ++it) { + out << it->first << ' ' << it->second << '\n'; + } + out.flush(); + out.close(); + + dirty = false; +} + +void Crypt::load() { + chatKeyMap.clear(); + + std::ifstream in(ConfigFile); + while(in) { + std::string key; + int64_t chat = 0; + in >> chat >> key; + if(chat && !key.empty()) { + chatKeyMap[chat] = key; + } + } + dirty = false; +} diff --git a/src/tgtui.cpp b/src/tgtui.cpp index f3ccab6..2ea8281 100644 --- a/src/tgtui.cpp +++ b/src/tgtui.cpp @@ -11,6 +11,7 @@ #include #include "config.h" +#include "crypt.h" namespace pl = std::placeholders; @@ -44,7 +45,7 @@ static void clearVec(std::vector v) { v.clear(); } -TgTUI::TgTUI() : tgclient(std::bind(&TgTUI::initDoneCB, this)) {} +TgTUI::TgTUI() : tgclient(std::bind(&TgTUI::initDoneCB, this)), crypt(std::make_unique()) {} TgTUI::~TgTUI() { stop(); @@ -168,10 +169,10 @@ void TgTUI::handleChatMessages(const std::vector>& msgs Log::debug << "new messages: " << msgs.size(); - std::vector listEntrys = convertToList>(msgs, [](const std::shared_ptr& msg) { + std::vector listEntrys = convertToList>(msgs, [this](const std::shared_ptr& msg) { const char direction = ( msg->isOutgoing ? '>' : '<' ); const std::string timeStr = "[" + FormatTime(msg->sendDate) + "] "; - std::string msgText = msg->text; + std::string msgText = crypt->decryptFromChat(msg->chat, msg->text); // find and remove first \n std::size_t nPos = msgText.find('\n'); diff --git a/thirdparty/liby b/thirdparty/liby new file mode 160000 index 0000000..ccb094d --- /dev/null +++ b/thirdparty/liby @@ -0,0 +1 @@ +Subproject commit ccb094d91a556a74bed467dcd3fc3ad961eb8ee6