From 53598ec0e971d15a1f7f4ff29d341f6550ffcbe7 Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 28 Sep 2020 11:15:07 -0400 Subject: [PATCH] dont serialize ephemeral members of service identity (#1370) * prepare for keytool script * dont serialize ephemeral members in service key file * regnerate ephemeral members in service identity on load * add keygen script * use nacl for generating keys * format --- contrib/py/keygen/.gitignore | 1 + contrib/py/keygen/keygen.py | 35 ++++++++++++++++++++++++++ contrib/py/keygen/readme.md | 14 +++++++++++ llarp/router_contact.cpp | 11 ++++---- llarp/router_contact.hpp | 6 ++--- llarp/service/identity.cpp | 49 ++++++++++++++++++------------------ llarp/service/identity.hpp | 4 +++ 7 files changed, 85 insertions(+), 35 deletions(-) create mode 100644 contrib/py/keygen/.gitignore create mode 100755 contrib/py/keygen/keygen.py create mode 100644 contrib/py/keygen/readme.md diff --git a/contrib/py/keygen/.gitignore b/contrib/py/keygen/.gitignore new file mode 100644 index 000000000..a4ed579b5 --- /dev/null +++ b/contrib/py/keygen/.gitignore @@ -0,0 +1 @@ +*.private \ No newline at end of file diff --git a/contrib/py/keygen/keygen.py b/contrib/py/keygen/keygen.py new file mode 100755 index 000000000..fa6639301 --- /dev/null +++ b/contrib/py/keygen/keygen.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +""" +keygen tool for lokinet +""" + +from argparse import ArgumentParser as AP +from base64 import b32encode + +from nacl.signing import SigningKey + +def base32z(data): + """ base32 z encode """ + return b32encode(data).translate( + bytes.maketrans( + b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', + b'ybndrfg8ejkmcpqxot1uwisza345h769')).decode().rstrip('=') + + +def main(): + """ + main function for keygen + """ + argparser = AP() + argparser.add_argument('--keyfile', type=str, required=True, help='place to put generated keys') + args = argparser.parse_args() + secret = SigningKey.generate() + with open(args.keyfile, 'wb') as wfile: + wfile.write(b'd1:s64:') + wfile.write(secret.encode()) + wfile.write(secret.verify_key.encode()) + wfile.write(b'e') + print("{}.loki".format(base32z(secret.verify_key.encode()))) + +if __name__ == '__main__': + main() diff --git a/contrib/py/keygen/readme.md b/contrib/py/keygen/readme.md new file mode 100644 index 000000000..3ee03e09a --- /dev/null +++ b/contrib/py/keygen/readme.md @@ -0,0 +1,14 @@ +# lokinet key generator + +requires: + +* python3.7 or higher +* pynacl + +usage: + +```bash +./keygen.py --keyfile somekeyfile.private +``` + +this will overwrite the keyfile with new keys diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index 0718fa261..89ca14719 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -90,7 +90,7 @@ namespace llarp return BEncodeSignedSection(buf); else if (version == 1) { - //TODO: heapless serialization for this in lokimq's bt serialization. + // TODO: heapless serialization for this in lokimq's bt serialization. if (not buf->writef("li1e%lu:", signature.size())) return false; if (not buf->write(signature.begin(), signature.end())) @@ -224,16 +224,15 @@ namespace llarp { Clear(); - if (*buf->cur == 'd') // old format + if (*buf->cur == 'd') // old format { return DecodeVersion_0(buf); } - else if (*buf->cur != 'l') // if not dict, should be new format and start with list + else if (*buf->cur != 'l') // if not dict, should be new format and start with list { return false; } - try { std::string_view buf_view(reinterpret_cast(buf->cur), buf->sz); @@ -267,7 +266,7 @@ namespace llarp bool RouterContact::DecodeVersion_0(llarp_buffer_t* buf) { - signed_bt_dict = std::string(reinterpret_cast(buf->cur), buf->sz); + signed_bt_dict = std::string(reinterpret_cast(buf->cur), buf->sz); return bencode_decode_dict(*this, buf); } @@ -424,7 +423,7 @@ namespace llarp buf.sz = buf.cur - buf.base; buf.cur = buf.base; - signed_bt_dict = std::string(reinterpret_cast(buf.base), buf.sz); + signed_bt_dict = std::string(reinterpret_cast(buf.base), buf.sz); if (version == 0 or version == 1) { diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index 2f3c0d297..dc861a19f 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -20,7 +20,7 @@ namespace lokimq { struct bt_list_consumer; -} // namespace lokimq (forward declarations) +} // namespace lokimq namespace llarp { @@ -222,9 +222,7 @@ namespace llarp bool VerifySignature() const; - - private: - + private: bool DecodeVersion_0(llarp_buffer_t* buf); diff --git a/llarp/service/identity.cpp b/llarp/service/identity.cpp index f789d771f..abdab267c 100644 --- a/llarp/service/identity.cpp +++ b/llarp/service/identity.cpp @@ -13,16 +13,10 @@ namespace llarp { if (!bencode_start_dict(buf)) return false; - if (!BEncodeWriteDictEntry("e", enckey, buf)) - return false; - if (!BEncodeWriteDictEntry("q", pq, buf)) - return false; if (!BEncodeWriteDictEntry("s", signkey, buf)) return false; if (!BEncodeWriteDictInt("v", version, buf)) return false; - if (!BEncodeWriteDictEntry("x", vanity, buf)) - return false; return bencode_end(buf); } @@ -30,30 +24,23 @@ namespace llarp Identity::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) { bool read = false; - if (!BEncodeMaybeReadDictEntry("e", enckey, read, key, buf)) - return false; - if (key == "q") - { - llarp_buffer_t str; - if (!bencode_read_string(buf, &str)) - return false; - if (str.sz == 3200 || str.sz == 2818) - { - pq = str.base; - return true; - } - - return false; - } if (!BEncodeMaybeReadDictEntry("s", signkey, read, key, buf)) return false; if (!BEncodeMaybeReadDictInt("v", version, read, key, buf)) return false; - if (!BEncodeMaybeReadDictEntry("x", vanity, read, key, buf)) - return false; return read; } + void + Identity::Clear() + { + signkey.Zero(); + enckey.Zero(); + pq.Zero(); + derivedSignKey.Zero(); + vanity.Zero(); + } + void Identity::RegenerateKeys() { @@ -64,7 +51,7 @@ namespace llarp crypto->pqe_keygen(pq); if (not crypto->derive_subkey_private(derivedSignKey, signkey, 1)) { - LogError("failed to generate derived key"); + throw std::runtime_error("failed to derive subkey"); } } @@ -87,6 +74,9 @@ namespace llarp void Identity::EnsureKeys(fs::path fname, bool needBackup) { + // make sure we are empty + Clear(); + std::array tmp; llarp_buffer_t buf(tmp); @@ -137,12 +127,21 @@ namespace llarp if (!bencode_decode_dict(*this, &buf)) throw std::length_error("could not decode service identity"); + auto crypto = CryptoManager::instance(); + + // ensure that the encryption key is set + if (enckey.IsZero()) + crypto->encryption_keygen(enckey); + + // also ensure the ntru key is set + if (pq.IsZero()) + crypto->pqe_keygen(pq); + std::optional van; if (!vanity.IsZero()) van = vanity; // update pubkeys pub.Update(seckey_topublic(signkey), seckey_topublic(enckey), van); - auto crypto = CryptoManager::instance(); if (not crypto->derive_subkey_private(derivedSignKey, signkey, 1)) { throw std::runtime_error("failed to derive subkey"); diff --git a/llarp/service/identity.hpp b/llarp/service/identity.hpp index 349c2c2f5..ba8471883 100644 --- a/llarp/service/identity.hpp +++ b/llarp/service/identity.hpp @@ -55,6 +55,10 @@ namespace llarp bool Sign(Signature& sig, const llarp_buffer_t& buf) const; + + /// zero out all secret key members + void + Clear(); }; inline bool