Browse Source

pre-calculate ephemeral keys for x25519

pull/1542/head
orignal 4 years ago
parent
commit
1f31fdc257
  1. 8
      libi2pd/NTCP2.cpp
  2. 4
      libi2pd/NTCP2.h
  3. 52
      libi2pd/Transports.cpp
  4. 23
      libi2pd/Transports.h

8
libi2pd/NTCP2.cpp

@ -83,7 +83,7 @@ namespace transport
void NTCP2Establisher::KDF1Alice () void NTCP2Establisher::KDF1Alice ()
{ {
KeyDerivationFunction1 (m_RemoteStaticKey, m_EphemeralKeys, m_RemoteStaticKey, GetPub ()); KeyDerivationFunction1 (m_RemoteStaticKey, *m_EphemeralKeys, m_RemoteStaticKey, GetPub ());
} }
void NTCP2Establisher::KDF1Bob () void NTCP2Establisher::KDF1Bob ()
@ -102,7 +102,7 @@ namespace transport
// x25519 between remote pub and ephemaral priv // x25519 between remote pub and ephemaral priv
uint8_t inputKeyMaterial[32]; uint8_t inputKeyMaterial[32];
m_EphemeralKeys.Agree (GetRemotePub (), inputKeyMaterial); m_EphemeralKeys->Agree (GetRemotePub (), inputKeyMaterial);
MixKey (inputKeyMaterial); MixKey (inputKeyMaterial);
} }
@ -127,13 +127,13 @@ namespace transport
void NTCP2Establisher::KDF3Bob () void NTCP2Establisher::KDF3Bob ()
{ {
uint8_t inputKeyMaterial[32]; uint8_t inputKeyMaterial[32];
m_EphemeralKeys.Agree (m_RemoteStaticKey, inputKeyMaterial); m_EphemeralKeys->Agree (m_RemoteStaticKey, inputKeyMaterial);
MixKey (inputKeyMaterial); MixKey (inputKeyMaterial);
} }
void NTCP2Establisher::CreateEphemeralKey () void NTCP2Establisher::CreateEphemeralKey ()
{ {
m_EphemeralKeys.GenerateKeys (); m_EphemeralKeys = i2p::transport::transports.GetNextX25519KeysPair ();
} }
void NTCP2Establisher::CreateSessionRequestMessage () void NTCP2Establisher::CreateSessionRequestMessage ()

4
libi2pd/NTCP2.h

@ -79,7 +79,7 @@ namespace transport
NTCP2Establisher (); NTCP2Establisher ();
~NTCP2Establisher (); ~NTCP2Establisher ();
const uint8_t * GetPub () const { return m_EphemeralKeys.GetPublicKey (); }; const uint8_t * GetPub () const { return m_EphemeralKeys->GetPublicKey (); };
const uint8_t * GetRemotePub () const { return m_RemoteEphemeralPublicKey; }; // Y for Alice and X for Bob const uint8_t * GetRemotePub () const { return m_RemoteEphemeralPublicKey; }; // Y for Alice and X for Bob
uint8_t * GetRemotePub () { return m_RemoteEphemeralPublicKey; }; // to set uint8_t * GetRemotePub () { return m_RemoteEphemeralPublicKey; }; // to set
@ -110,7 +110,7 @@ namespace transport
bool ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce); bool ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce);
bool ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf); bool ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf);
i2p::crypto::X25519Keys m_EphemeralKeys; std::shared_ptr<i2p::crypto::X25519Keys> m_EphemeralKeys;
uint8_t m_RemoteEphemeralPublicKey[32]; // x25519 uint8_t m_RemoteEphemeralPublicKey[32]; // x25519
uint8_t m_RemoteStaticKey[32], m_IV[16], m_H[32] /*h*/, m_CK[64] /* [ck, k]*/; uint8_t m_RemoteStaticKey[32], m_IV[16], m_H[32] /*h*/, m_CK[64] /* [ck, k]*/;
i2p::data::IdentHash m_RemoteIdentHash; i2p::data::IdentHash m_RemoteIdentHash;

52
libi2pd/Transports.cpp

