pre-calculate ephemeral keys for x25519

pull/1542/head
orignal 4 years ago
parent df9965e129
commit 1f31fdc257

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

@ -79,7 +79,7 @@ namespace transport
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
uint8_t * GetRemotePub () { return m_RemoteEphemeralPublicKey; }; // to set
@ -110,7 +110,7 @@ namespace transport
bool ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce);
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_RemoteStaticKey[32], m_IV[16], m_H[32] /*h*/, m_CK[64] /* [ck, k]*/;
i2p::data::IdentHash m_RemoteIdentHash;

@ -21,23 +21,27 @@ namespace i2p
{
namespace transport
{
DHKeysPairSupplier::DHKeysPairSupplier (int size):
template<typename Keys>
EphemeralKeysSupplier<Keys>::EphemeralKeysSupplier (int size):
m_QueueSize (size), m_IsRunning (false), m_Thread (nullptr)
{
}
DHKeysPairSupplier::~DHKeysPairSupplier ()
template<typename Keys>
EphemeralKeysSupplier<Keys>::~EphemeralKeysSupplier ()
{
Stop ();
}
void DHKeysPairSupplier::Start ()
template<typename Keys>
void EphemeralKeysSupplier<Keys>::Start ()
{
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);
@ -52,19 +56,20 @@ namespace transport
}
}
void DHKeysPairSupplier::Run ()
template<typename Keys>
void EphemeralKeysSupplier<Keys>::Run ()
{
while (m_IsRunning)
{
int num, total = 0;
while ((num = m_QueueSize - (int)m_Queue.size ()) > 0 && total < 10)
{
CreateDHKeysPairs (num);
CreateEphemeralKeys (num);
total += num;
}
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
}
else
@ -76,24 +81,26 @@ namespace transport
}
}
void DHKeysPairSupplier::CreateDHKeysPairs (int num)
template<typename Keys>
void EphemeralKeysSupplier<Keys>::CreateEphemeralKeys (int num)
{
if (num > 0)
{
for (int i = 0; i < num; i++)
{
auto pair = std::make_shared<i2p::crypto::DHKeys> ();
auto pair = std::make_shared<Keys> ();
pair->GenerateKeys ();
std::unique_lock<std::mutex> l(m_AcquiredMutex);
std::unique_lock<std::mutex> l(m_AcquiredMutex);
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 ())
{
auto pair = m_Queue.front ();
@ -103,12 +110,13 @@ namespace transport
}
}
// queue is empty, create new
auto pair = std::make_shared<i2p::crypto::DHKeys> ();
auto pair = std::make_shared<Keys> ();
pair->GenerateKeys ();
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)
{
@ -126,7 +134,7 @@ namespace transport
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_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_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth(0),
m_LastInBandwidthUpdateBytes (0), m_LastOutBandwidthUpdateBytes (0),
@ -158,6 +166,7 @@ namespace transport
i2p::config::GetOption("nat", m_IsNAT);
m_DHKeysPairSupplier.Start ();
m_X25519KeysPairSupplier.Start ();
m_IsRunning = true;
m_Thread = new std::thread (std::bind (&Transports::Run, this));
std::string ntcpproxy; i2p::config::GetOption("ntcpproxy", ntcpproxy);
@ -312,6 +321,7 @@ namespace transport
}
m_DHKeysPairSupplier.Stop ();
m_X25519KeysPairSupplier.Stop ();
m_IsRunning = false;
if (m_Service) m_Service->stop ();
if (m_Thread)
@ -630,6 +640,16 @@ namespace transport
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)
{
m_Service->post([session, this]()

@ -32,33 +32,37 @@ namespace i2p
{
namespace transport
{
class DHKeysPairSupplier
template<typename Keys>
class EphemeralKeysSupplier
{
// called from this file only, so implementation is in Transports.cpp
public:
DHKeysPairSupplier (int size);
~DHKeysPairSupplier ();
EphemeralKeysSupplier (int size);
~EphemeralKeysSupplier ();
void Start ();
void Stop ();
std::shared_ptr<i2p::crypto::DHKeys> Acquire ();
void Return (std::shared_ptr<i2p::crypto::DHKeys> pair);
std::shared_ptr<Keys> Acquire ();
void Return (std::shared_ptr<Keys> pair);
private:
void Run ();
void CreateDHKeysPairs (int num);
void CreateEphemeralKeys (int num);
private:
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;
std::thread * m_Thread;
std::condition_variable m_Acquired;
std::mutex m_AcquiredMutex;
};
typedef EphemeralKeysSupplier<i2p::crypto::DHKeys> DHKeysPairSupplier;
typedef EphemeralKeysSupplier<i2p::crypto::X25519Keys> X25519KeysPairSupplier;
struct Peer
{
int numAttempts;
@ -97,6 +101,8 @@ namespace transport
boost::asio::io_service& GetService () { return *m_Service; };
std::shared_ptr<i2p::crypto::DHKeys> GetNextDHKeysPair ();
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 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;
DHKeysPairSupplier m_DHKeysPairSupplier;
X25519KeysPairSupplier m_X25519KeysPairSupplier;
std::atomic<uint64_t> m_TotalSentBytes, m_TotalReceivedBytes, m_TotalTransitTransmittedBytes;
uint32_t m_InBandwidth, m_OutBandwidth, m_TransitBandwidth; // bytes per second

Loading…
Cancel
Save