upd
This commit is contained in:
parent
7ed2435811
commit
118875234a
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.o
|
||||
cerberus
|
48
Makefile
48
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
|
||||
|
105
bfsk.cpp
105
bfsk.cpp
@ -1,78 +1,53 @@
|
||||
#include "bfsk.hpp"
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
std::vector<float> bfskModulate(const std::vector<unsigned char> &data) {
|
||||
int samplesPerBit = (int)((double)SAMPLE_RATE / BFSK_BAUD);
|
||||
size_t totalBits = data.size() * 8;
|
||||
size_t totalSamples = totalBits * samplesPerBit;
|
||||
std::vector<float> 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<float> bfskModulate(const std::vector<uint8_t> &data){
|
||||
int spb=(int)(SAMPLE_RATE/BFSK_BAUD);
|
||||
size_t tb=data.size()*8;
|
||||
size_t ts=tb*spb;
|
||||
std::vector<float> 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<spb;s++){
|
||||
float val=bit? sinf((float)phase1): sinf((float)phase0);
|
||||
if(bit) phase1+=inc1; else phase0+=inc0;
|
||||
out[idx*2+0]=val*0.3f;
|
||||
out[idx*2+1]=val*0.3f;
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> bfskDemodulate(const std::vector<float> &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<unsigned char> 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<uint8_t> bfskDemodulate(const std::vector<float> &monoData){
|
||||
int spb=(int)(SAMPLE_RATE/BFSK_BAUD);
|
||||
size_t tb=monoData.size()/spb;
|
||||
size_t tbytes=tb/8;
|
||||
std::vector<uint8_t> 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<tb;b++){
|
||||
double sum0=0.0,sum1=0.0;
|
||||
double ph0=0.0,ph1=0.0;
|
||||
size_t st=b*spb;
|
||||
for(int s=0;s<spb;s++){
|
||||
float sample=monoData[st+s];
|
||||
float r0=sinf((float)ph0), r1=sinf((float)ph1);
|
||||
sum0+=sample*r0; sum1+=sample*r1;
|
||||
ph0+=inc0; ph1+=inc1;
|
||||
}
|
||||
|
||||
int bit = (std::fabs(sum1) > 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<res.size()) res[bytePos]|=(bit<<bitPos);
|
||||
bitIdx++;
|
||||
}
|
||||
|
||||
return result;
|
||||
return res;
|
||||
}
|
||||
|
14
bfsk.hpp
14
bfsk.hpp
@ -1,11 +1,11 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
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<float> bfskModulate(const std::vector<unsigned char> &data);
|
||||
|
||||
std::vector<unsigned char> bfskDemodulate(const std::vector<float> &monoData);
|
||||
std::vector<float> bfskModulate(const std::vector<uint8_t> &data);
|
||||
std::vector<uint8_t> bfskDemodulate(const std::vector<float> &monoData);
|
||||
|
66
cli.cpp
66
cli.cpp
@ -1,60 +1,58 @@
|
||||
#include "cli.hpp"
|
||||
#include "commands.hpp"
|
||||
#include "config.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
#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 <text> [key]");
|
||||
else if(strncmp(input,"cerber dr",9)==0) linenoiseAddCompletion(lc,"cerber drinktea <hex> [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 <usernick>\n"
|
||||
<< " nick generatekey\n"
|
||||
<< " web start / web connect pm|server <ip> / web stop\n"
|
||||
<< " sound find / sound lose\n"
|
||||
<< " exit\n\n" CLR_RESET;
|
||||
<< " web start/connect/stop\n"
|
||||
<< " sound find/lose\n"
|
||||
<< " cerber maketea <text> [hexKey]\n"
|
||||
<< " cerber drinktea <hex> [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);
|
||||
}
|
||||
}
|
||||
|
1
cli.hpp
1
cli.hpp
@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
void runCLI(AppConfig &config);
|
||||
|
284
commands.cpp
284
commands.cpp
@ -1,113 +1,207 @@
|
||||
#include "commands.hpp"
|
||||
#include "config.hpp"
|
||||
#include "webserver.hpp"
|
||||
#include "sound.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <cstdio>
|
||||
|
||||
static std::vector<std::string> splitTokens(const std::string &line) {
|
||||
std::istringstream iss(line);
|
||||
return { std::istream_iterator<std::string>(iss),
|
||||
std::istream_iterator<std::string>() };
|
||||
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<len;i++){
|
||||
oss << std::setw(2)<<std::setfill('0')<<(int)data[i];
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
static std::vector<uint8_t> fromHex(const std::string& hex) {
|
||||
std::vector<uint8_t> data;
|
||||
data.reserve(hex.size()/2);
|
||||
for(size_t i=0;i<hex.size();i+=2){
|
||||
uint8_t val=(uint8_t)std::stoi(hex.substr(i,2),nullptr,16);
|
||||
data.push_back(val);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
static void hexStrToKey(const std::string &hex, uint8_t outKey[32]) {
|
||||
std::vector<uint8_t> 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: "<<config.nickname<<"\n";
|
||||
} else if(sub=="generatekey"){
|
||||
FILE* f=fopen("/dev/urandom","rb");
|
||||
if(!f)return;
|
||||
fread(config.sharedSecret,1,KEY_SIZE,f);
|
||||
fclose(f);
|
||||
config.haveSharedSecret=true;
|
||||
std::cout<<"[nick] 256-bit key generated: "<<toHex(config.sharedSecret,32)<<"\n";
|
||||
}
|
||||
}
|
||||
|
||||
static void handleWebCommand(const std::string &args, AppConfig &config);
|
||||
static void handleSoundCommand(const std::string &args, AppConfig &config);
|
||||
|
||||
static void handleMakeTea(const std::string& input, AppConfig& config) {
|
||||
std::istringstream iss(input);
|
||||
std::string plaintext;
|
||||
iss >> 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: "<<toHex(config.sharedSecret,32)<<"\n";
|
||||
}
|
||||
std::vector<uint8_t> nonce(NONCE_SIZE), mac(MAC_SIZE);
|
||||
std::vector<uint8_t> 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<uint8_t> 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="<<toHex(usedKey,32)<<"\n";
|
||||
std::ostringstream oss;
|
||||
for(auto &x: out){
|
||||
oss<<std::hex<<std::setw(2)<<std::setfill('0')<<(int)x;
|
||||
}
|
||||
std::cout<<"[makeTea] encrypted: "<<oss.str()<<"\n";
|
||||
}
|
||||
|
||||
static void handleDrinkTea(const std::string& input, AppConfig& config) {
|
||||
std::istringstream iss(input);
|
||||
std::string hexIn;
|
||||
iss >> 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_SIZE+MAC_SIZE) return;
|
||||
std::vector<uint8_t> nonce(data.begin(), data.begin()+NONCE_SIZE);
|
||||
std::vector<uint8_t> mac(data.begin()+NONCE_SIZE, data.begin()+NONCE_SIZE+MAC_SIZE);
|
||||
std::vector<uint8_t> cipher(data.begin()+NONCE_SIZE+MAC_SIZE, data.end());
|
||||
std::vector<uint8_t> 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="<<toHex(usedKey,32)<<"\n";
|
||||
std::cout<<"[drinkTea] decrypted: "<<s<<"\n";
|
||||
}
|
||||
|
||||
void processCommand(const std::string &input, AppConfig &config) {
|
||||
if (input.empty()) return;
|
||||
|
||||
auto tokens = splitTokens(input);
|
||||
if (tokens.empty()) return;
|
||||
|
||||
std::string cmd = tokens[0];
|
||||
|
||||
if (cmd == "nick") {
|
||||
if (tokens.size() < 2) {
|
||||
std::cout << CLR_YELLOW "[nick] Доступно: set <name>, generatekey\n" CLR_RESET;
|
||||
return;
|
||||
}
|
||||
std::string sub = tokens[1];
|
||||
if (sub == "set") {
|
||||
if (tokens.size() < 3) {
|
||||
std::cout << CLR_YELLOW "[nick] Использование: nick set <usernick>\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 <ip>, 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 <pm|server> <ip>\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: "<<input<<"\n";
|
||||
}
|
||||
|
||||
static void handleWebCommand(const std::string &args, AppConfig &config){
|
||||
std::istringstream iss(args);
|
||||
std::string cmd; iss>>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);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "config.hpp"
|
||||
|
||||
void processCommand(const std::string &input, AppConfig &config);
|
||||
struct AppConfig;
|
||||
void processCommand(const std::string& input, AppConfig& config);
|
||||
|
BIN
commands.o
BIN
commands.o
Binary file not shown.
32
config.hpp
32
config.hpp
@ -1,30 +1,22 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
#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<unsigned char> 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) {}
|
||||
};
|
||||
|
56
history.txt
56
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
|
||||
|
205
sound.cpp
205
sound.cpp
@ -1,180 +1,95 @@
|
||||
|
||||
#include "sound.hpp"
|
||||
#include "bfsk.hpp"
|
||||
#include "config.hpp"
|
||||
#include "x25519_handshake.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include <portaudio.h>
|
||||
|
||||
extern "C" {
|
||||
#include "monocypher.h"
|
||||
}
|
||||
|
||||
constexpr int CAPTURE_SECONDS = 3;
|
||||
|
||||
constexpr int CAPTURE_SECONDS=3;
|
||||
static std::atomic<bool> gSoundActive{false};
|
||||
static std::thread gSoundThread;
|
||||
|
||||
static std::vector<float> gInputBuffer;
|
||||
static size_t gWritePos = 0;
|
||||
|
||||
static size_t gWritePos=0;
|
||||
static std::vector<float> 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<const float*>(input);
|
||||
float *out = static_cast<float*>(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;i<frameCount;i++){
|
||||
if(gWritePos<gInputBuffer.size()){
|
||||
gInputBuffer[gWritePos++]=in?in[i]:0.0f;
|
||||
}
|
||||
|
||||
float sample = 0.0f;
|
||||
if (gReadPos < gOutputBuffer.size()) {
|
||||
sample = gOutputBuffer[gReadPos++];
|
||||
float sample=0.0f;
|
||||
if(gReadPos<gOutputBuffer.size()){
|
||||
sample=gOutputBuffer[gReadPos++];
|
||||
}
|
||||
out[i*2 + 0] = sample;
|
||||
out[i*2 + 1] = sample;
|
||||
out[i*2+0]=sample;
|
||||
out[i*2+1]=sample;
|
||||
}
|
||||
|
||||
return paContinue;
|
||||
}
|
||||
|
||||
static void soundThreadFunc(AppConfig config) {
|
||||
PaError err = Pa_Initialize();
|
||||
if (err != paNoError) {
|
||||
std::cerr << CLR_RED "[sound] Pa_Initialize error: " << Pa_GetErrorText(err) << CLR_RESET "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
PaStreamParameters inParams, outParams;
|
||||
|
||||
inParams.device = Pa_GetDefaultInputDevice();
|
||||
if (inParams.device == paNoDevice) {
|
||||
std::cerr << CLR_RED "[sound] Нет устройства ввода.\n" CLR_RESET;
|
||||
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) {
|
||||
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<unsigned char> packet;
|
||||
packet.push_back('E');
|
||||
packet.insert(packet.end(), config.ephemeralPub, config.ephemeralPub + 32);
|
||||
|
||||
gOutputBuffer = bfskModulate(packet);
|
||||
gReadPos = 0;
|
||||
|
||||
std::vector<uint8_t> 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();
|
||||
}
|
||||
|
@ -2,5 +2,4 @@
|
||||
#include "config.hpp"
|
||||
|
||||
void soundFind(AppConfig &config);
|
||||
|
||||
void soundLose(AppConfig &config);
|
||||
|
@ -1,66 +1,40 @@
|
||||
#include "webserver.hpp"
|
||||
#include "config.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
|
||||
#include "libs/httplib.h"
|
||||
|
||||
static std::atomic<bool> 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;
|
||||
}
|
||||
|
@ -3,5 +3,5 @@
|
||||
#include <string>
|
||||
|
||||
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);
|
||||
|
BIN
webserver.o
BIN
webserver.o
Binary file not shown.
@ -1,38 +1,25 @@
|
||||
#include "x25519_handshake.hpp"
|
||||
#include "config.hpp"
|
||||
|
||||
#include <cstring> // Для std::memcpy и std::memset
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
// Подключаем 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<<CLR_GREEN<<"[x25519] key computed!\n"<<CLR_RESET;
|
||||
}
|
||||
|
@ -1,9 +1,6 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#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]);
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user