ed25519 api refactor (#1041)

This commit is contained in:
Alden Torres 2016-08-30 02:37:51 -04:00 committed by Arvid Norberg
parent ebe53883b5
commit 2ac45d17ef
15 changed files with 99 additions and 92 deletions

View File

@ -456,12 +456,10 @@ namespace
std::vector<char> 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;
}

View File

@ -57,9 +57,9 @@ namespace libtorrent
{ return std::string(reinterpret_cast<char const*>(&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
{

View File

@ -51,7 +51,6 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent
{
namespace aux { struct session_impl; }
struct counters;
#ifndef TORRENT_NO_DEPRECATE
struct session_status;

View File

@ -33,7 +33,6 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_DIRECT_REQUEST_HPP
#define TORRENT_DIRECT_REQUEST_HPP
#include <boost/function/function1.hpp>
#include <libtorrent/kademlia/msg.hpp>
#include <libtorrent/kademlia/traversal_algorithm.hpp>

View File

@ -38,14 +38,14 @@ POSSIBILITY OF SUCH DAMAGE.
#include <libtorrent/kademlia/types.hpp>
#include <array>
#include <memory>
#include <tuple>
namespace libtorrent {
namespace dht
{
// See documentation of internal random_bytes
TORRENT_EXPORT void ed25519_create_seed(std::array<char, 32>& seed);
TORRENT_EXPORT std::array<char, 32> 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<char, 32> const& seed);
TORRENT_EXPORT std::tuple<public_key, secret_key> ed25519_create_keypair(
std::array<char, 32> const& seed);
// Creates a signature of the given message with the given key pair.
TORRENT_EXPORT void ed25519_sign(signature& sig, span<char const> msg
TORRENT_EXPORT signature ed25519_sign(span<char const> 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<public_key> pk
, std::shared_ptr<secret_key> sk, std::array<char, 32> const& scalar);
TORRENT_EXPORT public_key ed25519_add_scalar(public_key const& pk
, std::array<char, 32> const& scalar);
TORRENT_EXPORT secret_key ed25519_add_scalar(secret_key const& sk
, std::array<char, 32> 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<char, 32>& secret
, public_key const& pk, secret_key const& sk);
TORRENT_EXPORT std::array<char, 32> ed25519_key_exchange(
public_key const& pk, secret_key const& sk);
}}

View File

@ -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<char const> v
, span<char const> salt
, sequence_number seq
, public_key const& pk
, secret_key const& sk
, signature& sig);
, secret_key const& sk);
class TORRENT_EXTRA_EXPORT item
{

View File

@ -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);

View File

@ -315,7 +315,7 @@ TORRENT_TEST(dht_dual_stack_mutable_item)
if (ticks == 2)
{
std::array<char, 32> 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<char, 64>& 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<char> 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;
});

View File

@ -709,4 +709,3 @@ namespace libtorrent { namespace dht
}
}}

View File

