mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-22 04:04:16 +00:00
Merge pull request #5 from orignal/master
Merge pull request #5 from orignal/master
This commit is contained in:
commit
877be9c68e
2
Makefile
2
Makefile
@ -3,7 +3,7 @@ CC = g++
|
|||||||
CFLAGS = -g -Wall -std=c++0x
|
CFLAGS = -g -Wall -std=c++0x
|
||||||
OBJECTS = i2p.o base64.o NTCPSession.o RouterInfo.o Transports.o RouterContext.o \
|
OBJECTS = i2p.o base64.o NTCPSession.o RouterInfo.o Transports.o RouterContext.o \
|
||||||
NetDb.o LeaseSet.o Tunnel.o TunnelEndpoint.o TunnelGateway.o TransitTunnel.o \
|
NetDb.o LeaseSet.o Tunnel.o TunnelEndpoint.o TunnelGateway.o TransitTunnel.o \
|
||||||
I2NPProtocol.o Log.o Garlic.o HTTPServer.o Streaming.o Identity.o
|
I2NPProtocol.o Log.o Garlic.o HTTPServer.o Streaming.o Identity.o SSU.o
|
||||||
INCFLAGS =
|
INCFLAGS =
|
||||||
LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem
|
LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem
|
||||||
LIBS =
|
LIBS =
|
||||||
|
103
NetDb.cpp
103
NetDb.cpp
@ -1,6 +1,7 @@
|
|||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <boost/asio.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <cryptopp/gzip.h>
|
#include <cryptopp/gzip.h>
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
@ -206,6 +207,8 @@ namespace data
|
|||||||
};
|
};
|
||||||
|
|
||||||
int count = 0, deletedCount = 0;
|
int count = 0, deletedCount = 0;
|
||||||
|
auto total = m_RouterInfos.size ();
|
||||||
|
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
for (auto it: m_RouterInfos)
|
for (auto it: m_RouterInfos)
|
||||||
{
|
{
|
||||||
if (it.second->IsUpdated ())
|
if (it.second->IsUpdated ())
|
||||||
@ -215,13 +218,23 @@ namespace data
|
|||||||
it.second->SetUpdated (false);
|
it.second->SetUpdated (false);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
else if (it.second->IsUnreachable ())
|
else
|
||||||
{
|
{
|
||||||
if (boost::filesystem::exists (GetFilePath (directory, it.second)))
|
// RouterInfo expires in 72 hours if more than 300
|
||||||
{
|
if (total > 300 && ts > it.second->GetTimestamp () + 3*24*3600*1000LL) // 3 days
|
||||||
boost::filesystem::remove (GetFilePath (directory, it.second));
|
{
|
||||||
deletedCount++;
|
total--;
|
||||||
|
it.second->SetUnreachable (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (it.second->IsUnreachable ())
|
||||||
|
{
|
||||||
|
if (boost::filesystem::exists (GetFilePath (directory, it.second)))
|
||||||
|
{
|
||||||
|
boost::filesystem::remove (GetFilePath (directory, it.second));
|
||||||
|
deletedCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
@ -239,16 +252,6 @@ namespace data
|
|||||||
|
|
||||||
void NetDb::RequestDestination (const IdentHash& destination, bool isLeaseSet)
|
void NetDb::RequestDestination (const IdentHash& destination, bool isLeaseSet)
|
||||||
{
|
{
|
||||||
auto floodfill= GetRandomNTCPRouter (true);
|
|
||||||
if (floodfill)
|
|
||||||
RequestDestination (destination, floodfill, isLeaseSet);
|
|
||||||
else
|
|
||||||
LogPrint ("No floodfill routers found");
|
|
||||||
}
|
|
||||||
|
|
||||||
void NetDb::RequestDestination (const IdentHash& destination, const RouterInfo * floodfill, bool isLeaseSet)
|
|
||||||
{
|
|
||||||
if (!floodfill) return;
|
|
||||||
i2p::tunnel::OutboundTunnel * outbound = i2p::tunnel::tunnels.GetNextOutboundTunnel ();
|
i2p::tunnel::OutboundTunnel * outbound = i2p::tunnel::tunnels.GetNextOutboundTunnel ();
|
||||||
if (outbound)
|
if (outbound)
|
||||||
{
|
{
|
||||||
@ -256,9 +259,31 @@ namespace data
|
|||||||
if (inbound)
|
if (inbound)
|
||||||
{
|
{
|
||||||
RequestedDestination * dest = CreateRequestedDestination (destination, isLeaseSet);
|
RequestedDestination * dest = CreateRequestedDestination (destination, isLeaseSet);
|
||||||
dest->SetLastOutboundTunnel (outbound);
|
auto floodfill = GetClosestFloodfill (destination, dest->GetExcludedPeers ());
|
||||||
auto msg = dest->CreateRequestMessage (floodfill, inbound);
|
if (floodfill)
|
||||||
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg);
|
{
|
||||||
|
std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
|
||||||
|
// our RouterInfo
|
||||||
|
msgs.push_back (i2p::tunnel::TunnelMessageBlock
|
||||||
|
{
|
||||||
|
i2p::tunnel::eDeliveryTypeRouter,
|
||||||
|
floodfill->GetIdentHash (), 0,
|
||||||
|
CreateDatabaseStoreMsg ()
|
||||||
|
});
|
||||||
|
|
||||||
|
// DatabaseLookup message
|
||||||
|
dest->SetLastOutboundTunnel (outbound);
|
||||||
|
msgs.push_back (i2p::tunnel::TunnelMessageBlock
|
||||||
|
{
|
||||||
|
i2p::tunnel::eDeliveryTypeRouter,
|
||||||
|
floodfill->GetIdentHash (), 0,
|
||||||
|
dest->CreateRequestMessage (floodfill, inbound)
|
||||||
|
});
|
||||||
|
|
||||||
|
outbound->SendTunnelDataMsg (msgs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint ("No more floodfills found");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint ("No inbound tunnels found");
|
LogPrint ("No inbound tunnels found");
|
||||||
@ -487,7 +512,8 @@ namespace data
|
|||||||
if (msg) m_Queue.Put (msg);
|
if (msg) m_Queue.Put (msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
const RouterInfo * NetDb::GetClosestFloodfill (const IdentHash& destination) const
|
const RouterInfo * NetDb::GetClosestFloodfill (const IdentHash& destination,
|
||||||
|
const std::set<IdentHash>& excluded) const
|
||||||
{
|
{
|
||||||
RouterInfo * r = nullptr;
|
RouterInfo * r = nullptr;
|
||||||
XORMetric minMetric;
|
XORMetric minMetric;
|
||||||
@ -495,7 +521,7 @@ namespace data
|
|||||||
minMetric.SetMax ();
|
minMetric.SetMax ();
|
||||||
for (auto it: m_RouterInfos)
|
for (auto it: m_RouterInfos)
|
||||||
{
|
{
|
||||||
if (it.second->IsFloodfill () &&! it.second->IsUnreachable ())
|
if (it.second->IsFloodfill () &&! it.second->IsUnreachable () && !excluded.count (it.first))
|
||||||
{
|
{
|
||||||
XORMetric m = destKey ^ it.second->GetRoutingKey ();
|
XORMetric m = destKey ^ it.second->GetRoutingKey ();
|
||||||
if (m < minMetric)
|
if (m < minMetric)
|
||||||
@ -507,5 +533,42 @@ namespace data
|
|||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetDb::DownloadRouterInfo (const std::string& address, const std::string& filename)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boost::asio::ip::tcp::iostream site(address, "http");
|
||||||
|
if (!site)
|
||||||
|
{
|
||||||
|
//site.expires_from_now (boost::posix_time::seconds (10)); // wait for 10 seconds
|
||||||
|
site << "GET " << filename << "HTTP/1.0\nHost: " << address << "\nAccept: */*\nConnection: close\n\n";
|
||||||
|
// read response
|
||||||
|
std::string version, statusMessage;
|
||||||
|
site >> version; // HTTP version
|
||||||
|
int status;
|
||||||
|
site >> status; // status
|
||||||
|
std::getline (site, statusMessage);
|
||||||
|
if (status == 200) // OK
|
||||||
|
{
|
||||||
|
std::string header;
|
||||||
|
while (header != "\n")
|
||||||
|
std::getline (site, header);
|
||||||
|
// read content
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << site.rdbuf();
|
||||||
|
AddRouterInfo ((uint8_t *)ss.str ().c_str (), ss.str ().size ());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint ("HTTP response ", status);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint ("Can't connect to ", address);
|
||||||
|
}
|
||||||
|
catch (std::exception& ex)
|
||||||
|
{
|
||||||
|
LogPrint ("Failed to download ", filename, " : ", ex.what ());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
9
NetDb.h
9
NetDb.h
@ -26,7 +26,8 @@ namespace data
|
|||||||
|
|
||||||
const IdentHash& GetDestination () const { return m_Destination; };
|
const IdentHash& GetDestination () const { return m_Destination; };
|
||||||
int GetNumExcludedPeers () const { return m_ExcludedPeers.size (); };
|
int GetNumExcludedPeers () const { return m_ExcludedPeers.size (); };
|
||||||
const RouterInfo * GetLastRouter () const { return m_LastRouter; };
|
const std::set<IdentHash>& GetExcludedPeers () { return m_ExcludedPeers; };
|
||||||
|
const RouterInfo * GetLastRouter () const { return m_LastRouter; };
|
||||||
const i2p::tunnel::InboundTunnel * GetLastReplyTunnel () const { return m_LastReplyTunnel; };
|
const i2p::tunnel::InboundTunnel * GetLastReplyTunnel () const { return m_LastReplyTunnel; };
|
||||||
bool IsExploratory () const { return m_IsExploratory; };
|
bool IsExploratory () const { return m_IsExploratory; };
|
||||||
bool IsExcluded (const IdentHash& ident) const { return m_ExcludedPeers.count (ident); };
|
bool IsExcluded (const IdentHash& ident) const { return m_ExcludedPeers.count (ident); };
|
||||||
@ -62,8 +63,7 @@ namespace data
|
|||||||
|
|
||||||
void RequestDestination (const char * b32); // in base32
|
void RequestDestination (const char * b32); // in base32
|
||||||
void RequestDestination (const IdentHash& destination, bool isLeaseSet = false);
|
void RequestDestination (const IdentHash& destination, bool isLeaseSet = false);
|
||||||
void RequestDestination (const IdentHash& destination, const RouterInfo * floodfill, bool isLeaseSet = false);
|
|
||||||
|
|
||||||
void HandleDatabaseStoreMsg (uint8_t * buf, size_t len);
|
void HandleDatabaseStoreMsg (uint8_t * buf, size_t len);
|
||||||
void HandleDatabaseSearchReplyMsg (I2NPMessage * msg);
|
void HandleDatabaseSearchReplyMsg (I2NPMessage * msg);
|
||||||
|
|
||||||
@ -76,9 +76,10 @@ namespace data
|
|||||||
|
|
||||||
void Load (const char * directory);
|
void Load (const char * directory);
|
||||||
void SaveUpdated (const char * directory);
|
void SaveUpdated (const char * directory);
|
||||||
|
void DownloadRouterInfo (const std::string& address, const std::string& filename); // for reseed
|
||||||
void Run (); // exploratory thread
|
void Run (); // exploratory thread
|
||||||
void Explore ();
|
void Explore ();
|
||||||
const RouterInfo * GetClosestFloodfill (const IdentHash& destination) const;
|
const RouterInfo * GetClosestFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
|
||||||
|
|
||||||
RequestedDestination * CreateRequestedDestination (const IdentHash& dest,
|
RequestedDestination * CreateRequestedDestination (const IdentHash& dest,
|
||||||
bool isLeaseSet, bool isExploratory = false);
|
bool isLeaseSet, bool isExploratory = false);
|
||||||
|
@ -128,7 +128,13 @@ namespace data
|
|||||||
size = be16toh (size);
|
size = be16toh (size);
|
||||||
while (r < size)
|
while (r < size)
|
||||||
{
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
char key[500], value[500];
|
char key[500], value[500];
|
||||||
|
// TODO: investigate why properties get read as one long string under Windows
|
||||||
|
// length should not be more than 44
|
||||||
|
#else
|
||||||
|
char key[50], value[50];
|
||||||
|
#endif
|
||||||
r += ReadString (key, s);
|
r += ReadString (key, s);
|
||||||
s.seekg (1, std::ios_base::cur); r++; // =
|
s.seekg (1, std::ios_base::cur); r++; // =
|
||||||
r += ReadString (value, s);
|
r += ReadString (value, s);
|
||||||
|
44
SSU.cpp
Normal file
44
SSU.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include "Log.h"
|
||||||
|
#include "hmac.h"
|
||||||
|
#include "SSU.h"
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace ssu
|
||||||
|
{
|
||||||
|
SSUServer::SSUServer (boost::asio::io_service& service, int port):
|
||||||
|
m_Socket (service, boost::asio::ip::udp::v4 (), port)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSUServer::Start ()
|
||||||
|
{
|
||||||
|
Receive ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSUServer::Stop ()
|
||||||
|
{
|
||||||
|
m_Socket.close ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSUServer::Receive ()
|
||||||
|
{
|
||||||
|
m_Socket.async_receive_from (boost::asio::buffer (m_ReceiveBuffer, SSU_MTU), m_SenderEndpoint,
|
||||||
|
boost::bind (&SSUServer::HandleReceivedFrom, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSUServer::HandleReceivedFrom (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
||||||
|
{
|
||||||
|
if (!ecode)
|
||||||
|
{
|
||||||
|
LogPrint ("SSU received ", bytes_transferred, " bytes");
|
||||||
|
// Handle
|
||||||
|
Receive ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint ("SSU receive error: ", ecode.message ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
36
SSU.h
Normal file
36
SSU.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#ifndef SSU_H__
|
||||||
|
#define SSU_H__
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace ssu
|
||||||
|
{
|
||||||
|
const int SSU_MTU = 1484;
|
||||||
|
|
||||||
|
class SSUServer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
SSUServer (boost::asio::io_service& service, int port);
|
||||||
|
void Start ();
|
||||||
|
void Stop ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void Receive ();
|
||||||
|
void HandleReceivedFrom (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
boost::asio::ip::udp::socket m_Socket;
|
||||||
|
boost::asio::ip::udp::endpoint m_SenderEndpoint;
|
||||||
|
uint8_t m_ReceiveBuffer[SSU_MTU];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -12,7 +12,7 @@ namespace i2p
|
|||||||
Transports transports;
|
Transports transports;
|
||||||
|
|
||||||
Transports::Transports ():
|
Transports::Transports ():
|
||||||
m_Thread (0), m_Work (m_Service),m_NTCPAcceptor (0)
|
m_Thread (nullptr), m_Work (m_Service),m_NTCPAcceptor (nullptr), m_SSUServer (nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,11 +34,22 @@ namespace i2p
|
|||||||
m_NTCPAcceptor = new boost::asio::ip::tcp::acceptor (m_Service,
|
m_NTCPAcceptor = new boost::asio::ip::tcp::acceptor (m_Service,
|
||||||
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address.port));
|
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address.port));
|
||||||
|
|
||||||
LogPrint ("Start listening port ", address.port);
|
LogPrint ("Start listening TCP port ", address.port);
|
||||||
auto conn = new i2p::ntcp::NTCPServerConnection (m_Service);
|
auto conn = new i2p::ntcp::NTCPServerConnection (m_Service);
|
||||||
m_NTCPAcceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAccept, this,
|
m_NTCPAcceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAccept, this,
|
||||||
conn, boost::asio::placeholders::error));
|
conn, boost::asio::placeholders::error));
|
||||||
}
|
}
|
||||||
|
else if (address.transportStyle == RouterInfo::eTransportSSU)
|
||||||
|
{
|
||||||
|
if (!m_SSUServer)
|
||||||
|
{
|
||||||
|
m_SSUServer = new i2p::ssu::SSUServer (m_Service, address.port);
|
||||||
|
LogPrint ("Start listening UDP port ", address.port);
|
||||||
|
m_SSUServer->Start ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint ("SSU server already exists");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +60,12 @@ namespace i2p
|
|||||||
m_NTCPSessions.clear ();
|
m_NTCPSessions.clear ();
|
||||||
delete m_NTCPAcceptor;
|
delete m_NTCPAcceptor;
|
||||||
|
|
||||||
|
if (m_SSUServer)
|
||||||
|
{
|
||||||
|
m_SSUServer->Stop ();
|
||||||
|
delete m_SSUServer;
|
||||||
|
}
|
||||||
|
|
||||||
m_IsRunning = false;
|
m_IsRunning = false;
|
||||||
m_Service.stop ();
|
m_Service.stop ();
|
||||||
if (m_Thread)
|
if (m_Thread)
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include "NTCPSession.h"
|
#include "NTCPSession.h"
|
||||||
|
#include "SSU.h"
|
||||||
#include "RouterInfo.h"
|
#include "RouterInfo.h"
|
||||||
#include "I2NPProtocol.h"
|
#include "I2NPProtocol.h"
|
||||||
|
|
||||||
@ -47,6 +48,7 @@ namespace i2p
|
|||||||
boost::asio::ip::tcp::acceptor * m_NTCPAcceptor;
|
boost::asio::ip::tcp::acceptor * m_NTCPAcceptor;
|
||||||
|
|
||||||
std::map<i2p::data::IdentHash, i2p::ntcp::NTCPSession *> m_NTCPSessions;
|
std::map<i2p::data::IdentHash, i2p::ntcp::NTCPSession *> m_NTCPSessions;
|
||||||
|
i2p::ssu::SSUServer * m_SSUServer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
60
hmac.h
Normal file
60
hmac.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#ifndef HMAC_H__
|
||||||
|
#define HMAC_H__
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <string.h>
|
||||||
|
#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
|
||||||
|
#include <cryptopp/md5.h>
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace crypto
|
||||||
|
{
|
||||||
|
const uint64_t IPAD = 0x3636363636363636;
|
||||||
|
const uint64_t OPAD = 0x5C5C5C5C5C5C5C5C;
|
||||||
|
|
||||||
|
inline void HMACMD5Digest (uint8_t * msg, size_t len, uint8_t * key, uint8_t * digest)
|
||||||
|
// key is 32 bytes
|
||||||
|
// digest is 16 bytes
|
||||||
|
// block size is 64 bytes
|
||||||
|
{
|
||||||
|
size_t totalLen = len + 64 + 32;
|
||||||
|
uint8_t * buf = new uint8_t[totalLen]; // TODO: reuse buffers
|
||||||
|
// ikeypad
|
||||||
|
((uint64_t *)buf)[0] = ((uint64_t *)key)[0] ^ IPAD;
|
||||||
|
((uint64_t *)buf)[1] = ((uint64_t *)key)[1] ^ IPAD;
|
||||||
|
((uint64_t *)buf)[2] = ((uint64_t *)key)[2] ^ IPAD;
|
||||||
|
((uint64_t *)buf)[3] = ((uint64_t *)key)[3] ^ IPAD;
|
||||||
|
((uint64_t *)buf)[4] = IPAD;
|
||||||
|
((uint64_t *)buf)[5] = IPAD;
|
||||||
|
((uint64_t *)buf)[6] = IPAD;
|
||||||
|
((uint64_t *)buf)[7] = IPAD;
|
||||||
|
// concatenate with msg
|
||||||
|
memcpy (buf + 64, msg, len);
|
||||||
|
// calculate first hash
|
||||||
|
uint8_t hash[16]; // MD5
|
||||||
|
CryptoPP::Weak1::MD5().CalculateDigest (hash, buf, len + 64);
|
||||||
|
|
||||||
|
// okeypad
|
||||||
|
((uint64_t *)buf)[0] = ((uint64_t *)key)[0] ^ OPAD;
|
||||||
|
((uint64_t *)buf)[1] = ((uint64_t *)key)[1] ^ OPAD;
|
||||||
|
((uint64_t *)buf)[2] = ((uint64_t *)key)[2] ^ OPAD;
|
||||||
|
((uint64_t *)buf)[3] = ((uint64_t *)key)[3] ^ OPAD;
|
||||||
|
((uint64_t *)buf)[4] = OPAD;
|
||||||
|
((uint64_t *)buf)[5] = OPAD;
|
||||||
|
((uint64_t *)buf)[6] = OPAD;
|
||||||
|
((uint64_t *)buf)[7] = OPAD;
|
||||||
|
// copy first hash after okeypad
|
||||||
|
memcpy (buf + 64, hash, 16);
|
||||||
|
// fill next 16 bytes with zeros (first hash size assumed 32 bytes in I2P)
|
||||||
|
memset (buf + 72, 0, 16);
|
||||||
|
|
||||||
|
// calculate digest
|
||||||
|
CryptoPP::Weak1::MD5().CalculateDigest (digest, buf, totalLen);
|
||||||
|
delete[] buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user