forked from premiere/premiere-libtorrent
better integration and API for ed25519 (#1037)
better integration and API for ed25519. using shared_ptr in ed25519_add_scalar
This commit is contained in:
parent
118e30fd86
commit
32f5f8f257
|
@ -140,6 +140,7 @@ set(kademlia_sources
|
|||
item
|
||||
get_peers
|
||||
get_item
|
||||
ed25519
|
||||
)
|
||||
|
||||
# -- ed25519 --
|
||||
|
@ -150,7 +151,6 @@ set(ed25519_sources
|
|||
key_exchange
|
||||
keypair
|
||||
sc
|
||||
seed
|
||||
sign
|
||||
verify
|
||||
)
|
||||
|
|
2
Jamfile
2
Jamfile
|
@ -706,6 +706,7 @@ KADEMLIA_SOURCES =
|
|||
item
|
||||
get_item
|
||||
put_data
|
||||
ed25519
|
||||
;
|
||||
|
||||
ED25519_SOURCES =
|
||||
|
@ -715,7 +716,6 @@ ED25519_SOURCES =
|
|||
key_exchange
|
||||
keypair
|
||||
sc
|
||||
seed
|
||||
sign
|
||||
verify
|
||||
;
|
||||
|
|
|
@ -2,9 +2,12 @@
|
|||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
||||
|
||||
#include "libtorrent/ed25519.hpp"
|
||||
#include "libtorrent/hasher512.hpp"
|
||||
#include "ge.h"
|
||||
#include "sc.h"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
/* see http://crypto.stackexchange.com/a/6215/4697 */
|
||||
void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar) {
|
||||
|
@ -28,6 +31,17 @@ void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, c
|
|||
/* private key: a = n + t */
|
||||
if (private_key) {
|
||||
sc_muladd(private_key, SC_1, n, private_key);
|
||||
|
||||
// Fixed ed25519_add_scalar vulnerability.
|
||||
// https://github.com/orlp/ed25519/commit/09ec167693edff9478b53d772487e94569cb58d0
|
||||
// https://github.com/orlp/ed25519/issues/3
|
||||
hasher512 hash;
|
||||
hash.update({reinterpret_cast<char const*>(private_key) + 32, 32});
|
||||
hash.update({reinterpret_cast<char const*>(scalar), 32});
|
||||
sha512_hash hashbuf = hash.final();
|
||||
for (i = 0; i < 32; ++i) {
|
||||
private_key[32 + i] = hashbuf[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* public key: A = nB + T */
|
||||
|
@ -57,3 +71,5 @@ void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, c
|
|||
ge_p3_tobytes(public_key, &A);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
#include "libtorrent/ed25519.hpp"
|
||||
#include "fe.h"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
void ed25519_key_exchange(unsigned char *shared_secret
|
||||
, const unsigned char *public_key, const unsigned char *private_key) {
|
||||
unsigned char e[32];
|
||||
|
@ -81,3 +84,5 @@ void ed25519_key_exchange(unsigned char *shared_secret
|
|||
fe_mul(x2, x2, z2);
|
||||
fe_tobytes(shared_secret, x2);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
#include "libtorrent/hasher512.hpp"
|
||||
#include "ge.h"
|
||||
|
||||
using namespace libtorrent;
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed) {
|
||||
ge_p3 A;
|
||||
|
@ -19,3 +20,5 @@ void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_ke
|
|||
ge_scalarmult_base(&A, private_key);
|
||||
ge_p3_tobytes(public_key, &A);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
// ignore warnings in this file
|
||||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
||||
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/system/system_error.hpp>
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/ed25519.hpp"
|
||||
|
||||
#ifndef ED25519_NO_SEED
|
||||
|
||||
#if TORRENT_USE_CRYPTOGRAPHIC_BUFFER
|
||||
#include <robuffer.h>
|
||||
#include <wrl/client.h>
|
||||
using namespace Windows::Security::Cryptography;
|
||||
using namespace Windows::Storage::Streams;
|
||||
using namespace Microsoft::WRL;
|
||||
#elif defined _WIN32
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
void ed25519_create_seed(unsigned char *seed) {
|
||||
#if TORRENT_USE_CRYPTOGRAPHIC_BUFFER
|
||||
IBuffer^ seedBuffer = CryptographicBuffer::GenerateRandom(32);
|
||||
ComPtr<IBufferByteAccess> bufferByteAccess;
|
||||
reinterpret_cast<IInspectable*>(seedBuffer)->QueryInterface(IID_PPV_ARGS(&bufferByteAccess));
|
||||
bufferByteAccess->Buffer(&seed);
|
||||
#elif defined _WIN32
|
||||
HCRYPTPROV prov;
|
||||
|
||||
if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
|
||||
throw boost::system::system_error(boost::system::error_code(GetLastError()
|
||||
, boost::system::system_category()));
|
||||
}
|
||||
|
||||
if (!CryptGenRandom(prov, 32, seed)) {
|
||||
CryptReleaseContext(prov, 0);
|
||||
throw boost::system::system_error(boost::system::error_code(GetLastError()
|
||||
, boost::system::system_category()));
|
||||
}
|
||||
|
||||
CryptReleaseContext(prov, 0);
|
||||
#else
|
||||
FILE *f = fopen("/dev/urandom", "rb");
|
||||
|
||||
if (f == NULL) {
|
||||
throw boost::system::system_error(boost::system::error_code(errno, boost::system::system_category()));
|
||||
}
|
||||
|
||||
int read = fread(seed, 1, 32, f);
|
||||
if (read != 32) {
|
||||
fclose(f);
|
||||
throw boost::system::system_error(boost::system::error_code(errno, boost::system::system_category()));
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -6,7 +6,8 @@
|
|||
#include "ge.h"
|
||||
#include "sc.h"
|
||||
|
||||
using namespace libtorrent;
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key) {
|
||||
ge_p3 R;
|
||||
|
@ -32,3 +33,5 @@ void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t
|
|||
, private_key
|
||||
, reinterpret_cast<unsigned char*>(r.data()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
#include "ge.h"
|
||||
#include "sc.h"
|
||||
|
||||
using namespace libtorrent;
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
static int consttime_equal(const unsigned char *x, const unsigned char *y) {
|
||||
unsigned char r = 0;
|
||||
|
@ -79,3 +80,5 @@ int ed25519_verify(const unsigned char *signature, const unsigned char *message,
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -197,6 +197,7 @@ nobase_include_HEADERS = \
|
|||
kademlia/rpc_manager.hpp \
|
||||
kademlia/traversal_algorithm.hpp \
|
||||
kademlia/types.hpp \
|
||||
kademlia/ed25519.hpp \
|
||||
kademlia/item.hpp \
|
||||
kademlia/get_item.hpp \
|
||||
kademlia/get_peers.hpp
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "libtorrent/export.hpp" // for TORRENT_EXPORT
|
||||
#include <stddef.h> // for size_t
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
enum
|
||||
{
|
||||
ed25519_seed_size = 32,
|
||||
|
@ -14,21 +16,12 @@ enum
|
|||
ed25519_shared_secret_size = 32
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
#ifndef ED25519_NO_SEED
|
||||
void TORRENT_EXPORT ed25519_create_seed(unsigned char *seed);
|
||||
#endif
|
||||
|
||||
// TODO: 3 wrap these into C++ calls with proper types (dht::signature,
|
||||
// public_key and secret_key)
|
||||
void TORRENT_EXPORT ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed);
|
||||
void TORRENT_EXPORT ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key);
|
||||
int TORRENT_EXPORT ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key);
|
||||
void TORRENT_EXPORT ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar);
|
||||
void TORRENT_EXPORT ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key);
|
||||
void TORRENT_EXTRA_EXPORT ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed);
|
||||
void TORRENT_EXTRA_EXPORT ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key);
|
||||
int TORRENT_EXTRA_EXPORT ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key);
|
||||
void TORRENT_EXTRA_EXPORT ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar);
|
||||
void TORRENT_EXTRA_EXPORT ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key);
|
||||
|
||||
}
|
||||
|
||||
#endif // ED25519_HPP
|
||||
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2016, Arvid Norberg, Alden Torres
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef LIBTORRENT_ED25519_HPP
|
||||
#define LIBTORRENT_ED25519_HPP
|
||||
|
||||
#include <libtorrent/config.hpp>
|
||||
#include <libtorrent/span.hpp>
|
||||
#include <libtorrent/kademlia/types.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
namespace libtorrent {
|
||||
namespace dht
|
||||
{
|
||||
|
||||
// See documentation of internal random_bytes
|
||||
TORRENT_EXPORT void ed25519_create_seed(std::array<char, 32>& seed);
|
||||
|
||||
// Creates a new key pair from the given seed.
|
||||
//
|
||||
// It's important to clarify that the seed completely determines
|
||||
// the key pair. Then it's enough to save the seed and the
|
||||
// public key as the key-pair in a buffer of 64 bytes. The standard
|
||||
// is (32 bytes seed, 32 bytes public key).
|
||||
//
|
||||
// This function does work with a given seed, giving you a pair of
|
||||
// (64 bytes private key, 32 bytes public key). It's a trade-off between
|
||||
// space and CPU, saving in one format or another.
|
||||
//
|
||||
// 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);
|
||||
|
||||
// Creates a signature of the given message with the given key pair.
|
||||
TORRENT_EXPORT void ed25519_sign(signature& sig, span<char const> msg
|
||||
, public_key const& pk, secret_key const& sk);
|
||||
|
||||
// Verifies the signature on the given message using ``pk``
|
||||
TORRENT_EXPORT bool ed25519_verify(signature const& sig
|
||||
, span<char const> msg, public_key const& pk);
|
||||
|
||||
// Adds a scalar to the given key pair where scalar is a 32 byte buffer
|
||||
// (possibly generated with `ed25519_create_seed`), generating a new key pair.
|
||||
//
|
||||
// You can calculate the public key sum without knowing the private key and
|
||||
// vice versa by passing in null for the key you don't know. This is useful
|
||||
// when a third party (an authoritative server for example) needs to enforce
|
||||
// randomness on a key pair while only knowing the public key of the other
|
||||
// side.
|
||||
//
|
||||
// Warning: the last bit of the scalar is ignored - if comparing scalars make
|
||||
// sure to clear it with `scalar[31] &= 127`.
|
||||
//
|
||||
// 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);
|
||||
|
||||
// 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.
|
||||
//
|
||||
// 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);
|
||||
|
||||
}}
|
||||
|
||||
#endif // LIBTORRENT_ED25519_HPP
|
|
@ -31,6 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
*/
|
||||
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/span.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <random>
|
||||
|
@ -47,6 +48,17 @@ namespace libtorrent
|
|||
{
|
||||
std::shuffle(first, last, random_engine());
|
||||
}
|
||||
|
||||
// Fills the buffer with random bytes.
|
||||
//
|
||||
// This functions perform differently under different setups
|
||||
// For Windows and all platforms when compiled with libcrypto, it
|
||||
// generates cryptographically random bytes.
|
||||
// If the above conditions are not true, then a standard
|
||||
// std::independent_bits_engine<std::mt19937, 8, std::uint8_t>
|
||||
// generator is used.
|
||||
//
|
||||
TORRENT_EXTRA_EXPORT void random_bytes(span<char> buffer);
|
||||
}
|
||||
|
||||
TORRENT_EXTRA_EXPORT std::uint32_t random(std::uint32_t max);
|
||||
|
|
|
@ -45,7 +45,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/socket_io.hpp"
|
||||
#include "setup_swarm.hpp"
|
||||
#include "setup_dht.hpp"
|
||||
#include "libtorrent/ed25519.hpp"
|
||||
#include "libtorrent/kademlia/ed25519.hpp"
|
||||
#include "libtorrent/bencode.hpp"
|
||||
#include "libtorrent/kademlia/item.hpp"
|
||||
#include <boost/bind.hpp>
|
||||
|
@ -314,9 +314,8 @@ TORRENT_TEST(dht_dual_stack_mutable_item)
|
|||
}
|
||||
if (ticks == 2)
|
||||
{
|
||||
std::array<unsigned char, ed25519_seed_size> seed;
|
||||
ed25519_create_keypair((unsigned char*)pk.bytes.data()
|
||||
, (unsigned char*)sk.bytes.data(), seed.data());
|
||||
std::array<char, 32> seed;
|
||||
ed25519_create_keypair(pk, sk, seed);
|
||||
|
||||
ses.dht_put_item(pk.bytes, [&](lt::entry& item, std::array<char, 64>& sig
|
||||
, std::uint64_t& seq, std::string const& salt)
|
||||
|
|
|
@ -20,13 +20,13 @@ KADEMLIA_SOURCES = \
|
|||
kademlia/get_peers.cpp \
|
||||
kademlia/get_item.cpp \
|
||||
kademlia/item.cpp \
|
||||
kademlia/ed25519.cpp \
|
||||
../ed25519/src/add_scalar.cpp \
|
||||
../ed25519/src/fe.cpp \
|
||||
../ed25519/src/ge.cpp \
|
||||
../ed25519/src/key_exchange.cpp \
|
||||
../ed25519/src/keypair.cpp \
|
||||
../ed25519/src/sc.cpp \
|
||||
../ed25519/src/seed.cpp \
|
||||
../ed25519/src/sign.cpp \
|
||||
../ed25519/src/verify.cpp \
|
||||
hasher512.cpp
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2016, Arvid Norberg, Alden Torres
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include <libtorrent/kademlia/ed25519.hpp>
|
||||
#include <libtorrent/random.hpp>
|
||||
#include <libtorrent/ed25519.hpp>
|
||||
|
||||
namespace libtorrent {
|
||||
namespace dht
|
||||
{
|
||||
|
||||
void ed25519_create_seed(std::array<char, 32>& seed)
|
||||
{
|
||||
aux::random_bytes(seed);
|
||||
}
|
||||
|
||||
void ed25519_create_keypair(public_key& pk
|
||||
, secret_key& sk, std::array<char, 32> const& seed)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
void ed25519_sign(signature& sig, span<char const> msg
|
||||
, public_key const& pk, secret_key const& sk)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
bool ed25519_verify(signature const& sig
|
||||
, span<char const> msg, public_key const& pk)
|
||||
{
|
||||
auto const sig_ptr = reinterpret_cast<unsigned char const*>(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());
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
auto const scalar_ptr = reinterpret_cast<unsigned char const*>(scalar.data());
|
||||
|
||||
libtorrent::ed25519_add_scalar(pk_ptr, sk_ptr, scalar_ptr);
|
||||
}
|
||||
|
||||
void ed25519_key_exchange(std::array<char, 32>& secret
|
||||
, public_key const& pk, secret_key const& sk)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
}}
|
|
@ -34,7 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <libtorrent/kademlia/item.hpp>
|
||||
#include <libtorrent/bencode.hpp>
|
||||
#include <libtorrent/span.hpp>
|
||||
#include <libtorrent/ed25519.hpp>
|
||||
#include <libtorrent/kademlia/ed25519.hpp>
|
||||
|
||||
#include <cstdio> // for snprintf
|
||||
#include <cinttypes> // for PRId64 et.al.
|
||||
|
@ -106,10 +106,7 @@ bool verify_mutable_item(
|
|||
char str[1200];
|
||||
int len = canonical_string(v, seq, salt, str);
|
||||
|
||||
return ed25519_verify(reinterpret_cast<unsigned char const*>(sig.bytes.data())
|
||||
, reinterpret_cast<unsigned char const*>(str)
|
||||
, len
|
||||
, reinterpret_cast<unsigned char const*>(pk.bytes.data())) == 1;
|
||||
return ed25519_verify(sig, {str, size_t(len)}, pk);
|
||||
}
|
||||
|
||||
// given the bencoded buffer ``v``, the salt (which is optional and may have
|
||||
|
@ -129,12 +126,7 @@ void sign_mutable_item(
|
|||
char str[1200];
|
||||
int const len = canonical_string(v, seq, salt, str);
|
||||
|
||||
ed25519_sign(reinterpret_cast<unsigned char*>(sig.bytes.data())
|
||||
, reinterpret_cast<unsigned char const*>(str)
|
||||
, len
|
||||
, reinterpret_cast<unsigned char const*>(pk.bytes.data())
|
||||
, reinterpret_cast<unsigned char const*>(sk.bytes.data())
|
||||
);
|
||||
ed25519_sign(sig, {str, size_t(len)}, pk, sk);
|
||||
}
|
||||
|
||||
item::item(public_key const& pk, span<char const> salt)
|
||||
|
|
|
@ -32,6 +32,19 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/random.hpp"
|
||||
#include "libtorrent/error_code.hpp"
|
||||
|
||||
#if TORRENT_USE_CRYPTOAPI
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
#elif defined TORRENT_USE_LIBCRYPTO
|
||||
extern "C" {
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/err.h>
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
@ -48,6 +61,51 @@ namespace libtorrent
|
|||
#endif
|
||||
return rng;
|
||||
}
|
||||
|
||||
void random_bytes(span<char> buffer)
|
||||
{
|
||||
#if TORRENT_USE_CRYPTOAPI
|
||||
HCRYPTPROV prov;
|
||||
|
||||
if (!CryptAcquireContext(&prov, NULL, NULL
|
||||
, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
|
||||
{
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
throw system_error(error_code(GetLastError(), system_category()));
|
||||
#else
|
||||
std::terminate();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!CryptGenRandom(prov, int(buffer.size())
|
||||
, reinterpret_cast<BYTE*>(buffer.data())))
|
||||
{
|
||||
CryptReleaseContext(prov, 0);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
throw system_error(error_code(GetLastError(), system_category()));
|
||||
#else
|
||||
std::terminate();
|
||||
#endif
|
||||
}
|
||||
|
||||
CryptReleaseContext(prov, 0);
|
||||
#elif defined TORRENT_USE_LIBCRYPTO
|
||||
int r = RAND_bytes(reinterpret_cast<unsigned char*>(buffer.data())
|
||||
, int(buffer.size()));
|
||||
if (r != 1)
|
||||
{
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
throw system_error(error_code(ERR_get_error(), system_category()));
|
||||
#else
|
||||
std::terminate();
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
std::uint32_t s = random(0xffffffff);
|
||||
std::independent_bits_engine<std::mt19937, 8, std::uint8_t> generator(s);
|
||||
std::generate(buffer.begin(), buffer.end(), std::ref(generator));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
std::uint32_t random(std::uint32_t max)
|
||||
|
|
|
@ -145,7 +145,6 @@ test-suite libtorrent :
|
|||
test_dht_storage.cpp
|
||||
test_direct_dht.cpp
|
||||
test_hasher512.cpp
|
||||
test_ed25519.cpp
|
||||
]
|
||||
|
||||
[ run test_string.cpp
|
||||
|
@ -156,6 +155,7 @@ test-suite libtorrent :
|
|||
[ run test_bitfield.cpp ]
|
||||
[ run test_crc32.cpp ]
|
||||
[ run test_ffs.cpp ]
|
||||
[ run test_ed25519.cpp ]
|
||||
[ run test_gzip.cpp ]
|
||||
[ run test_receive_buffer.cpp ]
|
||||
[ run test_alert_manager.cpp ]
|
||||
|
@ -230,6 +230,7 @@ alias win-tests :
|
|||
test_gzip
|
||||
test_piece_picker
|
||||
test_ffs
|
||||
test_ed25519
|
||||
test_session_params
|
||||
;
|
||||
|
||||
|
@ -240,6 +241,7 @@ alias arm-tests :
|
|||
test_bitfield
|
||||
test_crc32
|
||||
test_ffs
|
||||
test_ed25519
|
||||
;
|
||||
|
||||
explicit arm-tests ;
|
||||
|
|
|
@ -42,7 +42,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/broadcast_socket.hpp" // for supports_ipv6
|
||||
#include "libtorrent/performance_counters.hpp" // for counters
|
||||
#include "libtorrent/random.hpp"
|
||||
#include "libtorrent/ed25519.hpp"
|
||||
#include "libtorrent/kademlia/ed25519.hpp"
|
||||
#include "libtorrent/hex.hpp" // to_hex, from_hex
|
||||
|
||||
#include "libtorrent/kademlia/node_id.hpp"
|
||||
|
@ -1052,11 +1052,10 @@ 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");
|
||||
unsigned char seed[32];
|
||||
std::array<char, 32> seed;
|
||||
ed25519_create_seed(seed);
|
||||
|
||||
ed25519_create_keypair((unsigned char*)pk.bytes.data()
|
||||
, (unsigned char*)sk.bytes.data(), seed);
|
||||
ed25519_create_keypair(pk, sk, seed);
|
||||
std::fprintf(stderr, "pub: %s priv: %s\n"
|
||||
, aux::to_hex(pk.bytes).c_str()
|
||||
, aux::to_hex(sk.bytes).c_str());
|
||||
|
|
|
@ -30,44 +30,39 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
*/
|
||||
|
||||
#include "test.hpp"
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "libtorrent/ed25519.hpp"
|
||||
#include "libtorrent/kademlia/ed25519.hpp"
|
||||
#include "libtorrent/hex.hpp"
|
||||
|
||||
#include "test.hpp"
|
||||
|
||||
using namespace libtorrent;
|
||||
using namespace libtorrent::dht;
|
||||
|
||||
namespace
|
||||
{
|
||||
void from_hex(std::string s, unsigned char* out)
|
||||
void test_vector(std::string seed, std::string pub, std::string sig_hex, std::string message)
|
||||
{
|
||||
aux::from_hex(s, reinterpret_cast<char*>(out));
|
||||
}
|
||||
std::array<char, 32> s;
|
||||
secret_key sk;
|
||||
public_key pk;
|
||||
signature sig;
|
||||
std::vector<char> msg(int(message.size()) / 2);
|
||||
|
||||
void test_vector(std::string seed, std::string pub, std::string signature, std::string message)
|
||||
{
|
||||
unsigned char s[32];
|
||||
unsigned char sk[64];
|
||||
unsigned char pk[32];
|
||||
unsigned char sig[64];
|
||||
int msg_size = int(message.size()) / 2;
|
||||
std::vector<unsigned char> msg(msg_size);
|
||||
|
||||
from_hex(seed, s);
|
||||
aux::from_hex(seed, s.data());
|
||||
ed25519_create_keypair(pk, sk, s);
|
||||
|
||||
TEST_EQUAL(aux::to_hex({reinterpret_cast<char const*>(pk), 32}), pub);
|
||||
TEST_EQUAL(aux::to_hex(pk.bytes), pub);
|
||||
|
||||
from_hex(message, msg.data());
|
||||
ed25519_sign(sig, msg.data(), msg_size, pk, sk);
|
||||
aux::from_hex(message, msg.data());
|
||||
ed25519_sign(sig, msg, pk, sk);
|
||||
|
||||
TEST_EQUAL(aux::to_hex({reinterpret_cast<char const*>(sig), 64}), signature);
|
||||
TEST_EQUAL(aux::to_hex(sig.bytes), sig_hex);
|
||||
|
||||
int r = ed25519_verify(sig, msg.data(), msg_size, pk);
|
||||
bool r = ed25519_verify(sig, msg, pk);
|
||||
|
||||
TEST_CHECK(r);
|
||||
}
|
||||
|
@ -172,6 +167,136 @@ TORRENT_TEST(ed25519_test_vec1)
|
|||
, "f8b21962447b0a8f2e4279de411bea128e0be44b6915e6cda88341a68a0d8183"
|
||||
"57db938eac73e0af6d31206b3948f8c48a447308"
|
||||
);
|
||||
|
||||
// TST: 224
|
||||
test_vector(
|
||||
"ae1d2c6b171be24c2e413d364dcda97fa476aaf9123d3366b0be03a142fe6e7d"
|
||||
, "d437f57542c681dd543487408ec7a44bd42a5fd545ce2f4c8297d67bb0b3aa7b"
|
||||
, "909008f3fcfff43988aee1314b15b1822caaa8dab120bd452af494e08335b44a"
|
||||
"94c313c4b145eadd5166eaac034e29b7e6ac7941d5961fc49d260e1c4820b00e"
|
||||
, "9e6c2fc76e30f17cd8b498845da44f22d55bec150c6130b411c6339d14b39969"
|
||||
"ab1033be687569a991a06f70b2a8a6931a777b0e4be6723cd75e5aa7532813ef"
|
||||
"50b3d37271640fa2fb287c0355257641ea935c851c0b6ac68be72c88dfc5856f"
|
||||
"b53543fb377b0dbf64808afcc4274aa456855ad28f61267a419bc72166b9ca73"
|
||||
"cd3bb79bf7dd259baa75911440974b68e8ba95a78cbbe1cb6ad807a33a1cce2f"
|
||||
"406ff7bcbd058b44a311b38ab4d4e61416c4a74d883d6a6a794abd9cf1c03902"
|
||||
"8bf1b20e3d4990aae86f32bf06cd8349a7a884cce0165e36a0640e987b9d51"
|
||||
);
|
||||
|
||||
// TST: 225
|
||||
test_vector(
|
||||
"0265a7944baccfebf417b87ae1e6df2ff2a544ffb58225a08e092be03f026097"
|
||||
, "63d327615ea0139be0740b618aff1acfa818d4b0c2cfeaf0da93cdd5245fb5a9"
|
||||
, "b6c445b7eddca5935c61708d44ea5906bd19cc54224eae3c8e46ce99f5cbbd34"
|
||||
"1f26623938f5fe04070b1b02e71fbb7c78a90c0dda66cb143fab02e6a0bae306"
|
||||
, "874ed712a2c41c26a2d9527c55233fde0a4ffb86af8e8a1dd0a820502c5a2693"
|
||||
"2bf87ee0de72a8874ef2eebf83384d443f7a5f46a1233b4fb514a24699818248"
|
||||
"94f325bf86aa0fe1217153d40f3556c43a8ea9269444e149fb70e9415ae0766c"
|
||||
"565d93d1d6368f9a23a0ad76f9a09dbf79634aa97178677734d04ef1a5b3f87c"
|
||||
"e1ee9fc5a9ac4e7a72c9d7d31ec89e28a845d2e1103c15d6410ce3c723b0cc22"
|
||||
"09f698aa9fa288bbbecfd9e5f89cdcb09d3c215feb47a58b71ea70e2abead67f"
|
||||
"1b08ea6f561fb93ef05232eedabfc1c7702ab039bc465cf57e207f1093fc8208"
|
||||
);
|
||||
}
|
||||
|
||||
TORRENT_TEST(create_seed)
|
||||
{
|
||||
std::array<char, 32> s1;
|
||||
std::array<char, 32> s2;
|
||||
s1.fill(0);
|
||||
s2.fill(0);
|
||||
|
||||
TEST_CHECK(s1 == s2);
|
||||
ed25519_create_seed(s1);
|
||||
ed25519_create_seed(s2);
|
||||
TEST_CHECK(s1 != s2); // what are the odds
|
||||
|
||||
int n1 = 0;
|
||||
int n2 = 0;
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
if (s1[i] != 0) n1++;
|
||||
if (s2[i] != 0) n2++;
|
||||
}
|
||||
TEST_CHECK(n1 > 0);
|
||||
TEST_CHECK(n2 > 0);
|
||||
}
|
||||
|
||||
TORRENT_TEST(add_scalar)
|
||||
{
|
||||
// client
|
||||
std::array<char, 32> s1;
|
||||
ed25519_create_seed(s1);
|
||||
|
||||
public_key pk1;
|
||||
secret_key sk1;
|
||||
ed25519_create_keypair(pk1, sk1, 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// test sign and verification
|
||||
std::string msg = "Hello world";
|
||||
signature sig;
|
||||
ed25519_sign(sig, msg, pk1, sk1);
|
||||
bool r = ed25519_verify(sig, msg, pk1);
|
||||
TEST_CHECK(r);
|
||||
}
|
||||
|
||||
TORRENT_TEST(key_exchange)
|
||||
{
|
||||
// user A
|
||||
std::array<char, 32> s1;
|
||||
ed25519_create_seed(s1);
|
||||
|
||||
public_key pk1;
|
||||
secret_key sk1;
|
||||
ed25519_create_keypair(pk1, sk1, s1);
|
||||
|
||||
// user A sends to user B the public key
|
||||
|
||||
// user B
|
||||
std::array<char, 32> s2;
|
||||
ed25519_create_seed(s2);
|
||||
|
||||
public_key pk2;
|
||||
secret_key sk2;
|
||||
ed25519_create_keypair(pk2, sk2, s2);
|
||||
|
||||
// user B performs the key exchange
|
||||
std::array<char, 32> secretB;
|
||||
ed25519_key_exchange(secretB, 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);
|
||||
|
||||
// now both users A and B must shared the same secret
|
||||
TEST_EQUAL(aux::to_hex(secretA), aux::to_hex(secretB));
|
||||
}
|
||||
|
||||
#else
|
||||
TORRENT_TEST(empty)
|
||||
{
|
||||
TEST_CHECK(true);
|
||||
}
|
||||
#endif // TORRENT_DISABLE_DHT
|
||||
|
|
|
@ -36,7 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/alert_types.hpp"
|
||||
#include "libtorrent/bencode.hpp" // for bencode()
|
||||
#include "libtorrent/kademlia/item.hpp" // for sign_mutable_item
|
||||
#include "libtorrent/ed25519.hpp"
|
||||
#include "libtorrent/kademlia/ed25519.hpp"
|
||||
#include "libtorrent/span.hpp"
|
||||
|
||||
#include <functional>
|
||||
|
@ -45,6 +45,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <cstdlib>
|
||||
|
||||
using namespace libtorrent;
|
||||
using namespace libtorrent::dht;
|
||||
using namespace std::placeholders;
|
||||
namespace lt = libtorrent;
|
||||
|
||||
|
@ -150,8 +151,8 @@ int dump_key(char *filename)
|
|||
return 1;
|
||||
}
|
||||
|
||||
unsigned char seed[32];
|
||||
int size = int(fread(seed, 1, 32, f));
|
||||
std::array<char, 32> seed;
|
||||
int size = int(fread(seed.data(), 1, 32, f));
|
||||
if (size != 32)
|
||||
{
|
||||
std::fprintf(stderr, "invalid key file.\n");
|
||||
|
@ -159,21 +160,20 @@ int dump_key(char *filename)
|
|||
}
|
||||
std::fclose(f);
|
||||
|
||||
std::array<char, 32> pk;
|
||||
std::array<char, 64> sk;
|
||||
ed25519_create_keypair((unsigned char*)pk.data()
|
||||
, (unsigned char*)sk.data(), seed);
|
||||
public_key pk;
|
||||
secret_key sk;
|
||||
ed25519_create_keypair(pk, sk, seed);
|
||||
|
||||
std::printf("public key: %s\nprivate key: %s\n"
|
||||
, to_hex(pk).c_str()
|
||||
, to_hex(sk).c_str());
|
||||
, to_hex(pk.bytes).c_str()
|
||||
, to_hex(sk.bytes).c_str());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int generate_key(char* filename)
|
||||
{
|
||||
unsigned char seed[32];
|
||||
std::array<char, 32> seed;
|
||||
ed25519_create_seed(seed);
|
||||
|
||||
FILE* f = std::fopen(filename, "wb+");
|
||||
|
@ -184,7 +184,7 @@ int generate_key(char* filename)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int size = int(std::fwrite(seed, 1, 32, f));
|
||||
int size = int(std::fwrite(seed.data(), 1, 32, f));
|
||||
if (size != 32)
|
||||
{
|
||||
std::fprintf(stderr, "failed to write key file.\n");
|
||||
|
@ -347,24 +347,23 @@ int main(int argc, char* argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
unsigned char seed[32];
|
||||
fread(seed, 1, 32, f);
|
||||
std::array<char, 32> seed;
|
||||
fread(seed.data(), 1, 32, f);
|
||||
std::fclose(f);
|
||||
|
||||
++argv;
|
||||
--argc;
|
||||
if (argc < 1) usage();
|
||||
|
||||
std::array<char, 32> public_key;
|
||||
std::array<char, 64> private_key;
|
||||
ed25519_create_keypair((unsigned char*)public_key.data()
|
||||
, (unsigned char*)private_key.data(), seed);
|
||||
public_key pk;
|
||||
secret_key sk;
|
||||
ed25519_create_keypair(pk, sk, seed);
|
||||
|
||||
bootstrap(s);
|
||||
s.dht_put_item(public_key, std::bind(&put_string, _1, _2, _3, _4
|
||||
, public_key, private_key, argv[0]));
|
||||
s.dht_put_item(pk.bytes, std::bind(&put_string, _1, _2, _3, _4
|
||||
, pk.bytes, sk.bytes, argv[0]));
|
||||
|
||||
std::printf("MPUT publick key: %s\n", to_hex(public_key).c_str());
|
||||
std::printf("MPUT public key: %s\n", to_hex(pk.bytes).c_str());
|
||||
|
||||
alert* a = wait_for_alert(s, dht_put_alert::alert_type);
|
||||
dht_put_alert* pa = alert_cast<dht_put_alert>(a);
|
||||
|
|
Loading…
Reference in New Issue