@ -38,30 +38,41 @@ namespace libtorrent {
namespace dht
{
void ed25519_create_seed(std::array<char, 32>& seed)
std::array<char, 32> ed25519_create_seed()
{
std::array<char, 32> seed;
aux::random_bytes(seed);
return seed;
}
void ed25519_create_keypair(public_key& pk
, secret_key& sk, std::array<char, 32> const& seed)
std::tuple<public_key, secret_key> ed25519_create_keypair(
std::array<char, 32> const& seed)
{
public_key pk;
secret_key sk;
auto const pk_ptr = reinterpret_cast<unsigned char*>(pk.bytes.data());
auto const sk_ptr = reinterpret_cast<unsigned char*>(sk.bytes.data());
auto const seed_ptr = reinterpret_cast<unsigned char const*>(seed.data());
libtorrent::ed25519_create_keypair(pk_ptr, sk_ptr, seed_ptr);
return std::make_tuple(pk, sk);
}
void ed25519_sign(signature& sig, span<char const> msg
signature ed25519_sign(span<char const> msg
, public_key const& pk, secret_key const& sk)
{
signature sig;
auto const sig_ptr = reinterpret_cast<unsigned char*>(sig.bytes.data());
auto const msg_ptr = reinterpret_cast<unsigned char const*>(msg.data());
auto const pk_ptr = reinterpret_cast<unsigned char const*>(pk.bytes.data());
auto const sk_ptr = reinterpret_cast<unsigned char const*>(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<public_key> pk
, std::shared_ptr<secret_key> sk, std::array<char, 32> const& scalar)
public_key ed25519_add_scalar(public_key const& pk
, std::array<char, 32> const& scalar)
{
auto const pk_ptr = pk
? reinterpret_cast<unsigned char*>(pk->bytes.data()) : nullptr;
auto const sk_ptr = sk
? reinterpret_cast<unsigned char*>(sk->bytes.data()) : nullptr;
public_key ret(pk.bytes.data());
auto const ret_ptr = reinterpret_cast<unsigned char*>(ret.bytes.data());
auto const scalar_ptr = reinterpret_cast<unsigned char const*>(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<char, 32>& secret
, public_key const& pk, secret_key const& sk)
secret_key ed25519_add_scalar(secret_key const& sk
, std::array<char, 32> const& scalar)
{
secret_key ret(sk.bytes.data());
auto const ret_ptr = reinterpret_cast<unsigned char*>(ret.bytes.data());
auto const scalar_ptr = reinterpret_cast<unsigned char const*>(scalar.data());
libtorrent::ed25519_add_scalar(nullptr, ret_ptr, scalar_ptr);
return ret;
}
std::array<char, 32> ed25519_key_exchange(
public_key const& pk, secret_key const& sk)
{
std::array<char, 32> secret;
auto const secret_ptr = reinterpret_cast<unsigned char*>(secret.data());
auto const pk_ptr = reinterpret_cast<unsigned char const*>(pk.bytes.data());
auto const sk_ptr = reinterpret_cast<unsigned char const*>(sk.bytes.data());
libtorrent::ed25519_key_exchange(secret_ptr, pk_ptr, sk_ptr);
return secret;
}
}}

View File

@ -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<char const> v
, span<char const> 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<char const> salt)
@ -166,8 +165,8 @@ void item::assign(entry v, span<char const> salt
char buffer[1000];
int bsize = bencode(buffer, v);
TORRENT_ASSERT(bsize <= 1000);
sign_mutable_item(span<char const>(buffer, bsize)
, salt, seq, pk, sk, m_sig);
m_sig = sign_mutable_item(span<char const>(buffer, bsize)
, salt, seq, pk, sk);
m_salt.assign(salt.data(), salt.size());
m_pk = pk;
m_seq = seq;

View File

@ -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);

View File

@ -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<char, 32> seed;
ed25519_create_seed(seed);
std::array<char, 32> 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<char const>(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<char const>(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<char const>(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<char const>(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<char const> 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<char const> 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"

View File

@ -53,12 +53,12 @@ namespace
std::vector<char> 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<char, 32> s1;
std::array<char, 32> s2;
s1.fill(0);
s2.fill(0);
std::array<char, 32> s1 = ed25519_create_seed();
std::array<char, 32> 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<char, 32> s1;
ed25519_create_seed(s1);
std::array<char, 32> 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<char, 32> n;
ed25519_create_seed(n);
std::array<char, 32> 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<public_key>(pk1)
, std::make_shared<secret_key>(), 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<public_key>()
, std::make_shared<secret_key>(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<char, 32> s1;
ed25519_create_seed(s1);
std::array<char, 32> 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<char, 32> s2;
ed25519_create_seed(s2);
std::array<char, 32> 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<char, 32> secretB;
ed25519_key_exchange(secretB, pk1, sk2);
std::array<char, 32> secretB = ed25519_key_exchange(pk1, sk2);
// user B sends to user A the public key
// user A performs the key exchange
std::array<char, 32> secretA;
ed25519_key_exchange(secretA, pk2, sk1);
std::array<char, 32> 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));

View File

@ -128,9 +128,9 @@ void put_string(entry& e, std::array<char, 64>& 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<char, 32> seed;
ed25519_create_seed(seed);
std::array<char, 32> 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