mirror of
https://github.com/oxen-io/lokinet.git
synced 2024-11-15 12:13:24 +00:00
Merge pull request #937 from notlesh/key_management_cleanup
Key management cleanup
This commit is contained in:
commit
95cf9d0fe7
@ -6,6 +6,19 @@
|
||||
#include "crypto/crypto.hpp"
|
||||
#include "crypto/types.hpp"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <curl/curl.h>
|
||||
#endif
|
||||
|
||||
/// curl callback
|
||||
static size_t
|
||||
curl_RecvIdentKey(char *ptr, size_t, size_t nmemb, void *userdata)
|
||||
{
|
||||
for(size_t idx = 0; idx < nmemb; idx++)
|
||||
static_cast< std::vector< char > * >(userdata)->push_back(ptr[idx]);
|
||||
return nmemb;
|
||||
}
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
KeyManager::KeyManager()
|
||||
@ -14,7 +27,7 @@ namespace llarp
|
||||
}
|
||||
|
||||
bool
|
||||
KeyManager::initializeFromDisk(const llarp::Config& config, bool genIfAbsent)
|
||||
KeyManager::initialize(const llarp::Config& config, bool genIfAbsent)
|
||||
{
|
||||
if (m_initialized)
|
||||
return false;
|
||||
@ -24,6 +37,12 @@ namespace llarp
|
||||
m_encKeyPath = config.router.encryptionKeyfile();
|
||||
m_transportKeyPath = config.router.transportKeyfile();
|
||||
|
||||
m_usingLokid = config.lokid.whitelistRouters;
|
||||
m_lokidRPCAddr = config.lokid.lokidRPCAddr;
|
||||
m_lokidRPCUser = config.lokid.lokidRPCUser;
|
||||
m_lokidRPCPassword = config.lokid.lokidRPCPassword;
|
||||
|
||||
|
||||
RouterContact rc;
|
||||
bool exists = rc.Read(m_rcPath.c_str());
|
||||
if (not exists and not genIfAbsent)
|
||||
@ -56,6 +75,8 @@ namespace llarp
|
||||
}
|
||||
}
|
||||
|
||||
if (not m_usingLokid)
|
||||
{
|
||||
// load identity key or create if needed
|
||||
auto identityKeygen = [](llarp::SecretKey& key)
|
||||
{
|
||||
@ -64,6 +85,12 @@ namespace llarp
|
||||
};
|
||||
if (not loadOrCreateKey(m_idKeyPath, m_idKey, identityKeygen))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (not loadIdentityFromLokid())
|
||||
return false;
|
||||
}
|
||||
|
||||
// load encryption key
|
||||
auto encryptionKeygen = [](llarp::SecretKey& key)
|
||||
@ -202,4 +229,104 @@ namespace llarp
|
||||
return key.LoadFromFile(filepath.c_str());
|
||||
}
|
||||
|
||||
bool
|
||||
KeyManager::loadIdentityFromLokid()
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl)
|
||||
{
|
||||
bool ret = false;
|
||||
std::stringstream ss;
|
||||
ss << "http://" << m_lokidRPCAddr << "/json_rpc";
|
||||
const auto url = ss.str();
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_ANY);
|
||||
const auto auth = m_lokidRPCUser + ":" + m_lokidRPCPassword;
|
||||
curl_easy_setopt(curl, CURLOPT_USERPWD, auth.c_str());
|
||||
curl_slist *list = nullptr;
|
||||
list = curl_slist_append(list, "Content-Type: application/json");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
|
||||
|
||||
nlohmann::json request = {{"id", "0"},
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "get_service_node_privkey"}};
|
||||
const auto data = request.dump();
|
||||
std::vector< char > resp;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, data.size());
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &curl_RecvIdentKey);
|
||||
do
|
||||
{
|
||||
resp.clear();
|
||||
LogInfo("Getting Identity Keys from lokid...");
|
||||
if(curl_easy_perform(curl) == CURLE_OK)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto j = nlohmann::json::parse(resp);
|
||||
if(not j.is_object())
|
||||
continue;
|
||||
|
||||
const auto itr = j.find("result");
|
||||
if(itr == j.end())
|
||||
continue;
|
||||
if(not itr->is_object())
|
||||
continue;
|
||||
const auto k =
|
||||
(*itr)["service_node_ed25519_privkey"].get< std::string >();
|
||||
if(k.size() != (m_idKey.size() * 2))
|
||||
{
|
||||
if(k.empty())
|
||||
{
|
||||
LogError("lokid gave no identity key");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("lokid gave invalid identity key");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if(not HexDecode(k.c_str(), m_idKey.data(), m_idKey.size()))
|
||||
continue;
|
||||
if(CryptoManager::instance()->check_identity_privkey(m_idKey))
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("lokid gave bogus identity key");
|
||||
}
|
||||
}
|
||||
catch(nlohmann::json::exception &ex)
|
||||
{
|
||||
LogError("Bad response from lokid: ", ex.what());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("failed to get identity keys");
|
||||
}
|
||||
if(ret)
|
||||
{
|
||||
LogInfo("Got Identity Keys from lokid: ", RouterID(seckey_topublic(m_idKey)));
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
} while(true);
|
||||
curl_easy_cleanup(curl);
|
||||
curl_slist_free_all(list);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("failed to init curl");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace llarp
|
||||
|
@ -24,17 +24,18 @@ namespace llarp
|
||||
/// Constructor
|
||||
KeyManager();
|
||||
|
||||
/// Initializes from disk. This reads enough from disk to understand the current
|
||||
/// state of the stored keys.
|
||||
/// Initializes keys using the provided config, loading from disk and/or lokid
|
||||
/// via HTTP request.
|
||||
///
|
||||
/// NOTE: Must be called prior to obtaining any keys.
|
||||
/// NOTE: blocks on I/O
|
||||
///
|
||||
/// @param config should be a prepared config object
|
||||
/// @param genIfAbsent determines whether or not we will create files if they
|
||||
/// do not exist.
|
||||
/// @return true on success, false otherwise
|
||||
bool
|
||||
initializeFromDisk(const llarp::Config& config, bool genIfAbsent);
|
||||
initialize(const llarp::Config& config, bool genIfAbsent);
|
||||
|
||||
/// Obtain the identity key (e.g. ~/.lokinet/identity.private)
|
||||
///
|
||||
@ -69,6 +70,11 @@ namespace llarp
|
||||
std::string m_transportKeyPath;
|
||||
std::atomic_bool m_initialized;
|
||||
|
||||
bool m_usingLokid = false;
|
||||
std::string m_lokidRPCAddr = "127.0.0.1:22023";
|
||||
std::string m_lokidRPCUser;
|
||||
std::string m_lokidRPCPassword;
|
||||
|
||||
llarp::RouterContact m_rc;
|
||||
llarp::SecretKey m_idKey;
|
||||
llarp::SecretKey m_encKey;
|
||||
@ -86,6 +92,10 @@ namespace llarp
|
||||
const std::string& filepath,
|
||||
llarp::SecretKey& key,
|
||||
std::function<void(llarp::SecretKey& key)> keygen);
|
||||
|
||||
/// Requests the identity key from lokid via HTTP (curl)
|
||||
bool
|
||||
loadIdentityFromLokid();
|
||||
};
|
||||
|
||||
} // namespace llarp
|
||||
|
@ -30,9 +30,6 @@ namespace llarp
|
||||
const AddressInfo &ai) override;
|
||||
|
||||
|
||||
void
|
||||
Pump() override;
|
||||
|
||||
const char *
|
||||
Name() const override;
|
||||
|
||||
|
@ -31,25 +31,7 @@
|
||||
#include <utility>
|
||||
#if defined(ANDROID) || defined(IOS)
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#if defined(_WIN32)
|
||||
#else
|
||||
#include <curl/curl.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool
|
||||
llarp_loadServiceNodeIdentityKey(const fs::path &fpath,
|
||||
llarp::SecretKey &secret)
|
||||
{
|
||||
std::string path = fpath.string();
|
||||
llarp::IdentitySecret ident;
|
||||
|
||||
if(!ident.LoadFromFile(path.c_str()))
|
||||
return false;
|
||||
|
||||
return llarp::CryptoManager::instance()->seed_to_secretkey(secret, ident);
|
||||
}
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
@ -210,27 +192,10 @@ namespace llarp
|
||||
LogError(rcfile, " contains invalid RC");
|
||||
}
|
||||
|
||||
static size_t
|
||||
RecvIdentKey(char *ptr, size_t, size_t nmemb, void *userdata)
|
||||
{
|
||||
for(size_t idx = 0; idx < nmemb; idx++)
|
||||
static_cast< std::vector< char > * >(userdata)->push_back(ptr[idx]);
|
||||
return nmemb;
|
||||
}
|
||||
|
||||
bool
|
||||
Router::EnsureIdentity()
|
||||
{
|
||||
|
||||
// TODO: handle loading SN identity instead
|
||||
_identity = m_keyManager->getIdentityKey();
|
||||
_encryption = m_keyManager->getEncryptionKey();
|
||||
|
||||
if (_identity.IsZero())
|
||||
return false;
|
||||
if (_encryption.IsZero())
|
||||
return false;
|
||||
|
||||
if(whitelistRouters)
|
||||
{
|
||||
#if defined(ANDROID) || defined(IOS)
|
||||
@ -240,113 +205,17 @@ namespace llarp
|
||||
#if defined(_WIN32)
|
||||
LogError("running a service node on windows is not possible.");
|
||||
return false;
|
||||
#else
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl)
|
||||
{
|
||||
bool ret = false;
|
||||
std::stringstream ss;
|
||||
ss << "http://" << lokidRPCAddr << "/json_rpc";
|
||||
const auto url = ss.str();
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_ANY);
|
||||
const auto auth = lokidRPCUser + ":" + lokidRPCPassword;
|
||||
curl_easy_setopt(curl, CURLOPT_USERPWD, auth.c_str());
|
||||
curl_slist *list = nullptr;
|
||||
list = curl_slist_append(list, "Content-Type: application/json");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
|
||||
|
||||
nlohmann::json request = {{"id", "0"},
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "get_service_node_privkey"}};
|
||||
const auto data = request.dump();
|
||||
std::vector< char > resp;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, data.size());
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &RecvIdentKey);
|
||||
do
|
||||
{
|
||||
resp.clear();
|
||||
LogInfo("Getting Identity Keys from lokid...");
|
||||
if(curl_easy_perform(curl) == CURLE_OK)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto j = nlohmann::json::parse(resp);
|
||||
if(not j.is_object())
|
||||
continue;
|
||||
|
||||
const auto itr = j.find("result");
|
||||
if(itr == j.end())
|
||||
continue;
|
||||
if(not itr->is_object())
|
||||
continue;
|
||||
const auto k =
|
||||
(*itr)["service_node_ed25519_privkey"].get< std::string >();
|
||||
if(k.size() != (_identity.size() * 2))
|
||||
{
|
||||
if(k.empty())
|
||||
{
|
||||
LogError("lokid gave no identity key");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("lokid gave invalid identity key");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if(not HexDecode(k.c_str(), _identity.data(), _identity.size()))
|
||||
continue;
|
||||
if(CryptoManager::instance()->check_identity_privkey(_identity))
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("lokid gave bogus identity key");
|
||||
}
|
||||
}
|
||||
catch(nlohmann::json::exception &ex)
|
||||
{
|
||||
LogError("Bad response from lokid: ", ex.what());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("failed to get identity keys");
|
||||
}
|
||||
if(ret)
|
||||
{
|
||||
LogInfo("Got Identity Keys from lokid: ", RouterID(pubkey()));
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
} while(true);
|
||||
curl_easy_cleanup(curl);
|
||||
curl_slist_free_all(list);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("failed to init curl");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
return llarp_findOrCreateIdentity(ident_keyfile, _identity);
|
||||
}
|
||||
|
||||
if(usingSNSeed)
|
||||
{
|
||||
LogError("FIXME: load identity key from SNode seed");
|
||||
_identity = m_keyManager->getIdentityKey();
|
||||
_encryption = m_keyManager->getEncryptionKey();
|
||||
|
||||
if (_identity.IsZero())
|
||||
return false;
|
||||
if (_encryption.IsZero())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -368,7 +237,7 @@ namespace llarp
|
||||
if(!InitOutboundLinks())
|
||||
return false;
|
||||
|
||||
if (not m_keyManager->initializeFromDisk(*conf, true))
|
||||
if (not m_keyManager->initialize(*conf, true))
|
||||
return false;
|
||||
|
||||
return EnsureIdentity();
|
||||
|
@ -46,10 +46,6 @@ namespace llarp
|
||||
struct Config;
|
||||
} // namespace llarp
|
||||
|
||||
bool
|
||||
llarp_loadServiceNodeIdentityKey(const fs::path &fpath,
|
||||
llarp::SecretKey &secretkey);
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
struct Router final : public AbstractRouter
|
||||
|
Loading…
Reference in New Issue
Block a user