initial implementation of blinded sign -- not working yet

pull/1075/head
Thomas Winget 4 years ago committed by Jason Rhinelander
parent f7cd10a82e
commit a487982c49

@ -60,6 +60,9 @@ namespace llarp
/// ed25519 sign
virtual bool
sign(Signature &, const SecretKey &, const llarp_buffer_t &) = 0;
/// ed25519 sign (custom with derived keys)
virtual bool
sign(Signature &, const PrivateKey &, const llarp_buffer_t &) = 0;
/// ed25519 verify
virtual bool
verify(const PubKey &, const llarp_buffer_t &, const Signature &) = 0;

@ -7,9 +7,12 @@
#include <sodium/crypto_stream_xchacha20.h>
#include <sodium/crypto_core_ed25519.h>
#include <sodium/crypto_core_ristretto255.h>
#include <sodium/randombytes.h>
#include <sodium/utils.h>
#include <util/mem.hpp>
#include <util/endian.hpp>
#include <cassert>
#include <cstring>
extern "C"
{
@ -175,6 +178,52 @@ namespace llarp
!= -1;
}
bool
CryptoLibSodium::sign(Signature &sig, const PrivateKey &secret,
const llarp_buffer_t &buf)
{
PubKey pubkey;
secret.toPublic(pubkey);
crypto_hash_sha512_state hs;
unsigned char nonce[64];
unsigned char hram[64];
unsigned char mulres[32];
unsigned char r_hash_input[32];
randombytes_buf(r_hash_input, 32);
// r = H(H(k) || M) where here H(k) is random bytes
crypto_hash_sha512_init(&hs);
crypto_hash_sha512_update(&hs, r_hash_input, 32);
crypto_hash_sha512_update(&hs, buf.base, buf.sz);
crypto_hash_sha512_final(&hs, nonce);
crypto_core_ed25519_scalar_reduce(nonce, nonce);
// copy pubkey into sig to make (for now) sig = (R || A)
memmove(sig.Lo(), pubkey.data(), 32);
// R = r * B
crypto_scalarmult_ed25519_base(sig.Hi(), nonce);
// hram = H(R || A || M)
crypto_hash_sha512_init(&hs);
crypto_hash_sha512_update(&hs, sig.data(), 64);
crypto_hash_sha512_update(&hs, buf.base, buf.sz);
crypto_hash_sha512_final(&hs, hram);
// S = r + H(R || A || M) * s, so sig = (R || S)
crypto_core_ed25519_scalar_reduce(hram, hram);
crypto_core_ed25519_scalar_mul(mulres, hram, secret.data());
crypto_core_ed25519_scalar_add(sig.Lo(), mulres, nonce);
sodium_memzero(r_hash_input, sizeof r_hash_input);
sodium_memzero(nonce, sizeof nonce);
return true;
}
bool
CryptoLibSodium::verify(const PubKey &pub, const llarp_buffer_t &buf,
const Signature &sig)

@ -48,6 +48,9 @@ namespace llarp
/// ed25519 sign
bool
sign(Signature &, const SecretKey &, const llarp_buffer_t &) override;
/// ed25519 sign (custom with derived keys)
bool
sign(Signature &, const PrivateKey &, const llarp_buffer_t &) override;
/// ed25519 verify
bool
verify(const PubKey &, const llarp_buffer_t &,
@ -92,6 +95,7 @@ namespace llarp
bool
check_identity_privkey(const SecretKey &) override;
};
} // namespace sodium

@ -113,6 +113,15 @@ namespace llarp
return true;
}
bool
sign(Signature &sig, const PrivateKey &key, const llarp_buffer_t &) override
{
static_assert(Signature::SIZE == PrivateKey::SIZE * 2, "");
std::copy(key.begin(), key.end(), sig.begin());
std::copy(key.begin(), key.end(), sig.begin() + 32);
return true;
}
bool
verify(const PubKey &, const llarp_buffer_t &, const Signature &) override
{

@ -48,9 +48,9 @@ namespace llarp
MOCK_METHOD4(derive_subkey_private,
bool(PrivateKey &, const SecretKey &, uint64_t, const AlignedBuffer<32> *));
MOCK_METHOD3(sign,
bool(Signature &, const SecretKey &,
const llarp_buffer_t &));
MOCK_METHOD(bool, sign, (Signature &, const SecretKey &, const llarp_buffer_t &));
MOCK_METHOD(bool, sign, (Signature &, const PrivateKey &, const llarp_buffer_t &));
MOCK_METHOD3(verify,
bool(const PubKey &, const llarp_buffer_t &,

@ -38,7 +38,8 @@ TEST_F(HiddenServiceTest, TestGenerateIntroSet)
I.I.emplace_back(std::move(intro));
}
EXPECT_CALL(m_crypto, sign(I.Z, _, _)).WillOnce(Return(true));
using ::testing::Matcher;
EXPECT_CALL(m_crypto, sign(I.Z, Matcher<const SecretKey &>(_), _)).WillOnce(Return(true));
EXPECT_CALL(m_crypto, verify(_, _, I.Z)).WillOnce(Return(true));
EXPECT_CALL(m_crypto, xchacha20(_, _, _)).WillOnce(Return(true));
const auto maybe = ident.EncryptAndSignIntroSet(I, now);
@ -222,6 +223,35 @@ TEST_F(RealCryptographyTest, TestGenerateDeriveKey)
ASSERT_EQ(Aprime, Aprime_alt);
}
TEST_F(RealCryptographyTest, TestSignUsingDerivedKey)
{
auto crypto = CryptoManager::instance();
SecretKey root_key;
crypto->identity_keygen(root_key);
PrivateKey root_privkey;
root_key.toPrivate(root_privkey);
PrivateKey a;
PubKey A;
root_key.toPrivate(a);
a.toPublic(A);
PrivateKey aprime; // a'
crypto->derive_subkey_private(aprime, root_key, 1);
PubKey Aprime; // A'
crypto->derive_subkey(Aprime, A, 1);
std::string dummystr = "Jeff loves one-letter variable names.";
llarp_buffer_t buf(dummystr.data(), dummystr.size());
Signature sig;
ASSERT_TRUE(crypto->sign(sig, aprime, buf));
ASSERT_TRUE(crypto->verify(Aprime, buf, sig));
}
TEST_F(RealCryptographyTest, TestEncryptAndSignIntroSet)
{
service::Identity ident;

Loading…
Cancel
Save