@ -21,23 +21,27 @@ namespace i2p
{ {
namespace transport namespace transport
{ {
DHKeysPairSupplier::DHKeysPairSupplier (int size): template<typename Keys>
EphemeralKeysSupplier<Keys>::EphemeralKeysSupplier (int size):
m_QueueSize (size), m_IsRunning (false), m_Thread (nullptr) m_QueueSize (size), m_IsRunning (false), m_Thread (nullptr)
{ {
} }
DHKeysPairSupplier::~DHKeysPairSupplier () template<typename Keys>
EphemeralKeysSupplier<Keys>::~EphemeralKeysSupplier ()
{ {
Stop (); Stop ();
} }
void DHKeysPairSupplier::Start () template<typename Keys>
void EphemeralKeysSupplier<Keys>::Start ()
{ {
m_IsRunning = true; m_IsRunning = true;
m_Thread = new std::thread (std::bind (&DHKeysPairSupplier::Run, this)); m_Thread = new std::thread (std::bind (&EphemeralKeysSupplier<Keys>::Run, this));
} }
void DHKeysPairSupplier::Stop () template<typename Keys>
void EphemeralKeysSupplier<Keys>::Stop ()
{ {
{ {
std::unique_lock<std::mutex> l(m_AcquiredMutex); std::unique_lock<std::mutex> l(m_AcquiredMutex);
@ -52,19 +56,20 @@ namespace transport
} }
} }
void DHKeysPairSupplier::Run () template<typename Keys>
void EphemeralKeysSupplier<Keys>::Run ()
{ {
while (m_IsRunning) while (m_IsRunning)
{ {
int num, total = 0; int num, total = 0;
while ((num = m_QueueSize - (int)m_Queue.size ()) > 0 && total < 10) while ((num = m_QueueSize - (int)m_Queue.size ()) > 0 && total < 10)
{ {
CreateDHKeysPairs (num); CreateEphemeralKeys (num);
total += num; total += num;
} }
if (total >= 10) if (total >= 10)
{ {
LogPrint (eLogWarning, "Transports: ", total, " DH keys generated at the time"); LogPrint (eLogWarning, "Transports: ", total, " ephemeral keys generated at the time");
std::this_thread::sleep_for (std::chrono::seconds(1)); // take a break std::this_thread::sleep_for (std::chrono::seconds(1)); // take a break
} }
else else
@ -76,24 +81,26 @@ namespace transport
} }
} }
void DHKeysPairSupplier::CreateDHKeysPairs (int num) template<typename Keys>
void EphemeralKeysSupplier<Keys>::CreateEphemeralKeys (int num)
{ {
if (num > 0) if (num > 0)
{ {
for (int i = 0; i < num; i++) for (int i = 0; i < num; i++)
{ {
auto pair = std::make_shared<i2p::crypto::DHKeys> (); auto pair = std::make_shared<Keys> ();
pair->GenerateKeys (); pair->GenerateKeys ();
std::unique_lock<std::mutex> l(m_AcquiredMutex); std::unique_lock<std::mutex> l(m_AcquiredMutex);
m_Queue.push (pair); m_Queue.push (pair);
} }
} }
} }
std::shared_ptr<i2p::crypto::DHKeys> DHKeysPairSupplier::Acquire () template<typename Keys>
std::shared_ptr<Keys> EphemeralKeysSupplier<Keys>::Acquire ()
{ {
{ {
std::unique_lock<std::mutex> l(m_AcquiredMutex); std::unique_lock<std::mutex> l(m_AcquiredMutex);
if (!m_Queue.empty ()) if (!m_Queue.empty ())
{ {
auto pair = m_Queue.front (); auto pair = m_Queue.front ();
@ -103,12 +110,13 @@ namespace transport
} }
} }
// queue is empty, create new // queue is empty, create new
auto pair = std::make_shared<i2p::crypto::DHKeys> (); auto pair = std::make_shared<Keys> ();
pair->GenerateKeys (); pair->GenerateKeys ();
return pair; return pair;
} }
void DHKeysPairSupplier::Return (std::shared_ptr<i2p::crypto::DHKeys> pair) template<typename Keys>
void EphemeralKeysSupplier<Keys>::Return (std::shared_ptr<Keys> pair)
{ {
if (pair) if (pair)
{ {
@ -126,7 +134,7 @@ namespace transport
m_IsOnline (true), m_IsRunning (false), m_IsNAT (true), m_Thread (nullptr), m_Service (nullptr), m_IsOnline (true), m_IsRunning (false), m_IsNAT (true), m_Thread (nullptr), m_Service (nullptr),
m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr), m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr),
m_NTCPServer (nullptr), m_SSUServer (nullptr), m_NTCP2Server (nullptr), m_NTCPServer (nullptr), m_SSUServer (nullptr), m_NTCP2Server (nullptr),
m_DHKeysPairSupplier (5), // 5 pre-generated keys m_DHKeysPairSupplier (5), m_X25519KeysPairSupplier (5), // 5 pre-generated keys
m_TotalSentBytes(0), m_TotalReceivedBytes(0), m_TotalTransitTransmittedBytes (0), m_TotalSentBytes(0), m_TotalReceivedBytes(0), m_TotalTransitTransmittedBytes (0),
m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth(0), m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth(0),
m_LastInBandwidthUpdateBytes (0), m_LastOutBandwidthUpdateBytes (0), m_LastInBandwidthUpdateBytes (0), m_LastOutBandwidthUpdateBytes (0),
@ -158,6 +166,7 @@ namespace transport
i2p::config::GetOption("nat", m_IsNAT); i2p::config::GetOption("nat", m_IsNAT);
m_DHKeysPairSupplier.Start (); m_DHKeysPairSupplier.Start ();
m_X25519KeysPairSupplier.Start ();
m_IsRunning = true; m_IsRunning = true;
m_Thread = new std::thread (std::bind (&Transports::Run, this)); m_Thread = new std::thread (std::bind (&Transports::Run, this));
std::string ntcpproxy; i2p::config::GetOption("ntcpproxy", ntcpproxy); std::string ntcpproxy; i2p::config::GetOption("ntcpproxy", ntcpproxy);
@ -312,6 +321,7 @@ namespace transport
} }
m_DHKeysPairSupplier.Stop (); m_DHKeysPairSupplier.Stop ();
m_X25519KeysPairSupplier.Stop ();
m_IsRunning = false; m_IsRunning = false;
if (m_Service) m_Service->stop (); if (m_Service) m_Service->stop ();
if (m_Thread) if (m_Thread)
@ -630,6 +640,16 @@ namespace transport
m_DHKeysPairSupplier.Return (pair); m_DHKeysPairSupplier.Return (pair);
} }
std::shared_ptr<i2p::crypto::X25519Keys> Transports::GetNextX25519KeysPair ()
{
return m_X25519KeysPairSupplier.Acquire ();
}
void Transports::ReuseX25519KeysPair (std::shared_ptr<i2p::crypto::X25519Keys> pair)
{
m_X25519KeysPairSupplier.Return (pair);
}
void Transports::PeerConnected (std::shared_ptr<TransportSession> session) void Transports::PeerConnected (std::shared_ptr<TransportSession> session)
{ {
m_Service->post([session, this]() m_Service->post([session, this]()

23
libi2pd/Transports.h

@ -32,33 +32,37 @@ namespace i2p
{ {
namespace transport namespace transport
{ {
class DHKeysPairSupplier template<typename Keys>
class EphemeralKeysSupplier
{ {
// called from this file only, so implementation is in Transports.cpp
public: public:
DHKeysPairSupplier (int size); EphemeralKeysSupplier (int size);
~DHKeysPairSupplier (); ~EphemeralKeysSupplier ();
void Start (); void Start ();
void Stop (); void Stop ();
std::shared_ptr<i2p::crypto::DHKeys> Acquire (); std::shared_ptr<Keys> Acquire ();
void Return (std::shared_ptr<i2p::crypto::DHKeys> pair); void Return (std::shared_ptr<Keys> pair);
private: private:
void Run (); void Run ();
void CreateDHKeysPairs (int num); void CreateEphemeralKeys (int num);
private: private:
const int m_QueueSize; const int m_QueueSize;
std::queue<std::shared_ptr<i2p::crypto::DHKeys> > m_Queue; std::queue<std::shared_ptr<Keys> > m_Queue;
bool m_IsRunning; bool m_IsRunning;
std::thread * m_Thread; std::thread * m_Thread;
std::condition_variable m_Acquired; std::condition_variable m_Acquired;
std::mutex m_AcquiredMutex; std::mutex m_AcquiredMutex;
}; };
typedef EphemeralKeysSupplier<i2p::crypto::DHKeys> DHKeysPairSupplier;
typedef EphemeralKeysSupplier<i2p::crypto::X25519Keys> X25519KeysPairSupplier;
struct Peer struct Peer
{ {
int numAttempts; int numAttempts;
@ -97,6 +101,8 @@ namespace transport
boost::asio::io_service& GetService () { return *m_Service; }; boost::asio::io_service& GetService () { return *m_Service; };
std::shared_ptr<i2p::crypto::DHKeys> GetNextDHKeysPair (); std::shared_ptr<i2p::crypto::DHKeys> GetNextDHKeysPair ();
void ReuseDHKeysPair (std::shared_ptr<i2p::crypto::DHKeys> pair); void ReuseDHKeysPair (std::shared_ptr<i2p::crypto::DHKeys> pair);
std::shared_ptr<i2p::crypto::X25519Keys> GetNextX25519KeysPair ();
void ReuseX25519KeysPair (std::shared_ptr<i2p::crypto::X25519Keys> pair);
void SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr<i2p::I2NPMessage> msg); void SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr<i2p::I2NPMessage> msg);
void SendMessages (const i2p::data::IdentHash& ident, const std::vector<std::shared_ptr<i2p::I2NPMessage> >& msgs); void SendMessages (const i2p::data::IdentHash& ident, const std::vector<std::shared_ptr<i2p::I2NPMessage> >& msgs);
@ -160,6 +166,7 @@ namespace transport
std::unordered_map<i2p::data::IdentHash, Peer> m_Peers; std::unordered_map<i2p::data::IdentHash, Peer> m_Peers;
DHKeysPairSupplier m_DHKeysPairSupplier; DHKeysPairSupplier m_DHKeysPairSupplier;
X25519KeysPairSupplier m_X25519KeysPairSupplier;
std::atomic<uint64_t> m_TotalSentBytes, m_TotalReceivedBytes, m_TotalTransitTransmittedBytes; std::atomic<uint64_t> m_TotalSentBytes, m_TotalReceivedBytes, m_TotalTransitTransmittedBytes;
uint32_t m_InBandwidth, m_OutBandwidth, m_TransitBandwidth; // bytes per second uint32_t m_InBandwidth, m_OutBandwidth, m_TransitBandwidth; // bytes per second

Loading…
Cancel
Save