handle and publish NTCP2 address

This commit is contained in:
orignal 2018-06-15 12:52:43 -04:00
parent 2bd7a92d20
commit 706b976a28
4 changed files with 77 additions and 21 deletions

View File

@ -2,6 +2,7 @@
#include <openssl/rand.h>
#include "Config.h"
#include "Crypto.h"
#include "Ed25519.h"
#include "Timestamp.h"
#include "I2NPProtocol.h"
#include "NetDb.hpp"
@ -36,7 +37,7 @@ namespace i2p
void RouterContext::CreateNewRouter ()
{
m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519);
SaveKeys ();
SaveKeys ();
NewRouterInfo ();
}
@ -49,7 +50,8 @@ namespace i2p
port = rand () % (30777 - 9111) + 9111; // I2P network ports range
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
bool nat; i2p::config::GetOption("nat", nat);
bool ntcp2; i2p::config::GetOption("ntcp2", ntcp2);
bool nat; i2p::config::GetOption("nat", nat);
std::string ifname; i2p::config::GetOption("ifname", ifname);
std::string ifname4; i2p::config::GetOption("ifname4", ifname4);
std::string ifname6; i2p::config::GetOption("ifname6", ifname6);
@ -82,6 +84,11 @@ namespace i2p
routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
routerInfo.AddNTCPAddress (host.c_str(), port);
}
if (ntcp2)
{
NewNTCP2Keys ();
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv);
}
routerInfo.SetCaps (i2p::data::RouterInfo::eReachable |
i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer); // LR, BC
@ -102,11 +109,14 @@ namespace i2p
void RouterContext::NewNTCP2Keys ()
{
m_NTCP2Keys.reset (new NTCP2PrivateKeys ());
RAND_bytes (m_NTCP2Keys->staticKey, 32);
RAND_bytes (m_NTCP2Keys->staticPrivateKey, 32);
RAND_bytes (m_NTCP2Keys->iv, 16);
BN_CTX * ctx = BN_CTX_new ();
i2p::crypto::GetEd25519 ()->ScalarMulB (m_NTCP2Keys->staticPrivateKey, m_NTCP2Keys->staticPublicKey, ctx);
BN_CTX_free (ctx);
// save
std::ofstream fk (i2p::fs::DataDirPath (NTCP2_KEYS), std::ofstream::binary | std::ofstream::out);
fk.write ((char *)m_NTCP2Keys.get (), sizeof (NTCP2PrivateKeys));
fk.write ((char *)m_NTCP2Keys.get (), sizeof (NTCP2PrivateKeys));
}
void RouterContext::SetStatus (RouterStatus status)
@ -455,9 +465,13 @@ namespace i2p
m_NTCP2Keys.reset (new NTCP2PrivateKeys ());
n2k.read ((char *)m_NTCP2Keys.get (), sizeof (NTCP2PrivateKeys));
}
n2k.close ();
}
if (!m_NTCP2Keys)
if (!m_NTCP2Keys)
{
NewNTCP2Keys ();
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv);
}
}
return true;

View File

@ -37,7 +37,8 @@ namespace i2p
struct NTCP2PrivateKeys
{
uint8_t staticKey[32];
uint8_t staticPublicKey[32];
uint8_t staticPrivateKey[32];
uint8_t iv[16];
};
@ -58,6 +59,9 @@ namespace i2p
return std::shared_ptr<i2p::garlic::GarlicDestination> (this,
[](i2p::garlic::GarlicDestination *) {});
}
const uint8_t * GetNTCP2StaticPublicKey () const { return m_NTCP2Keys ? m_NTCP2Keys->staticPublicKey : nullptr; };
const uint8_t * GetNTCP2StaticPrivateKey () const { return m_NTCP2Keys ? m_NTCP2Keys->staticPrivateKey : nullptr; };
const uint8_t * GetNTCP2IV () const { return m_NTCP2Keys ? m_NTCP2Keys->iv : nullptr; };
uint32_t GetUptime () const;
uint32_t GetStartupTime () const { return m_StartupTime; };

View File

