add crypt class

This commit is contained in:
mrbesen 2023-11-23 21:36:16 +01:00
parent 7eff50e975
commit 5a0c50b55e
Signed by: MrBesen
GPG Key ID: 596B2350DCD67504
7 changed files with 158 additions and 6 deletions

3
.gitmodules vendored
View File

@ -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

View File

@ -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)

22
inc/crypt.h Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include <map>
#include <string>
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<int64_t, std::string> chatKeyMap;
bool dirty = true;
};

View File

@ -1,5 +1,6 @@
#pragma once
#include <memory>
#include <thread>
#include "slimchat.h"
@ -8,6 +9,8 @@
#include <cdk/cdk.h>
class Crypt;
class TgTUI {
public:
@ -28,6 +31,7 @@ private:
void handleChatMessages(const std::vector<std::shared_ptr<Message>>& msgs);
TGClient tgclient;
std::unique_ptr<Crypt> crypt;
std::vector<SlimChat> chats;
std::vector<char*> chatsItemList;

118
src/crypt.cpp Normal file
View File

@ -0,0 +1,118 @@
#include "crypt.h"
#include <chrono>
#include <fstream>
#define Y_FEATURES (Y_FEATURE_SUBPROCES | Y_FEATURE_STRING)
#include <y/str.h>
#include <y/subprocess.h>
#include <y/pipe/pipefeeder.h>
#include <y/pipe/pipereader.h>
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<int64_t, std::string>::iterator it = chatKeyMap.find(chat);
if(it == chatKeyMap.end()) {
// no key found
return "<key not found>";
}
Y::SubProcess::Builder builder("gpg");
builder
.setArgs({"-e", "--armor", "-r", it->second})
.setFDMode(Y::SubProcess::FD::ALL, Y::SubProcess::FDMode::Pipe)
;
std::unique_ptr<Y::SubProcess> 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<int64_t, std::string>::iterator it = chatKeyMap.find(chat);
if(it == chatKeyMap.end()) {
// no key found
return "<key not found>";
}
*/
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<Y::SubProcess> 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<int64_t, std::string>::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;
}

View File

@ -11,6 +11,7 @@
#include <cdk/cdk.h>
#include "config.h"
#include "crypt.h"
namespace pl = std::placeholders;
@ -44,7 +45,7 @@ static void clearVec(std::vector<char*> v) {
v.clear();
}
TgTUI::TgTUI() : tgclient(std::bind(&TgTUI::initDoneCB, this)) {}
TgTUI::TgTUI() : tgclient(std::bind(&TgTUI::initDoneCB, this)), crypt(std::make_unique<Crypt>()) {}
TgTUI::~TgTUI() {
stop();
@ -168,10 +169,10 @@ void TgTUI::handleChatMessages(const std::vector<std::shared_ptr<Message>>& msgs
Log::debug << "new messages: " << msgs.size();
std::vector<char*> listEntrys = convertToList<std::shared_ptr<Message>>(msgs, [](const std::shared_ptr<Message>& msg) {
std::vector<char*> listEntrys = convertToList<std::shared_ptr<Message>>(msgs, [this](const std::shared_ptr<Message>& 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');

1
thirdparty/liby vendored Submodule

@ -0,0 +1 @@
Subproject commit ccb094d91a556a74bed467dcd3fc3ad961eb8ee6