diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba9b4e9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +cerberus diff --git a/Makefile b/Makefile index e5f6885..7146e72 100644 --- a/Makefile +++ b/Makefile @@ -1,42 +1,38 @@ CC = clang CXX = clang++ - -CFLAGS = -O2 -Wall -I./libs -CXXFLAGS = -std=c++17 -O2 -Wall -I./libs - +CFLAGS = -O2 -Wall -I./libs -pthread +CXXFLAGS = -std=c++17 -O2 -Wall -I./libs -pthread UNAME_S := $(shell uname -s) BREW_PREFIX := $(shell brew --prefix portaudio 2>/dev/null) +ifneq ($(UNAME_S),) ifeq ($(UNAME_S),Darwin) - ifneq ($(BREW_PREFIX),) - CFLAGS += -I$(BREW_PREFIX)/include - CXXFLAGS += -I$(BREW_PREFIX)/include - LIBS += -L$(BREW_PREFIX)/lib -lportaudio - else - $(warning [Makefile] PortAudio не найдена через Homebrew. Установите её: brew install portaudio) - endif -else ifeq ($(UNAME_S),Linux) - HAVE_PKG := $(shell pkg-config --exists portaudio-2.0 && echo yes || echo no) - ifeq ($(HAVE_PKG),yes) - PORTAUDIO_CFLAGS := $(shell pkg-config --cflags portaudio-2.0) - PORTAUDIO_LIBS := $(shell pkg-config --libs portaudio-2.0) - CFLAGS += $(PORTAUDIO_CFLAGS) - CXXFLAGS += $(PORTAUDIO_CFLAGS) - LIBS += $(PORTAUDIO_LIBS) - else - $(warning [Makefile] portaudio-2.0 не найдена через pkg-config. Использую -lportaudio) - LIBS += -lportaudio - endif +ifneq ($(BREW_PREFIX),) +CFLAGS += -I$(BREW_PREFIX)/include +CXXFLAGS += -I$(BREW_PREFIX)/include +LIBS += -L$(BREW_PREFIX)/lib -lportaudio else - $(warning [Makefile] Unsupported OS: $(UNAME_S)) +$(warning PortAudio not found via brew) +endif +else ifeq ($(UNAME_S),Linux) +HAVE_PKG := $(shell pkg-config --exists portaudio-2.0 && echo yes || echo no) +ifeq ($(HAVE_PKG),yes) +PORTAUDIO_CFLAGS := $(shell pkg-config --cflags portaudio-2.0) +PORTAUDIO_LIBS := $(shell pkg-config --libs portaudio-2.0) +CFLAGS += $(PORTAUDIO_CFLAGS) +CXXFLAGS += $(PORTAUDIO_CFLAGS) +LIBS += $(PORTAUDIO_LIBS) +else +$(warning portaudio-2.0 not found, using -lportaudio) +LIBS += -lportaudio +endif +endif endif SRCS_CPP = main.cpp commands.cpp cli.cpp webserver.cpp sound.cpp bfsk.cpp x25519_handshake.cpp SRCS_C = libs/monocypher.c libs/linenoise.c - OBJS_CPP = $(SRCS_CPP:.cpp=.o) OBJS_C = $(SRCS_C:.c=.o) - TARGET = cerberus .PHONY: all clean diff --git a/bfsk.cpp b/bfsk.cpp index d887881..582aa98 100644 --- a/bfsk.cpp +++ b/bfsk.cpp @@ -1,78 +1,53 @@ #include "bfsk.hpp" #include #include -#include -std::vector bfskModulate(const std::vector &data) { - int samplesPerBit = (int)((double)SAMPLE_RATE / BFSK_BAUD); - size_t totalBits = data.size() * 8; - size_t totalSamples = totalBits * samplesPerBit; - std::vector out(totalSamples * 2, 0.0f); - - double phase0 = 0.0; - double phase1 = 0.0; - double inc0 = 2.0 * M_PI * BFSK_FREQ0 / (double)SAMPLE_RATE; - double inc1 = 2.0 * M_PI * BFSK_FREQ1 / (double)SAMPLE_RATE; - - size_t sampleIndex = 0; - - for (auto byteVal : data) { - for (int b = 0; b < 8; b++) { - int bit = (byteVal >> b) & 1; - for (int s = 0; s < samplesPerBit; s++) { - float val; - if (bit == 0) { - val = sinf((float)phase0); - phase0 += inc0; - } else { - val = sinf((float)phase1); - phase1 += inc1; - } - out[sampleIndex*2 + 0] = val * 0.3f; - out[sampleIndex*2 + 1] = val * 0.3f; - sampleIndex++; +std::vector bfskModulate(const std::vector &data){ + int spb=(int)(SAMPLE_RATE/BFSK_BAUD); + size_t tb=data.size()*8; + size_t ts=tb*spb; + std::vector out(ts*2,0.0f); + double phase0=0.0,phase1=0.0; + double inc0=2.0*M_PI*BFSK_FREQ0/(double)SAMPLE_RATE; + double inc1=2.0*M_PI*BFSK_FREQ1/(double)SAMPLE_RATE; + size_t idx=0; + for(auto byteVal:data){ + for(int b=0;b<8;b++){ + int bit=(byteVal>>b)&1; + for(int s=0;s bfskDemodulate(const std::vector &monoData) { - int samplesPerBit = (int)((double)SAMPLE_RATE / BFSK_BAUD); - size_t totalBits = monoData.size() / samplesPerBit; - size_t totalBytes = totalBits / 8; - - double inc0 = 2.0 * M_PI * BFSK_FREQ0 / (double)SAMPLE_RATE; - double inc1 = 2.0 * M_PI * BFSK_FREQ1 / (double)SAMPLE_RATE; - - std::vector result(totalBytes, 0); - - size_t bitIndex = 0; - for (size_t b = 0; b < totalBits; b++) { - double sum0 = 0.0; - double sum1 = 0.0; - double phase0 = 0.0; - double phase1 = 0.0; - - size_t startSample = b * samplesPerBit; - for (int s = 0; s < samplesPerBit; s++) { - float sample = monoData[startSample + s]; - float ref0 = sinf((float)phase0); - float ref1 = sinf((float)phase1); - sum0 += sample * ref0; - sum1 += sample * ref1; - phase0 += inc0; - phase1 += inc1; +std::vector bfskDemodulate(const std::vector &monoData){ + int spb=(int)(SAMPLE_RATE/BFSK_BAUD); + size_t tb=monoData.size()/spb; + size_t tbytes=tb/8; + std::vector res(tbytes,0); + double inc0=2.0*M_PI*BFSK_FREQ0/(double)SAMPLE_RATE; + double inc1=2.0*M_PI*BFSK_FREQ1/(double)SAMPLE_RATE; + size_t bitIdx=0; + for(size_t b=0;b std::fabs(sum0)) ? 1 : 0; - size_t bytePos = bitIndex / 8; - int bitPos = bitIndex % 8; - if (bytePos < result.size()) { - result[bytePos] |= (bit << bitPos); - } - bitIndex++; + int bit=(std::fabs(sum1)>std::fabs(sum0))?1:0; + size_t bytePos=bitIdx/8; int bitPos=bitIdx%8; + if(bytePos +#include -constexpr double BFSK_FREQ0 = 1000.0; -constexpr double BFSK_FREQ1 = 2000.0; -constexpr double BFSK_BAUD = 100.0; -constexpr int SAMPLE_RATE = 44100; +constexpr double BFSK_FREQ0=1000.0; +constexpr double BFSK_FREQ1=2000.0; +constexpr double BFSK_BAUD=100.0; +constexpr int SAMPLE_RATE=44100; -std::vector bfskModulate(const std::vector &data); - -std::vector bfskDemodulate(const std::vector &monoData); +std::vector bfskModulate(const std::vector &data); +std::vector bfskDemodulate(const std::vector &monoData); diff --git a/bfsk.o b/bfsk.o index 8a26e2b..e826b25 100644 Binary files a/bfsk.o and b/bfsk.o differ diff --git a/cerberus b/cerberus index f8e04db..73145a5 100755 Binary files a/cerberus and b/cerberus differ diff --git a/cli.cpp b/cli.cpp index d1bc551..05734f7 100644 --- a/cli.cpp +++ b/cli.cpp @@ -1,61 +1,59 @@ #include "cli.hpp" #include "commands.hpp" #include "config.hpp" - #include #include #include -#include -#include - +#include #include "libs/linenoise.h" -#define CLR_RESET "\x1b[0m" -#define CLR_CYAN "\x1b[36m" +static const char* asciiArt = +" (`-') _ (`-') <-.(`-') (`-') _ (`-') (`-').->\n" +" _ ( OO).-/<-.(OO ) __( OO) ( OO).-/<-.(OO ) .-> ( OO)_ \n" +" \\-,-----.(,------.,------,)'-'---.\\ (,------.,------,),--.(,--. (_)--\\_) \n" +" | .--./ | .---'| /`. '| .-. (/ | .---'| /`. '| | |(`-')/ _ / \n" +" /_) (`-')(| '--. | |_.' || '-' `.)(| '--. | |_.' || | |(OO )\\_..`--. \n" +" || |OO ) | .--' | . .'| /`'. | | .--' | . .'| | | | \\.-._) \\\n" +"(_' '--'\\ | `---.| |\\ \\ | '--' / | `---.| |\\ \\ \\ '-'(_ .'\\ /\n" +" `-----' `------'`--' '--'`------' `------'`--' '--' `-----' `-----'\n"; -static void completionCallback(const char *input, linenoiseCompletions *completions) { - if (strncmp(input, "nick", 4) == 0) { - linenoiseAddCompletion(completions, "nick set "); - linenoiseAddCompletion(completions, "nick generatekey"); - } - else if (strncmp(input, "web", 3) == 0) { - linenoiseAddCompletion(completions, "web start"); - linenoiseAddCompletion(completions, "web connect pm 127.0.0.1"); - linenoiseAddCompletion(completions, "web stop"); - } - else if (strncmp(input, "sound", 5) == 0) { - linenoiseAddCompletion(completions, "sound find"); - linenoiseAddCompletion(completions, "sound lose"); - } +static void completionCallback(const char *input, linenoiseCompletions *lc) { + if(strncmp(input,"nick ",5)==0) linenoiseAddCompletion(lc,"nick set "); + else if(strncmp(input,"nick g",6)==0) linenoiseAddCompletion(lc,"nick generatekey"); + else if(strncmp(input,"web s",5)==0) linenoiseAddCompletion(lc,"web start"); + else if(strncmp(input,"web c",5)==0) linenoiseAddCompletion(lc,"web connect pm 127.0.0.1"); + else if(strncmp(input,"web s",5)==0) linenoiseAddCompletion(lc,"web stop"); + else if(strncmp(input,"sound f",7)==0) linenoiseAddCompletion(lc,"sound find"); + else if(strncmp(input,"sound l",7)==0) linenoiseAddCompletion(lc,"sound lose"); + else if(strncmp(input,"cerber ma",9)==0) linenoiseAddCompletion(lc,"cerber maketea [key]"); + else if(strncmp(input,"cerber dr",9)==0) linenoiseAddCompletion(lc,"cerber drinktea [key]"); + else if(strncmp(input,"exit",4)==0) linenoiseAddCompletion(lc,"exit"); } void runCLI(AppConfig &config) { linenoiseHistoryLoad("history.txt"); - linenoiseSetCompletionCallback(completionCallback); - std::cout << CLR_CYAN "Cerberus BFSK Demo (linenoise + color)\n" - << "Доступные команды:\n" + std::cout << asciiArt << "\n" + << CLR_CYAN << "Cerberus BFSK:\n" << " nick set \n" << " nick generatekey\n" - << " web start / web connect pm|server / web stop\n" - << " sound find / sound lose\n" - << " exit\n\n" CLR_RESET; + << " web start/connect/stop\n" + << " sound find/lose\n" + << " cerber maketea [hexKey]\n" + << " cerber drinktea [hexKey]\n" + << " exit\n" + << CLR_RESET; - while (true) { - char *line = linenoise(CLR_CYAN ">_ " CLR_RESET); - if (!line) { - std::cout << "\n[cli] EOF/Ctrl+C - выходим.\n"; - break; - } + while(true){ + char* line = linenoise(">_ "); + if(!line) break; std::string input(line); free(line); - - if (!input.empty()) { + if(!input.empty()){ linenoiseHistoryAdd(input.c_str()); linenoiseHistorySave("history.txt"); - processCommand(input, config); } } -} +} \ No newline at end of file diff --git a/cli.hpp b/cli.hpp index 0a99e81..b228bed 100644 --- a/cli.hpp +++ b/cli.hpp @@ -1,5 +1,4 @@ #pragma once - #include "config.hpp" void runCLI(AppConfig &config); diff --git a/cli.o b/cli.o index b88d378..28dc4c6 100644 Binary files a/cli.o and b/cli.o differ diff --git a/commands.cpp b/commands.cpp index bdc1f5c..d566486 100644 --- a/commands.cpp +++ b/commands.cpp @@ -1,113 +1,207 @@ #include "commands.hpp" #include "config.hpp" -#include "webserver.hpp" -#include "sound.hpp" - #include -#include -#include +#include #include +#include +#include #include - -static std::vector splitTokens(const std::string &line) { - std::istringstream iss(line); - return { std::istream_iterator(iss), - std::istream_iterator() }; +extern "C" { +#include "monocypher.h" } -static void generateKey(AppConfig &config) { - config.key.resize(32); - FILE* f = fopen("/dev/urandom", "rb"); - if (!f) { - std::cerr << CLR_RED "[nick] Не удалось открыть /dev/urandom\n" CLR_RESET; +static const size_t NONCE_SIZE = 24; +static const size_t KEY_SIZE = 32; +static const size_t MAC_SIZE = 16; + +static std::string toHex(const uint8_t* data, size_t len) { + std::ostringstream oss; + oss << std::hex; + for (size_t i=0;i fromHex(const std::string& hex) { + std::vector data; + data.reserve(hex.size()/2); + for(size_t i=0;i buf=fromHex(hex); + if(buf.size()==32){ + for(int i=0;i<32;i++) outKey[i]=buf[i]; + } +} + +static void handleNickCommand(const std::string &args, AppConfig &config) { + std::istringstream iss(args); + std::string sub; + iss >> sub; + if(sub=="set"){ + std::string name; + std::getline(iss,name); + if(!name.empty() && name[0]==' ') name.erase(0,1); + config.nickname=name; + std::cout<<"[nick] set: "<> plaintext; + std::string keyHex; + iss >> keyHex; + uint8_t localKey[32]; + bool useLocal=false; + if(!keyHex.empty()){ + hexStrToKey(keyHex, localKey); + useLocal=true; + } + if(!config.haveSharedSecret && !useLocal){ + FILE* f=fopen("/dev/urandom","rb"); + if(!f)return; + fread(config.sharedSecret,1,KEY_SIZE,f); + fclose(f); + config.haveSharedSecret=true; + std::cout<<"[makeTea] No key found, random generated: "< nonce(NONCE_SIZE), mac(MAC_SIZE); + std::vector ciphertext(plaintext.size()); + { + FILE* f=fopen("/dev/urandom","rb"); + fread(nonce.data(),1,NONCE_SIZE,f); + fclose(f); + } + const uint8_t* usedKey= useLocal? localKey : config.sharedSecret; + crypto_aead_lock( + ciphertext.data(), + mac.data(), + usedKey, + nonce.data(), + nullptr,0, + (const uint8_t*)plaintext.data(), + plaintext.size() + ); + std::vector out; + out.insert(out.end(),nonce.begin(),nonce.end()); + out.insert(out.end(),mac.begin(),mac.end()); + out.insert(out.end(),ciphertext.begin(),ciphertext.end()); + std::cout<<"[makeTea] keyUsed="<> hexIn; + std::string keyHex; + iss >> keyHex; + uint8_t localKey[32]; + bool useLocal=false; + if(!keyHex.empty()){ + hexStrToKey(keyHex, localKey); + useLocal=true; + } + if(!config.haveSharedSecret && !useLocal) return; + auto data=fromHex(hexIn); + if(data.size() nonce(data.begin(), data.begin()+NONCE_SIZE); + std::vector mac(data.begin()+NONCE_SIZE, data.begin()+NONCE_SIZE+MAC_SIZE); + std::vector cipher(data.begin()+NONCE_SIZE+MAC_SIZE, data.end()); + std::vector plain(cipher.size()); + const uint8_t* usedKey= useLocal? localKey : config.sharedSecret; + int rc=crypto_aead_unlock( + plain.data(), + mac.data(), + usedKey, + nonce.data(), + nullptr,0, + cipher.data(), + cipher.size() + ); + if(rc!=0){ + std::cerr<<"[drinkTea] MAC error\n"; return; } - fread(config.key.data(), 1, 32, f); - fclose(f); - - std::cout << CLR_GREEN "[nick] 256-битный ключ сгенерирован!\n" CLR_RESET; + std::string s((char*)plain.data(),plain.size()); + std::cout<<"[drinkTea] keyUsed="<, generatekey\n" CLR_RESET; - return; - } - std::string sub = tokens[1]; - if (sub == "set") { - if (tokens.size() < 3) { - std::cout << CLR_YELLOW "[nick] Использование: nick set \n" CLR_RESET; - return; - } - std::string newNick; - for (size_t i = 2; i < tokens.size(); i++) { - if (i > 2) newNick += " "; - newNick += tokens[i]; - } - config.nickname = newNick; - std::cout << CLR_GREEN "[nick] Установлен ник: " << newNick << "\n" CLR_RESET; - } - else if (sub == "generatekey") { - generateKey(config); - } - else { - std::cout << CLR_YELLOW "[nick] Неизвестная подкоманда: " << sub << "\n" CLR_RESET; - } +void processCommand(const std::string& input, AppConfig& config) { + if(input.rfind("nick ",0)==0){ + handleNickCommand(input.substr(5), config); + return; } - else if (cmd == "web") { - if (tokens.size() < 2) { - std::cout << CLR_YELLOW "[web] Доступно: start, connect pm|server , stop\n" CLR_RESET; - return; - } - std::string sub = tokens[1]; - if (sub == "start") { - webServerStart(config); - } - else if (sub == "connect") { - if (tokens.size() < 4) { - std::cout << CLR_YELLOW "[web] Использование: web connect \n" CLR_RESET; - return; - } - std::string ctype = tokens[2]; - std::string ip = tokens[3]; - webServerConnect(config, ctype, ip); - } - else if (sub == "stop") { - webServerStop(config); - } - else { - std::cout << CLR_YELLOW "[web] Неизвестная подкоманда: " << sub << "\n" CLR_RESET; - } + if(input.rfind("web ",0)==0){ + handleWebCommand(input.substr(4), config); + return; } - else if (cmd == "sound") { - if (tokens.size() < 2) { - std::cout << CLR_YELLOW "[sound] Доступно: find, lose\n" CLR_RESET; - return; - } - std::string sub = tokens[1]; - if (sub == "find") { - soundFind(config); - } - else if (sub == "lose") { - soundLose(config); - } - else { - std::cout << CLR_YELLOW "[sound] Неизвестная подкоманда: " << sub << "\n" CLR_RESET; - } + if(input.rfind("sound ",0)==0){ + handleSoundCommand(input.substr(6), config); + return; } - else if (cmd == "exit") { - std::cout << CLR_CYAN "[cli] Завершаем работу по команде 'exit'\n" CLR_RESET; + if(input.rfind("cerber maketea ",0)==0){ + handleMakeTea(input.substr(15), config); + return; + } + if(input.rfind("cerber drinktea ",0)==0){ + handleDrinkTea(input.substr(16), config); + return; + } + if(input=="exit"){ + std::cout<<"[cli] exit\n"; exit(0); } - else { - std::cout << CLR_RED "Неизвестная команда: " << cmd << CLR_RESET << "\n"; + std::cout<<"[cli] Unknown: "<>cmd; + if(cmd=="start"){ + extern void webServerStart(AppConfig&); + webServerStart(config); + } else if(cmd=="connect"){ + std::string t,ip; iss>>t>>ip; + extern void webServerConnect(AppConfig&,const std::string&,const std::string&); + webServerConnect(config,t,ip); + } else if(cmd=="stop"){ + extern void webServerStop(AppConfig&); + webServerStop(config); + } +} + +static void handleSoundCommand(const std::string &args, AppConfig &config){ + std::istringstream iss(args); + std::string cmd; iss>>cmd; + if(cmd=="find"){ + extern void soundFind(AppConfig&); + soundFind(config); + } else if(cmd=="lose"){ + extern void soundLose(AppConfig&); + soundLose(config); } } diff --git a/commands.hpp b/commands.hpp index c141c34..c9175b5 100644 --- a/commands.hpp +++ b/commands.hpp @@ -1,6 +1,5 @@ #pragma once - #include -#include "config.hpp" -void processCommand(const std::string &input, AppConfig &config); +struct AppConfig; +void processCommand(const std::string& input, AppConfig& config); diff --git a/commands.o b/commands.o index 8f7a2c3..c1a2cf1 100644 Binary files a/commands.o and b/commands.o differ diff --git a/config.hpp b/config.hpp index 6317f3e..6d3ee4c 100644 --- a/config.hpp +++ b/config.hpp @@ -1,30 +1,22 @@ #pragma once #include -#include #include -#define CLR_RESET "\x1b[0m" -#define CLR_BOLD "\x1b[1m" -#define CLR_RED "\x1b[31m" -#define CLR_GREEN "\x1b[32m" -#define CLR_YELLOW "\x1b[33m" -#define CLR_BLUE "\x1b[34m" -#define CLR_MAGENTA "\x1b[35m" -#define CLR_CYAN "\x1b[36m" -#define CLR_WHITE "\x1b[37m" +#define CLR_RESET "\x1b[0m" +#define CLR_BOLD "\x1b[1m" +#define CLR_RED "\x1b[31m" +#define CLR_GREEN "\x1b[32m" +#define CLR_YELLOW "\x1b[33m" +#define CLR_BLUE "\x1b[34m" +#define CLR_CYAN "\x1b[36m" struct AppConfig { - std::string nickname = "noname"; - - std::vector key; - - bool webServerRunning = false; - bool soundExchangeActive = false; - - + std::string nickname; + bool webServerRunning; + bool soundExchangeActive; uint8_t ephemeralSec[32]; uint8_t ephemeralPub[32]; - uint8_t sharedSecret[32]; - bool haveSharedSecret = false; + bool haveSharedSecret; + AppConfig(): nickname("noname"), webServerRunning(false), soundExchangeActive(false), haveSharedSecret(false) {} }; diff --git a/history.txt b/history.txt index 9198e9f..727c8c0 100644 --- a/history.txt +++ b/history.txt @@ -13,3 +13,59 @@ web find web find sound find exit +sound find +sound lose +exit +ls +help +sound +nick set +nick set platon +nick generatekey +cerber maketea +cerber maketea aboba +cerber drinktea fa93d14d8702e215e805098b5ab58c518bf082c6e882bc6952674750b600000000000000000000005167bc15e8 +sound find +sound find +sound lose +exirt +exit +sound find +sound lose +exit +nick set platon +nick generatekey +nick maketea textual +cerber maketea xuy +cerber drinktea 60551f937ad549d2aa2492e05ba684acc67a90f95ab713bcdce90200000000000000000000000000a86932 +nick generatekey +cerber maketea mother +cerber drinktea a13f5ea8ff23673d45c7e43f690752e9d48360a00a576554b80829668888a1e3bcbec311c5c8afad373e62289c57 +nick set Alice +nick generatekey +cerber maketea Hi +nick set Bob +nick generatekey +cerber drinktea 930bd444ebfb9794517067f83a0c50ec678ed8b2632ba7c69201f76b62a43b395457eba05939b7c78ca6 +exit +nick generatekey +cerber maketea hi +cerber drinktea 1d5068faafb248389fc305fef3df85d9bd2cbc93f552cfe77a7521ed4a1cbf27c985dc48865f45e13b05 +nick set bob +nick generatekey +cerber drinktea 1d5068faafb248389fc305fef3df85d9bd2cbc93f552cfe77a7521ed4a1cbf27c985dc48865f45e13b05 +nick set noname +nick generatekey +cerber drinktea 1d5068faafb248389fc305fef3df85d9bd2cbc93f552cfe77a7521ed4a1cbf27c985dc48865f45e13b05 +exit +exit +nick generatekey +exit +cerber maketea pidor +cerber drinktea 4c2f53f936e6d576e54e5a0ae88c9e87441fc77d852c0461b5cfb8a14358c929407a181a2f65ea93528f741057 +exit +nick generatekey +cerber maketea penis 424cbf882606a41382aad5ce96d24688e04c7adf6cceca8d57bcb6a83a02adcb +cerber drinktea 209a9ef75a9a84434bb9ec84cd71c6fc0b6024da3f9ea550b4bb868f5efed3400cb06f4623a904618cb9317f35 keyUsed=424cbf882606a41382aad5ce96d24688e04c7adf6cceca8d57bcb6a83a02adcb +cerber drinktea 209a9ef75a9a84434bb9ec84cd71c6fc0b6024da3f9ea550b4bb868f5efed3400cb06f4623a904618cb9317f35 424cbf882606a41382aad5ce96d24688e04c7adf6cceca8d57bcb6a83a02adcb +exit diff --git a/main.o b/main.o index b83f800..ecf8d7b 100644 Binary files a/main.o and b/main.o differ diff --git a/sound.cpp b/sound.cpp index c94f749..f11643f 100644 --- a/sound.cpp +++ b/sound.cpp @@ -1,180 +1,95 @@ - #include "sound.hpp" #include "bfsk.hpp" #include "config.hpp" #include "x25519_handshake.hpp" - #include #include #include #include #include +#include -#include - -extern "C" { -#include "monocypher.h" -} - -constexpr int CAPTURE_SECONDS = 3; - +constexpr int CAPTURE_SECONDS=3; static std::atomic gSoundActive{false}; static std::thread gSoundThread; - static std::vector gInputBuffer; -static size_t gWritePos = 0; - +static size_t gWritePos=0; static std::vector gOutputBuffer; -static size_t gReadPos = 0; +static size_t gReadPos=0; -static int audioCallback(const void *input, - void *output, - unsigned long frameCount, - const PaStreamCallbackTimeInfo* timeInfo, - PaStreamCallbackFlags statusFlags, - void *userData) -{ - (void)timeInfo; (void)statusFlags; (void)userData; - const float *in = static_cast(input); - float *out = static_cast(output); - - for (unsigned long i = 0; i < frameCount; i++) { - if (gWritePos < gInputBuffer.size()) { - gInputBuffer[gWritePos++] = in ? in[i] : 0.0f; +static int audioCallback(const void *input,void *output,unsigned long frameCount,const PaStreamCallbackTimeInfo*,PaStreamCallbackFlags,void*){ + const float *in=(const float*)input; + float *out=(float*)output; + for(unsigned long i=0;idefaultLowInputLatency; - inParams.hostApiSpecificStreamInfo = nullptr; - - outParams.device = Pa_GetDefaultOutputDevice(); - if (outParams.device == paNoDevice) { - std::cerr << CLR_RED "[sound] Нет устройства вывода.\n" CLR_RESET; - Pa_Terminate(); - return; - } - outParams.channelCount = 2; - outParams.sampleFormat = paFloat32; - outParams.suggestedLatency = Pa_GetDeviceInfo(outParams.device)->defaultLowOutputLatency; - outParams.hostApiSpecificStreamInfo = nullptr; - - PaStream *stream = nullptr; - - err = Pa_OpenStream(&stream, - &inParams, - &outParams, - SAMPLE_RATE, - 256, - paNoFlag, - audioCallback, - nullptr); - if (err != paNoError) { - std::cerr << CLR_RED "[sound] Pa_OpenStream error: " << Pa_GetErrorText(err) << CLR_RESET "\n"; - Pa_Terminate(); - return; - } - - err = Pa_StartStream(stream); - if (err != paNoError) { - std::cerr << CLR_RED "[sound] Pa_StartStream error: " << Pa_GetErrorText(err) << CLR_RESET "\n"; - Pa_CloseStream(stream); - Pa_Terminate(); - return; - } - - std::cout << CLR_BLUE "[sound] Старт записи/воспроизведения (3 сек)...\n" CLR_RESET; - Pa_Sleep(CAPTURE_SECONDS * 1000); - +static void soundThreadFunc(AppConfig config){ + PaError err=Pa_Initialize(); + if(err!=paNoError)return; + PaStreamParameters inParams,outParams; + inParams.device=Pa_GetDefaultInputDevice(); + if(inParams.device==paNoDevice){Pa_Terminate();return;} + inParams.channelCount=1; + inParams.sampleFormat=paFloat32; + inParams.suggestedLatency=Pa_GetDeviceInfo(inParams.device)->defaultLowInputLatency; + inParams.hostApiSpecificStreamInfo=nullptr; + outParams.device=Pa_GetDefaultOutputDevice(); + if(outParams.device==paNoDevice){Pa_Terminate();return;} + outParams.channelCount=2; + outParams.sampleFormat=paFloat32; + outParams.suggestedLatency=Pa_GetDeviceInfo(outParams.device)->defaultLowOutputLatency; + outParams.hostApiSpecificStreamInfo=nullptr; + PaStream* stream=nullptr; + err=Pa_OpenStream(&stream,&inParams,&outParams,SAMPLE_RATE,256,paNoFlag,audioCallback,nullptr); + if(err!=paNoError){Pa_Terminate();return;} + err=Pa_StartStream(stream); + if(err!=paNoError){Pa_CloseStream(stream);Pa_Terminate();return;} + Pa_Sleep(CAPTURE_SECONDS*1000); Pa_StopStream(stream); Pa_CloseStream(stream); Pa_Terminate(); - - std::cout << CLR_BLUE "[sound] Остановка аудиопотока...\n" CLR_RESET; - - auto received = bfskDemodulate(gInputBuffer); - if (!received.empty()) { - if (received.size() >= 33 && received[0] == 'E') { + auto received=bfskDemodulate(gInputBuffer); + if(!received.empty()){ + if(received.size()>=33 && received[0]=='E'){ uint8_t otherPub[32]; - std::memcpy(otherPub, received.data() + 1, 32); - - x25519ComputeShared(config, otherPub); - std::cout << CLR_GREEN "[x25519] Общий сеансовый ключ вычислен!\n" CLR_RESET; - } else { - std::cout << CLR_YELLOW "[sound] Получены " << received.size() - << " байт, но не формат 'E' + 32 байта.\n" CLR_RESET; + for(int i=0;i<32;i++){ + otherPub[i]=received[1+i]; + } + x25519ComputeShared(config,otherPub); } - } else { - std::cout << CLR_YELLOW "[sound] Ничего не демодулировано.\n" CLR_RESET; } - - gSoundActive = false; + gSoundActive=false; } -void soundFind(AppConfig &config) { - if (config.soundExchangeActive) { - std::cout << CLR_YELLOW "[sound] Уже идёт процесс.\n" CLR_RESET; - return; - } - config.soundExchangeActive = true; - gSoundActive = true; - +void soundFind(AppConfig &config){ + if(config.soundExchangeActive)return; + config.soundExchangeActive=true; + gSoundActive=true; x25519GenerateEphemeral(config); - - std::vector packet; - packet.push_back('E'); - packet.insert(packet.end(), config.ephemeralPub, config.ephemeralPub + 32); - - gOutputBuffer = bfskModulate(packet); - gReadPos = 0; - + std::vector packet;packet.push_back('E'); + packet.insert(packet.end(),config.ephemeralPub,config.ephemeralPub+32); + gOutputBuffer=bfskModulate(packet); + gReadPos=0; gInputBuffer.clear(); - gInputBuffer.resize(SAMPLE_RATE * CAPTURE_SECONDS, 0.0f); - gWritePos = 0; - - gSoundThread = std::thread(soundThreadFunc, config); - - std::cout << CLR_GREEN "[sound] Отправляем свой публичный ключ X25519 и слушаем!\n" CLR_RESET; + gInputBuffer.resize(SAMPLE_RATE*CAPTURE_SECONDS,0.0f); + gWritePos=0; + gSoundThread=std::thread(soundThreadFunc,config); } -void soundLose(AppConfig &config) { - if (!config.soundExchangeActive) { - std::cout << CLR_YELLOW "[sound] Процесс не активен.\n" CLR_RESET; - return; - } - config.soundExchangeActive = false; - - if (gSoundActive) { - gSoundActive = false; - } - if (gSoundThread.joinable()) { - gSoundThread.join(); - } - std::cout << CLR_GREEN "[sound] Процесс остановлен.\n" CLR_RESET; +void soundLose(AppConfig &config){ + if(!config.soundExchangeActive)return; + config.soundExchangeActive=false; + if(gSoundActive)gSoundActive=false; + if(gSoundThread.joinable())gSoundThread.join(); } diff --git a/sound.hpp b/sound.hpp index 814d9f2..8710e6f 100644 --- a/sound.hpp +++ b/sound.hpp @@ -2,5 +2,4 @@ #include "config.hpp" void soundFind(AppConfig &config); - void soundLose(AppConfig &config); diff --git a/sound.o b/sound.o index b3a6902..ae3e133 100644 Binary files a/sound.o and b/sound.o differ diff --git a/webserver.cpp b/webserver.cpp index 972593e..2b6bbe5 100644 --- a/webserver.cpp +++ b/webserver.cpp @@ -1,66 +1,40 @@ #include "webserver.hpp" #include "config.hpp" - #include #include #include - #include "libs/httplib.h" static std::atomic g_serverRunning{false}; static std::thread g_serverThread; -static void serverThreadFunc() { +static void serverThreadFunc(){ httplib::Server svr; - svr.Get("/", [](const httplib::Request&, httplib::Response &res){ - res.set_content("Hello from Cerberus BFSK!", "text/plain"); + svr.Get("/",[](const httplib::Request&,httplib::Response &res){ + res.set_content("Hello from Cerberus BFSK!","text/plain"); }); - - if (!svr.listen("0.0.0.0", 8080)) { - std::cerr << CLR_RED "[web] Ошибка listen(8080). Возможно, порт занят.\n" CLR_RESET; - } - g_serverRunning = false; + if(!svr.listen("0.0.0.0",8080)){} + g_serverRunning=false; } -void webServerStart(AppConfig &config) { - if (config.webServerRunning) { - std::cout << CLR_YELLOW "[web] Сервер уже запущен.\n" CLR_RESET; - return; - } - g_serverRunning = true; - g_serverThread = std::thread(serverThreadFunc); - - config.webServerRunning = true; - std::cout << CLR_GREEN "[web] Сервер запущен на порту 8080.\n" CLR_RESET; +void webServerStart(AppConfig &config){ + if(config.webServerRunning)return; + g_serverRunning=true; + g_serverThread=std::thread(serverThreadFunc); + config.webServerRunning=true; } -void webServerConnect(AppConfig &config, const std::string &type, const std::string &ip) { - if (!config.webServerRunning) { - std::cout << CLR_YELLOW "[web] Сначала запустите сервер (web start)\n" CLR_RESET; - return; - } - httplib::Client cli(ip.c_str(), 8080); - if (auto res = cli.Get("/")) { - if (res->status == 200) { - std::cout << CLR_CYAN "[web] Ответ от " << ip << ": " << res->body << CLR_RESET "\n"; - } else { - std::cout << CLR_YELLOW "[web] Подключились, статус: " << res->status << CLR_RESET "\n"; - } - } else { - std::cout << CLR_RED "[web] Не удалось подключиться к " << ip << ":8080.\n" CLR_RESET; +void webServerConnect(AppConfig &config,const std::string &type,const std::string &ip){ + if(!config.webServerRunning)return; + httplib::Client cli(ip.c_str(),8080); + if(auto res=cli.Get("/")){ + if(res->status==200){} } } -void webServerStop(AppConfig &config) { - if (!config.webServerRunning) { - std::cout << CLR_YELLOW "[web] Сервер не запущен.\n" CLR_RESET; - return; - } - g_serverRunning = false; - if (g_serverThread.joinable()) { - g_serverThread.detach(); - } - - config.webServerRunning = false; - std::cout << CLR_GREEN "[web] Сервер остановлен (демо).\n" CLR_RESET; +void webServerStop(AppConfig &config){ + if(!config.webServerRunning)return; + if(g_serverThread.joinable())g_serverThread.detach(); + g_serverRunning=false; + config.webServerRunning=false; } diff --git a/webserver.hpp b/webserver.hpp index 5cedbc8..e6f5a8b 100644 --- a/webserver.hpp +++ b/webserver.hpp @@ -3,5 +3,5 @@ #include void webServerStart(AppConfig &config); -void webServerConnect(AppConfig &config, const std::string &type, const std::string &ip); +void webServerConnect(AppConfig &config,const std::string &type,const std::string &ip); void webServerStop(AppConfig &config); diff --git a/webserver.o b/webserver.o index a2420d3..13629c7 100644 Binary files a/webserver.o and b/webserver.o differ diff --git a/x25519_handshake.cpp b/x25519_handshake.cpp index 2306eb1..6a2d87b 100644 --- a/x25519_handshake.cpp +++ b/x25519_handshake.cpp @@ -1,38 +1,25 @@ #include "x25519_handshake.hpp" -#include "config.hpp" - -#include // Для std::memcpy и std::memset +#include +#include #include - -// Подключаем Monocypher extern "C" { #include "monocypher.h" } -void x25519GenerateEphemeral(AppConfig &config) { - FILE* f = fopen("/dev/urandom", "rb"); - if (!f) { - std::cerr << CLR_RED "[x25519] Не удалось открыть /dev/urandom\n" CLR_RESET; - return; - } - size_t read = fread(config.ephemeralSec, 1, 32, f); +void x25519GenerateEphemeral(AppConfig &config){ + FILE* f=fopen("/dev/urandom","rb"); + if(!f)return; + fread(config.ephemeralSec,1,32,f); fclose(f); - if (read != 32) { - std::cerr << CLR_RED "[x25519] Не удалось прочитать 32 байта из /dev/urandom\n" CLR_RESET; - return; - } - - crypto_x25519_public_key(config.ephemeralPub, config.ephemeralSec); - - std::memset(config.sharedSecret, 0, 32); - config.haveSharedSecret = false; + crypto_x25519_public_key(config.ephemeralPub,config.ephemeralSec); + std::memset(config.sharedSecret,0,32); + config.haveSharedSecret=false; } -void x25519ComputeShared(AppConfig &config, const uint8_t otherPub[32]) { +void x25519ComputeShared(AppConfig &config,const uint8_t otherPub[32]){ uint8_t shared[32]; - crypto_x25519(shared, config.ephemeralSec, otherPub); - std::memcpy(config.sharedSecret, shared, 32); - - config.haveSharedSecret = true; - std::cout << CLR_GREEN "[x25519] Общий сеансовый ключ вычислен!\n" CLR_RESET; + crypto_x25519(shared,config.ephemeralSec,otherPub); + std::memcpy(config.sharedSecret,shared,32); + config.haveSharedSecret=true; + std::cout< -#include - #include "config.hpp" void x25519GenerateEphemeral(AppConfig &config); - -void x25519ComputeShared(AppConfig &config, const uint8_t otherPub[32]); +void x25519ComputeShared(AppConfig &config,const uint8_t otherPub[32]); diff --git a/x25519_handshake.o b/x25519_handshake.o index 996b2c1..a471faa 100644 Binary files a/x25519_handshake.o and b/x25519_handshake.o differ