@ -176,10 +176,14 @@ namespace data
auto address = std::make_shared<Address>();
s.read ((char *)&address->cost, sizeof (address->cost));
s.read ((char *)&address->date, sizeof (address->date));
char transportStyle[5];
ReadString (transportStyle, 5, s);
if (!strcmp (transportStyle, "NTCP"))
bool isNtcp2 = false;
char transportStyle[6];
auto transportStyleLen = ReadString (transportStyle, 6, s) - 1;
if (!strncmp (transportStyle, "NTCP", 4)) // NTCP or NTCP2
{
address->transportStyle = eTransportNTCP;
if (transportStyleLen > 4 || transportStyle[4] == '2') isNtcp2= true;
}
else if (!strcmp (transportStyle, "SSU"))
{
address->transportStyle = eTransportSSU;
@ -288,7 +292,7 @@ namespace data
if (!s) return;
}
if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented
if (supportedTransports)
if (supportedTransports && !isNtcp2) // we ignore NTCP2 addresses for now. TODO:
{
addresses->push_back(address);
m_SupportedTransports |= supportedTransports;
@ -435,7 +439,7 @@ namespace data
s.write ((const char *)&address.date, sizeof (address.date));
std::stringstream properties;
if (address.transportStyle == eTransportNTCP)
WriteString ("NTCP", s);
WriteString (address.IsNTCP2 () ? "NTCP2" : "NTCP", s);
else if (address.transportStyle == eTransportSSU)
{
WriteString ("SSU", s);
@ -451,10 +455,13 @@ namespace data
else
WriteString ("", s);
WriteString ("host", properties);
properties << '=';
WriteString (address.host.to_string (), properties);
properties << ';';
if (!address.IsNTCP2 ()) // we don't publish NTCP2 address fow now. TODO: implement
{
WriteString ("host", properties);
properties << '=';
WriteString (address.host.to_string (), properties);
properties << ';';
}
if (address.transportStyle == eTransportSSU)
{
// write introducers if any
@ -529,10 +536,23 @@ namespace data
properties << ';';
}
}
WriteString ("port", properties);
properties << '=';
WriteString (boost::lexical_cast<std::string>(address.port), properties);
properties << ';';
if (!address.IsNTCP2 ()) // we don't publish NTCP2 address fow now. TODO: implement
{
WriteString ("port", properties);
properties << '=';
WriteString (boost::lexical_cast<std::string>(address.port), properties);
properties << ';';
}
if (address.IsNTCP2 ())
{
// publish s and v for NTCP2
WriteString ("s", properties); properties << '=';
WriteString (address.ntcp2->staticKey.ToBase64 (), properties); properties << ';';
WriteString ("v", properties); properties << '=';
WriteString ("2", properties); properties << ';';
// TODO: publish "i"
}
uint16_t size = htobe16 (properties.str ().size ());
s.write ((char *)&size, sizeof (size));
@ -668,6 +688,21 @@ namespace data
m_Caps |= eSSUIntroducer;
}
void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv)
{
for (const auto& it: *m_Addresses) // don't insert one more NTCP2
if (it->ntcp2) return;
auto addr = std::make_shared<Address>();
addr->port = 0;
addr->transportStyle = eTransportNTCP;
addr->cost = 14;
addr->date = 0;
addr->ntcp2.reset (new NTCP2Ext ());
memcpy (addr->ntcp2->staticKey, staticKey, 32);
memcpy (addr->ntcp2->iv, iv, 32);
m_Addresses->push_back(std::move(addr));
}
bool RouterInfo::AddIntroducer (const Introducer& introducer)
{
for (auto& addr : *m_Addresses)

View File

@ -92,8 +92,8 @@ namespace data
struct NTCP2Ext
{
uint8_t staticKey[32];
uint8_t iv[16];
Tag<32> staticKey;
Tag<16> iv;
};
struct Address
@ -122,6 +122,8 @@ namespace data
{
return !(*this == other);
}
bool IsNTCP2 () const { return (bool)ntcp2; };
};
typedef std::list<std::shared_ptr<Address> > Addresses;
@ -143,6 +145,7 @@ namespace data
void AddNTCPAddress (const char * host, int port);
void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0);
void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv);
bool AddIntroducer (const Introducer& introducer);
bool RemoveIntroducer (const boost::asio::ip::udp::endpoint& e);
void SetProperty (const std::string& key, const std::string& value); // called from RouterContext only