Skip to content

Commit ec231d5

Browse files
authored
Merge pull request #2278 from jagerman/fix-persist-keygen
Fix [network]:keyfile issues
2 parents acc8c22 + cac2bac commit ec231d5

File tree

2 files changed

+42
-10
lines changed

2 files changed

+42
-10
lines changed

llarp/crypto/key_manager.cpp

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,45 @@ namespace llarp
1515
{
1616
log::trace(logcat, "{} called", __PRETTY_FUNCTION__);
1717

18-
// TODO FIXME: do we want to allow hex or other non-binary encodings here?
19-
auto tmp = util::file_to_string(fname, 64);
20-
if (tmp.size() != 64)
21-
throw std::invalid_argument{"Invalid key file {}: Expected 64 bytes, not {}"_format(fname, tmp.size())};
18+
auto tmp = util::file_to_string(fname);
19+
if ((tmp.size() == 128 or (tmp.size() == 129 and tmp.ends_with("\n"))
20+
or (tmp.size() == 130 and tmp.ends_with("\r\n")))
21+
and oxenc::is_hex(tmp.begin(), tmp.begin() + 128))
22+
oxenc::from_hex(tmp.begin(), tmp.begin() + 128, key.data());
23+
else if (tmp.size() == 64)
24+
std::memcpy(key.data(), tmp.data(), 64);
25+
else if (tmp.starts_with('d') and tmp.ends_with('e')) {
26+
// Old Lokinet keys were bt-dicts with the key we care about in the 's' key:
27+
oxenc::bt_dict_consumer old{tmp};
28+
auto oldkey = old.require_span<unsigned char, 64>("s");
29+
std::memcpy(key.data(), oldkey.data(), 64);
30+
old.finish();
31+
}
32+
else
33+
throw std::invalid_argument{
34+
"Invalid key file {} ({}B): Expected 64 bytes, 128 hex, or legacy lokinet key file"_format(fname, tmp.size())};
2235

23-
std::memcpy(key.data(), tmp.data(), 64);
2436
if (!key.check_pubkey())
2537
throw std::invalid_argument{"Invalid key file {}: Keypair seed and pubkey do not match"};
2638
}
2739

28-
bool KeyManager::write_to_file(const Ed25519SecretKey& key, const std::filesystem::path& fname)
40+
bool KeyManager::write_to_file(const Ed25519SecretKey& key, const std::filesystem::path& fname, bool hex)
2941
{
3042
log::trace(logcat, "{} called", __PRETTY_FUNCTION__);
3143
try
3244
{
33-
util::buffer_to_file(fname, key.to_view());
45+
if (hex)
46+
{
47+
std::string out;
48+
out.reserve(129);
49+
oxenc::to_hex(key.begin(), key.end(), std::back_inserter(out));
50+
out += '\n';
51+
util::buffer_to_file(fname, out);
52+
}
53+
else
54+
{
55+
util::buffer_to_file(fname, key.to_view());
56+
}
3457
}
3558
catch (const std::exception& e)
3659
{
@@ -45,7 +68,7 @@ namespace llarp
4568
{
4669
if (not is_relay)
4770
{
48-
if (config.network.keyfile)
71+
if (config.network.keyfile and std::filesystem::exists(*config.network.keyfile))
4972
{
5073
load_from_file(secret_key, *config.network.keyfile);
5174
log::info(logcat, "Successfully loaded persistent client key from config path");
@@ -54,6 +77,12 @@ namespace llarp
5477
{
5578
log::debug(logcat, "Client generating secret key...");
5679
secret_key = crypto::generate_ed25519();
80+
81+
if (config.network.keyfile && !write_to_file(secret_key, *config.network.keyfile))
82+
{
83+
log::critical(logcat, "Failed to save persistent key to {}", *config.network.keyfile);
84+
throw std::runtime_error{"Failed to save configured persistent key file"};
85+
}
5786
}
5887

5988
public_key.assign(secret_key.pubkey_span());

llarp/crypto/key_manager.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,12 @@ namespace llarp
3030
const RouterID& router_id() const { return public_key; }
3131

3232
// Helper functions to load a key; these are used by KeyManager itself, but are exposed as
33-
// they also have some uses for key loading outside KeyManager.
33+
// they also have some uses for key loading outside KeyManager. Loading accepts either 64
34+
// raw bytes, or 128 hex (with optional trailing newline), and verifies that the loaded
35+
// value contains matching pubkey and seed. Writing writes either raw bytes, or hex with a
36+
// trailing newline.
3437
static void load_from_file(Ed25519SecretKey& key, const std::filesystem::path& fname);
35-
static bool write_to_file(const Ed25519SecretKey& key, const std::filesystem::path& fname);
38+
static bool write_to_file(const Ed25519SecretKey& key, const std::filesystem::path& fname, bool hex = true);
3639
};
3740

3841
} // namespace llarp

0 commit comments

Comments
 (0)