From 2ac45d17ef52afcc53685eb92eaf78bfc6c1845a Mon Sep 17 00:00:00 2001 From: Alden Torres Date: Tue, 30 Aug 2016 02:37:51 -0400 Subject: [PATCH] ed25519 api refactor (#1041) --- bindings/python/src/session.cpp | 6 +- include/libtorrent/bloom_filter.hpp | 4 +- include/libtorrent/kademlia/dht_tracker.hpp | 1 - .../libtorrent/kademlia/direct_request.hpp | 1 - include/libtorrent/kademlia/ed25519.hpp | 20 ++++--- include/libtorrent/kademlia/item.hpp | 5 +- include/libtorrent/kademlia/node.hpp | 2 +- simulation/test_dht.cpp | 7 +-- src/kademlia/dht_tracker.cpp | 1 - src/kademlia/ed25519.cpp | 55 ++++++++++++++----- src/kademlia/item.cpp | 11 ++-- src/peer_connection.cpp | 4 +- test/test_dht.cpp | 17 +++--- test/test_ed25519.cpp | 46 ++++++---------- tools/dht_put.cpp | 11 ++-- 15 files changed, 99 insertions(+), 92 deletions(-) diff --git a/bindings/python/src/session.cpp b/bindings/python/src/session.cpp index 75b0117c6..6be3599eb 100644 --- a/bindings/python/src/session.cpp +++ b/bindings/python/src/session.cpp @@ -456,12 +456,10 @@ namespace std::vector buf; bencode(std::back_inserter(buf), e); ++seq; - dht::signature sign; - sign_mutable_item(buf, salt + dht::signature sign = sign_mutable_item(buf, salt , dht::sequence_number(seq) , dht::public_key(pk.data()) - , dht::secret_key(sk.data()) - , sign); + , dht::secret_key(sk.data())); sig = sign.bytes; } diff --git a/include/libtorrent/bloom_filter.hpp b/include/libtorrent/bloom_filter.hpp index 142f52b91..26ee279ff 100644 --- a/include/libtorrent/bloom_filter.hpp +++ b/include/libtorrent/bloom_filter.hpp @@ -57,9 +57,9 @@ namespace libtorrent { return std::string(reinterpret_cast(&bits[0]), N); } void from_string(char const* str) - { memcpy(bits, str, N); } + { std::memcpy(bits, str, N); } - void clear() { memset(bits, 0, N); } + void clear() { std::memset(bits, 0, N); } float size() const { diff --git a/include/libtorrent/kademlia/dht_tracker.hpp b/include/libtorrent/kademlia/dht_tracker.hpp index 316f28cfa..ad6a79045 100644 --- a/include/libtorrent/kademlia/dht_tracker.hpp +++ b/include/libtorrent/kademlia/dht_tracker.hpp @@ -51,7 +51,6 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { - namespace aux { struct session_impl; } struct counters; #ifndef TORRENT_NO_DEPRECATE struct session_status; diff --git a/include/libtorrent/kademlia/direct_request.hpp b/include/libtorrent/kademlia/direct_request.hpp index 380ccbdd9..2ed1ea979 100644 --- a/include/libtorrent/kademlia/direct_request.hpp +++ b/include/libtorrent/kademlia/direct_request.hpp @@ -33,7 +33,6 @@ POSSIBILITY OF SUCH DAMAGE. #ifndef TORRENT_DIRECT_REQUEST_HPP #define TORRENT_DIRECT_REQUEST_HPP -#include #include #include diff --git a/include/libtorrent/kademlia/ed25519.hpp b/include/libtorrent/kademlia/ed25519.hpp index 1c96e1a0a..d921f558c 100644 --- a/include/libtorrent/kademlia/ed25519.hpp +++ b/include/libtorrent/kademlia/ed25519.hpp @@ -38,14 +38,14 @@ POSSIBILITY OF SUCH DAMAGE. #include #include -#include +#include namespace libtorrent { namespace dht { // See documentation of internal random_bytes - TORRENT_EXPORT void ed25519_create_seed(std::array& seed); + TORRENT_EXPORT std::array ed25519_create_seed(); // Creates a new key pair from the given seed. // @@ -60,11 +60,11 @@ namespace dht // // The smaller format is not weaker by any means, in fact, it is only // the seed (32 bytes) that determines the point in the curve. - TORRENT_EXPORT void ed25519_create_keypair(public_key& pk - , secret_key& sk, std::array const& seed); + TORRENT_EXPORT std::tuple ed25519_create_keypair( + std::array const& seed); // Creates a signature of the given message with the given key pair. - TORRENT_EXPORT void ed25519_sign(signature& sig, span msg + TORRENT_EXPORT signature ed25519_sign(span msg , public_key const& pk, secret_key const& sk); // Verifies the signature on the given message using ``pk`` @@ -85,8 +85,10 @@ namespace dht // // see http://crypto.stackexchange.com/a/6215/4697 // see test_ed25519 for a practical example - TORRENT_EXPORT void ed25519_add_scalar(std::shared_ptr pk - , std::shared_ptr sk, std::array const& scalar); + TORRENT_EXPORT public_key ed25519_add_scalar(public_key const& pk + , std::array const& scalar); + TORRENT_EXPORT secret_key ed25519_add_scalar(secret_key const& sk + , std::array const& scalar); // Performs a key exchange on the given public key and private key, producing a // shared secret. It is recommended to hash the shared secret before using it. @@ -94,8 +96,8 @@ namespace dht // This is useful when two parties want to share a secret but both only knows // their respective public keys. // see test_ed25519 for a practical example - TORRENT_EXPORT void ed25519_key_exchange(std::array& secret - , public_key const& pk, secret_key const& sk); + TORRENT_EXPORT std::array ed25519_key_exchange( + public_key const& pk, secret_key const& sk); }} diff --git a/include/libtorrent/kademlia/item.hpp b/include/libtorrent/kademlia/item.hpp index 51da64e90..a4b7a6138 100644 --- a/include/libtorrent/kademlia/item.hpp +++ b/include/libtorrent/kademlia/item.hpp @@ -65,13 +65,12 @@ bool TORRENT_EXTRA_EXPORT verify_mutable_item( // is written into a 64 byte buffer pointed to by ``sig``. The caller // is responsible for allocating the destination buffer that's passed in // as the ``sig`` argument. Typically it would be allocated on the stack. -void TORRENT_EXPORT sign_mutable_item( +signature TORRENT_EXPORT sign_mutable_item( span v , span salt , sequence_number seq , public_key const& pk - , secret_key const& sk - , signature& sig); + , secret_key const& sk); class TORRENT_EXTRA_EXPORT item { diff --git a/include/libtorrent/kademlia/node.hpp b/include/libtorrent/kademlia/node.hpp index eae69693e..84eb6eacd 100644 --- a/include/libtorrent/kademlia/node.hpp +++ b/include/libtorrent/kademlia/node.hpp @@ -171,7 +171,7 @@ public: void new_write_key(); // pings the given node, and adds it to - // the routing table if it respons and if the + // the routing table if it response and if the // bucket is not full. void add_node(udp::endpoint node); diff --git a/simulation/test_dht.cpp b/simulation/test_dht.cpp index 4ff41e670..af5d57c7a 100644 --- a/simulation/test_dht.cpp +++ b/simulation/test_dht.cpp @@ -315,7 +315,7 @@ TORRENT_TEST(dht_dual_stack_mutable_item) if (ticks == 2) { std::array seed; - ed25519_create_keypair(pk, sk, seed); + std::tie(pk, sk) = lt::dht::ed25519_create_keypair(seed); ses.dht_put_item(pk.bytes, [&](lt::entry& item, std::array& sig , std::uint64_t& seq, std::string const& salt) @@ -323,10 +323,9 @@ TORRENT_TEST(dht_dual_stack_mutable_item) item = "mutable item"; seq = 1; std::vector v; - lt::dht::signature sign; lt::bencode(std::back_inserter(v), item); - lt::dht::sign_mutable_item(v, salt - , lt::dht::sequence_number(seq), pk, sk, sign); + lt::dht::signature sign = lt::dht::sign_mutable_item(v, salt + , lt::dht::sequence_number(seq), pk, sk); put_count++; sig = sign.bytes; }); diff --git a/src/kademlia/dht_tracker.cpp b/src/kademlia/dht_tracker.cpp index 57d08d449..fb665a0b0 100644 --- a/src/kademlia/dht_tracker.cpp +++ b/src/kademlia/dht_tracker.cpp @@ -709,4 +709,3 @@ namespace libtorrent { namespace dht } }} - diff --git a/src/kademlia/ed25519.cpp b/src/kademlia/ed25519.cpp index f8a3d9982..b47f72ad8 100644 --- a/src/kademlia/ed25519.cpp +++ b/src/kademlia/ed25519.cpp @@ -38,30 +38,41 @@ namespace libtorrent { namespace dht { - void ed25519_create_seed(std::array& seed) + std::array ed25519_create_seed() { + std::array seed; aux::random_bytes(seed); + return seed; } - void ed25519_create_keypair(public_key& pk - , secret_key& sk, std::array const& seed) + std::tuple ed25519_create_keypair( + std::array const& seed) { + public_key pk; + secret_key sk; + auto const pk_ptr = reinterpret_cast(pk.bytes.data()); auto const sk_ptr = reinterpret_cast(sk.bytes.data()); auto const seed_ptr = reinterpret_cast(seed.data()); libtorrent::ed25519_create_keypair(pk_ptr, sk_ptr, seed_ptr); + + return std::make_tuple(pk, sk); } - void ed25519_sign(signature& sig, span msg + signature ed25519_sign(span msg , public_key const& pk, secret_key const& sk) { + signature sig; + auto const sig_ptr = reinterpret_cast(sig.bytes.data()); auto const msg_ptr = reinterpret_cast(msg.data()); auto const pk_ptr = reinterpret_cast(pk.bytes.data()); auto const sk_ptr = reinterpret_cast(sk.bytes.data()); libtorrent::ed25519_sign(sig_ptr, msg_ptr, msg.size(), pk_ptr, sk_ptr); + + return sig; } bool ed25519_verify(signature const& sig @@ -74,26 +85,44 @@ namespace dht return libtorrent::ed25519_verify(sig_ptr, msg_ptr, msg.size(), pk_ptr) == 1; } - void ed25519_add_scalar(std::shared_ptr pk - , std::shared_ptr sk, std::array const& scalar) + public_key ed25519_add_scalar(public_key const& pk + , std::array const& scalar) { - auto const pk_ptr = pk - ? reinterpret_cast(pk->bytes.data()) : nullptr; - auto const sk_ptr = sk - ? reinterpret_cast(sk->bytes.data()) : nullptr; + public_key ret(pk.bytes.data()); + + auto const ret_ptr = reinterpret_cast(ret.bytes.data()); auto const scalar_ptr = reinterpret_cast(scalar.data()); - libtorrent::ed25519_add_scalar(pk_ptr, sk_ptr, scalar_ptr); + libtorrent::ed25519_add_scalar(ret_ptr, nullptr, scalar_ptr); + + return ret; } - void ed25519_key_exchange(std::array& secret - , public_key const& pk, secret_key const& sk) + secret_key ed25519_add_scalar(secret_key const& sk + , std::array const& scalar) { + secret_key ret(sk.bytes.data()); + + auto const ret_ptr = reinterpret_cast(ret.bytes.data()); + auto const scalar_ptr = reinterpret_cast(scalar.data()); + + libtorrent::ed25519_add_scalar(nullptr, ret_ptr, scalar_ptr); + + return ret; + } + + std::array ed25519_key_exchange( + public_key const& pk, secret_key const& sk) + { + std::array secret; + auto const secret_ptr = reinterpret_cast(secret.data()); auto const pk_ptr = reinterpret_cast(pk.bytes.data()); auto const sk_ptr = reinterpret_cast(sk.bytes.data()); libtorrent::ed25519_key_exchange(secret_ptr, pk_ptr, sk_ptr); + + return secret; } }} diff --git a/src/kademlia/item.cpp b/src/kademlia/item.cpp index fc3d1eecb..85eeffdd2 100644 --- a/src/kademlia/item.cpp +++ b/src/kademlia/item.cpp @@ -115,18 +115,17 @@ bool verify_mutable_item( // key) a signature ``sig`` is produced. The ``sig`` pointer must point to // at least 64 bytes of available space. This space is where the signature is // written. -void sign_mutable_item( +signature sign_mutable_item( span v , span salt , sequence_number const seq , public_key const& pk - , secret_key const& sk - , signature& sig) + , secret_key const& sk) { char str[1200]; int const len = canonical_string(v, seq, salt, str); - ed25519_sign(sig, {str, size_t(len)}, pk, sk); + return ed25519_sign({str, size_t(len)}, pk, sk); } item::item(public_key const& pk, span salt) @@ -166,8 +165,8 @@ void item::assign(entry v, span salt char buffer[1000]; int bsize = bencode(buffer, v); TORRENT_ASSERT(bsize <= 1000); - sign_mutable_item(span(buffer, bsize) - , salt, seq, pk, sk, m_sig); + m_sig = sign_mutable_item(span(buffer, bsize) + , salt, seq, pk, sk); m_salt.assign(salt.data(), salt.size()); m_pk = pk; m_seq = seq; diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 7d9b7b2f1..053aea39a 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -5704,7 +5704,7 @@ namespace libtorrent #ifndef TORRENT_DISABLE_LOGGING peer_log(peer_log_alert::incoming, "READ" - , "%d bytes", int(bytes_transferred)); + , "%d bytes", bytes_transferred); #endif } @@ -6063,7 +6063,7 @@ namespace libtorrent // -------------------------- void peer_connection::on_send_data(error_code const& error - , std::size_t bytes_transferred) + , std::size_t const bytes_transferred) { TORRENT_ASSERT(is_single_thread()); m_counters.inc_stats_counter(counters::on_write_counter); diff --git a/test/test_dht.cpp b/test/test_dht.cpp index 3dcfc9b9e..0aad7de50 100644 --- a/test/test_dht.cpp +++ b/test/test_dht.cpp @@ -1052,10 +1052,9 @@ void test_put(address(&rand_addr)()) seq = sequence_number(4); std::fprintf(stderr, "\nTEST GET/PUT%s \ngenerating ed25519 keys\n\n" , with_salt ? " with-salt" : " no-salt"); - std::array seed; - ed25519_create_seed(seed); + std::array seed = ed25519_create_seed(); - ed25519_create_keypair(pk, sk, seed); + std::tie(pk, sk) = ed25519_create_keypair(seed); std::fprintf(stderr, "pub: %s priv: %s\n" , aux::to_hex(pk.bytes).c_str() , aux::to_hex(sk.bytes).c_str()); @@ -1104,7 +1103,7 @@ void test_put(address(&rand_addr)()) } itemv = span(buffer, bencode(buffer, items[0].ent)); - sign_mutable_item(itemv, salt, seq, pk, sk, sig); + sig = sign_mutable_item(itemv, salt, seq, pk, sk); TEST_EQUAL(verify_mutable_item(itemv, salt, seq, pk, sig), true); send_dht_request(t.dht_node, "put", t.source, &response @@ -1175,7 +1174,7 @@ void test_put(address(&rand_addr)()) // also test that invalid signatures fail! itemv = span(buffer, bencode(buffer, items[0].ent)); - sign_mutable_item(itemv, salt, seq, pk, sk, sig); + sig = sign_mutable_item(itemv, salt, seq, pk, sk); TEST_EQUAL(verify_mutable_item(itemv, salt, seq, pk, sig), 1); // break the signature sig.bytes[2] ^= 0xaa; @@ -1240,7 +1239,7 @@ void test_put(address(&rand_addr)()) seq = next_seq(seq); // put item 1 itemv = span(buffer, bencode(buffer, items[1].ent)); - sign_mutable_item(itemv, salt, seq, pk, sk, sig); + sig = sign_mutable_item(itemv, salt, seq, pk, sk); TEST_EQUAL(verify_mutable_item(itemv, salt, seq, pk, sig), 1); TEST_CHECK(item_target_id(salt, pk) == target_id); @@ -1844,7 +1843,7 @@ void test_mutable_get(address(&rand_addr)(), bool const with_salt) signature sig; itemv = span(buffer, bencode(buffer, items[0].ent)); - sign_mutable_item(itemv, salt, seq, pk, sk, sig); + sig = sign_mutable_item(itemv, salt, seq, pk, sk); send_dht_response(t.dht_node, response, initial_node , msg_args() .token("10") @@ -2390,7 +2389,7 @@ TORRENT_TEST(signing_test1) span empty_salt; signature sig; - sign_mutable_item(test_content, empty_salt, sequence_number(1), pk, sk, sig); + sig = sign_mutable_item(test_content, empty_salt, sequence_number(1), pk, sk); TEST_EQUAL(aux::to_hex(sig.bytes) , "305ac8aeb6c9c151fa120f120ea2cfb923564e11552d06a5d856091e5e853cff" @@ -2414,7 +2413,7 @@ TORRENT_TEST(signing_test2) span test_salt("foobar", 6); // test vector 2 (the keypair is the same as test 1) - sign_mutable_item(test_content, test_salt, sequence_number(1), pk, sk, sig); + sig = sign_mutable_item(test_content, test_salt, sequence_number(1), pk, sk); TEST_EQUAL(aux::to_hex(sig.bytes) , "6834284b6b24c3204eb2fea824d82f88883a3d95e8b4a21b8c0ded553d17d17d" diff --git a/test/test_ed25519.cpp b/test/test_ed25519.cpp index d5a1de707..a3c701e69 100644 --- a/test/test_ed25519.cpp +++ b/test/test_ed25519.cpp @@ -53,12 +53,12 @@ namespace std::vector msg(int(message.size()) / 2); aux::from_hex(seed, s.data()); - ed25519_create_keypair(pk, sk, s); + std::tie(pk, sk) = ed25519_create_keypair(s); TEST_EQUAL(aux::to_hex(pk.bytes), pub); aux::from_hex(message, msg.data()); - ed25519_sign(sig, msg, pk, sk); + sig = ed25519_sign(msg, pk, sk); TEST_EQUAL(aux::to_hex(sig.bytes), sig_hex); @@ -201,14 +201,9 @@ TORRENT_TEST(ed25519_test_vec1) TORRENT_TEST(create_seed) { - std::array s1; - std::array s2; - s1.fill(0); - s2.fill(0); + std::array s1 = ed25519_create_seed(); + std::array s2 = ed25519_create_seed(); - TEST_CHECK(s1 == s2); - ed25519_create_seed(s1); - ed25519_create_seed(s2); TEST_CHECK(s1 != s2); // what are the odds int n1 = 0; @@ -225,37 +220,32 @@ TORRENT_TEST(create_seed) TORRENT_TEST(add_scalar) { // client - std::array s1; - ed25519_create_seed(s1); + std::array s1 = ed25519_create_seed(); public_key pk1; secret_key sk1; - ed25519_create_keypair(pk1, sk1, s1); + std::tie(pk1, sk1) = ed25519_create_keypair(s1); // client sends to server the public key // server generates another seed, it could be an scalar // n = HMAC(k, pk1) and sends it back to the client // see http://crypto.stackexchange.com/a/6215/4697 - std::array n; - ed25519_create_seed(n); + std::array n = ed25519_create_seed(); // now the server knows that the client's public key // must be (or assigns) pk1 + n - ed25519_add_scalar(std::make_shared(pk1) - , std::make_shared(), n); + pk1 = ed25519_add_scalar(pk1, n); // server sends n to the client // the client, in order to properly sign messages, must // adjust the private key - ed25519_add_scalar(std::make_shared() - , std::make_shared(sk1), n); + sk1 = ed25519_add_scalar(sk1, n); // test sign and verification std::string msg = "Hello world"; - signature sig; - ed25519_sign(sig, msg, pk1, sk1); + signature sig = ed25519_sign(msg, pk1, sk1); bool r = ed25519_verify(sig, msg, pk1); TEST_CHECK(r); } @@ -263,32 +253,28 @@ TORRENT_TEST(add_scalar) TORRENT_TEST(key_exchange) { // user A - std::array s1; - ed25519_create_seed(s1); + std::array s1 = ed25519_create_seed(); public_key pk1; secret_key sk1; - ed25519_create_keypair(pk1, sk1, s1); + std::tie(pk1, sk1) = ed25519_create_keypair(s1); // user A sends to user B the public key // user B - std::array s2; - ed25519_create_seed(s2); + std::array s2 = ed25519_create_seed(); public_key pk2; secret_key sk2; - ed25519_create_keypair(pk2, sk2, s2); + std::tie(pk2, sk2) = ed25519_create_keypair(s2); // user B performs the key exchange - std::array secretB; - ed25519_key_exchange(secretB, pk1, sk2); + std::array secretB = ed25519_key_exchange(pk1, sk2); // user B sends to user A the public key // user A performs the key exchange - std::array secretA; - ed25519_key_exchange(secretA, pk2, sk1); + std::array secretA = ed25519_key_exchange(pk2, sk1); // now both users A and B must shared the same secret TEST_EQUAL(aux::to_hex(secretA), aux::to_hex(secretB)); diff --git a/tools/dht_put.cpp b/tools/dht_put.cpp index 973e58259..bbe576a55 100644 --- a/tools/dht_put.cpp +++ b/tools/dht_put.cpp @@ -128,9 +128,9 @@ void put_string(entry& e, std::array& sig bencode(std::back_inserter(buf), e); dht::signature sign; ++seq; - sign_mutable_item(buf, salt, dht::sequence_number(seq) + sign = sign_mutable_item(buf, salt, dht::sequence_number(seq) , dht::public_key(pk.data()) - , dht::secret_key(sk.data()), sign); + , dht::secret_key(sk.data())); sig = sign.bytes; } @@ -162,7 +162,7 @@ int dump_key(char *filename) public_key pk; secret_key sk; - ed25519_create_keypair(pk, sk, seed); + std::tie(pk, sk) = ed25519_create_keypair(seed); std::printf("public key: %s\nprivate key: %s\n" , to_hex(pk.bytes).c_str() @@ -173,8 +173,7 @@ int dump_key(char *filename) int generate_key(char* filename) { - std::array seed; - ed25519_create_seed(seed); + std::array seed = ed25519_create_seed(); FILE* f = std::fopen(filename, "wb+"); if (f == nullptr) @@ -357,7 +356,7 @@ int main(int argc, char* argv[]) public_key pk; secret_key sk; - ed25519_create_keypair(pk, sk, seed); + std::tie(pk, sk) = ed25519_create_keypair(seed); bootstrap(s); s.dht_put_item(pk.bytes, std::bind(&put_string, _1, _2, _3, _4