From 04ed29ceec75e2da087eed95bb6f140dcc594e96 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 17 May 2021 19:47:56 +0300 Subject: [PATCH] add verifyhost tool Signed-off-by: R4SAS --- Makefile | 9 +++-- verifyhost.cpp | 107 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 verifyhost.cpp diff --git a/Makefile b/Makefile index 1b7ea3e..2ec136b 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ ifeq ($(UNAME),Linux) LIBS += -lrt -lpthread else ifeq ($(UNAME),Darwin) LIBS += -lpthread - LDFLAGS += -L/usr/local/opt/openssl@1.1/lib -L/usr/local/lib + LDFLAGS += -L/usr/local/opt/openssl@1.1/lib -L/usr/local/lib INCFLAGS += -I/usr/local/opt/openssl@1.1/include -I/usr/local/include else ifeq ($(UNAME),FreeBSD) LIBS += -lthr -lpthread @@ -41,7 +41,7 @@ else LDFLAGS += -s -Wl,-Bstatic -static-libgcc -static-libstdc++ endif -all: $(I2PD_LIB) keygen keyinfo famtool routerinfo regaddr regaddr_3ld vain i2pbase64 offlinekeys b33address regaddralias x25519 +all: $(I2PD_LIB) keygen keyinfo famtool routerinfo regaddr regaddr_3ld vain i2pbase64 offlinekeys b33address regaddralias x25519 verifyhost routerinfo: routerinfo.o $(I2PD_LIB) $(CXX) -o routerinfo routerinfo.o $(LDFLAGS) $(LIBS) @@ -79,6 +79,9 @@ regaddralias: regaddralias.o $(I2PD_LIB) x25519: x25519.o $(I2PD_LIB) $(CXX) -o x25519 x25519.o $(LDFLAGS) $(LIBS) +verifyhost: verifyhost.o $(I2PD_LIB) + $(CXX) -o verifyhost verifyhost.o $(LDFLAGS) $(LIBS) + .SUFFIXES: .SUFFIXES: .c .cc .C .cpp .o @@ -98,7 +101,7 @@ clean-obj: rm -f $(wildcard *.o) clean-bin: - rm -f b33address famtool i2pbase64 keygen keyinfo offlinekeys regaddr regaddr_3ld regaddralias routerinfo vain x25519 + rm -f b33address famtool i2pbase64 keygen keyinfo offlinekeys regaddr regaddr_3ld regaddralias routerinfo vain x25519 verifyhost clean: clean-i2pd clean-obj clean-bin diff --git a/verifyhost.cpp b/verifyhost.cpp new file mode 100644 index 0000000..59779ac --- /dev/null +++ b/verifyhost.cpp @@ -0,0 +1,107 @@ +#include +#include +#include +#include "Identity.h" +#include "Base.h" + +int main (int argc, char * argv[]) +{ + if (argc < 2) + { + std::cout << "Usage: verifyhost ''" << std::endl; + return -1; + } + + i2p::crypto::InitCrypto (false, true, true, false); + + i2p::data::IdentityEx Identity, OldIdentity; + + std::string str (argv[1]); + std::size_t pos; + + // get record without command block after "#!" + pos = str.find ("#!"); + std::string hostStr = str.substr (0, pos); + + // get host base64 + pos = hostStr.find ("="); + std::string hostBase64 = hostStr.substr (pos + 1); + + // load identity + if (Identity.FromBase64 (hostBase64)) + { + // get record without sig key and signature + pos = str.find ("#sig="); + if (pos == std::string::npos) + { + pos = str.find ("!sig="); + if (pos == std::string::npos) + { + std::cout << "Destination signature not found." << std::endl; + return 1; + } + } + + int offset = (str[pos - 1] == '#' /* only sig in record */) ? 1 : 0; + + std::string hostNoSig = str.substr (0, pos - offset); + std::string sig = str.substr (pos + 5); // after "#sig=" till end + + auto signatureLen = Identity.GetSignatureLen (); + uint8_t * signature = new uint8_t[signatureLen]; + + // validate signature + i2p::data::Base64ToByteStream(sig.c_str (), sig.length(), signature, signatureLen); + if (!Identity.Verify ((uint8_t *)hostNoSig.c_str (), hostNoSig.length (), signature)) + { + std::cout << "Invalid destination signature." << std::endl; + return 1; + } + + if (str.find ("olddest=") != std::string::npos) // if olddest present + { + // get olddest + pos = str.find ("#olddest="); + std::string oldDestCut = str.substr (pos + 9); + pos = oldDestCut.find ("#"); + std::string oldDestBase64 = oldDestCut.substr (0, pos); + + // load identity + if(!OldIdentity.FromBase64 (oldDestBase64)) + { + std::cout << "Invalid old destination base64." << std::endl; + return 1; + } + + signatureLen = OldIdentity.GetSignatureLen (); + signature = new uint8_t[signatureLen]; + + // get record till oldsig key and oldsig + pos = str.find ("#oldsig="); + std::string hostNoOldSig = str.substr (0, pos); + + std::string oldSigCut = str.substr (pos + 8); + pos = oldSigCut.find ("#"); + std::string oldSig = oldSigCut.substr (0, pos); + + // validate signature + i2p::data::Base64ToByteStream(oldSig.c_str (), oldSig.length(), signature, signatureLen); + bool oldSignValid = OldIdentity.Verify ((uint8_t *)hostNoOldSig.c_str (), hostNoOldSig.length (), signature); + + if(!oldSignValid) + { + std::cout << "Invalid old destination signature." << std::endl; + return 1; + } + } + } + else + { + std::cout << "Invalid destination base64." << std::endl; + return 1; + } + + i2p::crypto::TerminateCrypto (); + + return 0; +}