From 0f13591802aebf80ea7e728dfe88fd3fb0714413 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 28 Jan 2020 16:55:36 -0500 Subject: [PATCH] does not work --- daemon/CMakeLists.txt | 4 +- llarp/crypto/crypto_libsodium.cpp | 74 +++++++++++++++----- llarp/crypto/types.cpp | 6 +- llarp/service/identity.cpp | 7 +- llarp/service/intro_set.cpp | 11 +-- test/service/test_llarp_service_identity.cpp | 62 ++++++++++++++++ 6 files changed, 136 insertions(+), 28 deletions(-) diff --git a/daemon/CMakeLists.txt b/daemon/CMakeLists.txt index 329e39d7a..051ada2e1 100644 --- a/daemon/CMakeLists.txt +++ b/daemon/CMakeLists.txt @@ -42,8 +42,8 @@ else() target_link_directories(${EXE} PRIVATE /usr/local/lib) target_link_directories(${CTL} PRIVATE /usr/local/lib) endif() - target_link_libraries(${EXE} PUBLIC ${EXE_LIBS} ${LIBS}) - target_link_libraries(${CTL} PUBLIC ${EXE_LIBS} ${LIBS}) + target_link_libraries(${EXE} PUBLIC ${EXE_LIBS} ${LIBS} ${CRYPTOGRAPHY_LIB}) + target_link_libraries(${CTL} PUBLIC ${EXE_LIBS} ${LIBS} ${CRYPTOGRAPHY_LIB}) if(CURL_FOUND) target_include_directories(${CTL} PRIVATE ${CURL_INCLUDE_DIRS}) diff --git a/llarp/crypto/crypto_libsodium.cpp b/llarp/crypto/crypto_libsodium.cpp index a244549f9..2b163acc0 100644 --- a/llarp/crypto/crypto_libsodium.cpp +++ b/llarp/crypto/crypto_libsodium.cpp @@ -2,8 +2,11 @@ #include #include #include +#include +#include #include #include +#include #include #include #include @@ -181,6 +184,33 @@ namespace llarp != -1; } + /// clamp a 32 byte ec point + static void + clamp_ed25519(byte_t *out) + { + out[0] &= 248; + out[31] &= 127; + out[31] |= 64; + } + + template < typename K > + static K + clamp(const K &p) + { + K out = p; + clamp_ed25519(out); + return out; + } + + template < typename K > + static bool + is_clamped(const K &key) + { + K other(key); + clamp_ed25519(other.data()); + return other == key; + } + template < typename K > static bool make_scalar(byte_t *out, const K &k, uint64_t i) @@ -194,48 +224,58 @@ namespace llarp if(not hash(h.data(), llarp_buffer_t(buf))) return false; // return make_point(n) - return crypto_core_ed25519_from_hash(out, h.data()) != -1; + return crypto_core_ed25519_from_uniform(out, h.data()) != -1; } + static AlignedBuffer< 32 > zero; + bool - CryptoLibSodium::derive_subkey(PubKey &out_k, const PubKey &in_k, + CryptoLibSodium::derive_subkey(PubKey &out_key, const PubKey &root_key, uint64_t key_n) { // scalar p AlignedBuffer< 32 > p; // p = H( i || in_k ) - if(not make_scalar(p.data(), in_k, key_n)) + if(not make_scalar(p.data(), root_key, key_n)) return false; - // out_k = in_k * p % N - crypto_core_ed25519_scalar_mul(out_k.data(), in_k.data(), p.data()); + crypto_core_ed25519_scalar_mul(out_key.data(), root_key.data(), p.data()); + LogInfo("derive_subkey() scalar = ", p, " root_key = ", root_key, + " derived_key = ", out_key); return true; } bool - CryptoLibSodium::derive_subkey_secret(SecretKey &out_k, - const SecretKey &in_k, uint64_t key_n) + CryptoLibSodium::derive_subkey_secret(SecretKey &out_key, + const SecretKey &in_key, + uint64_t key_n) { + const PubKey root_key = in_key.toPublic(); // scalar p AlignedBuffer< 32 > p; - // p = H( i || in_k.pub) - if(not make_scalar(p.data(), in_k.toPublic(), key_n)) + // p = H( i || in_key.pub) + if(not make_scalar(p.data(), root_key, key_n)) + { + LogError("cannot make scalar"); + return false; + } + // a * p * basepoint + crypto_core_ed25519_scalar_mul(out_key.data(), in_key.data(), p.data()); + if(not out_key.Recalculate()) return false; - // out_k = in_n * p % N - crypto_core_ed25519_scalar_mul(out_k.data(), in_k.data(), p.data()); - // recalculate out_K public component - return out_k.Recalculate(); + LogInfo("derive_subkey_secret() scalar = ", p, " root_key = ", root_key, + " derived_key = ", out_key.toPublic(), + " full_derived_key = ", out_key.ToHex()); + return true; } bool CryptoLibSodium::seed_to_secretkey(llarp::SecretKey &secret, const llarp::IdentitySecret &seed) { - PubKey pk; - return crypto_sign_ed25519_seed_keypair(pk.data(), secret.data(), + return crypto_sign_ed25519_seed_keypair(secret.data() + 32, secret.data(), seed.data()) != -1; } - void CryptoLibSodium::randomize(const llarp_buffer_t &buff) { @@ -258,6 +298,8 @@ namespace llarp assert(pk == sk_pk); (void)result; (void)sk_pk; + + // encryption_keygen(keys); } bool diff --git a/llarp/crypto/types.cpp b/llarp/crypto/types.cpp index 0dae7f5da..a5d23949f 100644 --- a/llarp/crypto/types.cpp +++ b/llarp/crypto/types.cpp @@ -9,6 +9,7 @@ #include #include +#include namespace llarp { @@ -57,10 +58,7 @@ namespace llarp bool SecretKey::Recalculate() { - AlignedBuffer< 32 > seed; - if(crypto_sign_ed25519_sk_to_seed(seed.data(), data()) == -1) - return false; - return crypto_sign_seed_keypair(data() + 32, data(), seed.data()) != -1; + return crypto_scalarmult_ed25519_base(data() + 32, data()) != -1; } bool diff --git a/llarp/service/identity.cpp b/llarp/service/identity.cpp index 9eba9c9a5..40588f201 100644 --- a/llarp/service/identity.cpp +++ b/llarp/service/identity.cpp @@ -62,7 +62,10 @@ namespace llarp crypto_sign_ed25519_sk_to_curve25519(enckey.data(), signkey.data()); pub.Update(seckey_topublic(signkey)); crypto->pqe_keygen(pq); - crypto->derive_subkey_secret(derivedSignKey, signkey, 1); + if(not crypto->derive_subkey_secret(derivedSignKey, signkey, 1)) + { + LogError("failed to generate derived key"); + } } bool @@ -176,7 +179,7 @@ namespace llarp buf.cur = buf.base; const SharedSecret k(i.A.Addr()); CryptoManager::instance()->xchacha20(buf, k, encrypted.nounce); - encrypted.introsetPayload.reserve(buf.sz); + encrypted.introsetPayload.resize(buf.sz); std::copy_n(buf.base, buf.sz, encrypted.introsetPayload.data()); if(not encrypted.Sign(derivedSignKey)) return {}; diff --git a/llarp/service/intro_set.cpp b/llarp/service/intro_set.cpp index fa3f41c0c..c00283dba 100644 --- a/llarp/service/intro_set.cpp +++ b/llarp/service/intro_set.cpp @@ -78,7 +78,8 @@ namespace llarp printer.printAttribute("d", derivedSigningKey); printer.printAttribute("n", nounce); printer.printAttribute("s", signedAt); - printer.printAttribute("x", introsetPayload); + printer.printAttribute( + "x", "[" + std::to_string(introsetPayload.size()) + " bytes]"); printer.printAttribute("z", sig); return out; } @@ -114,14 +115,15 @@ namespace llarp return false; buf.sz = buf.cur - buf.base; buf.cur = buf.base; - return CryptoManager::instance()->sign(sig, k, buf); + if(not CryptoManager::instance()->sign(sig, k, buf)) + return false; + LogInfo("signed encrypted introset: ", *this); + return true; } bool EncryptedIntroSet::Verify(llarp_time_t now) const { - if(signedAt > now) - return false; if(IsExpired(now)) return false; std::array< byte_t, MAX_INTROSET_SIZE + 128 > tmp; @@ -130,6 +132,7 @@ namespace llarp copy.sig.Zero(); if(not copy.BEncode(&buf)) return false; + LogInfo("verify encrypted introset: ", copy, " sig = ", sig); buf.sz = buf.cur - buf.base; buf.cur = buf.base; return CryptoManager::instance()->verify(derivedSigningKey, buf, sig); diff --git a/test/service/test_llarp_service_identity.cpp b/test/service/test_llarp_service_identity.cpp index 313232e1c..79b89d587 100644 --- a/test/service/test_llarp_service_identity.cpp +++ b/test/service/test_llarp_service_identity.cpp @@ -39,6 +39,7 @@ TEST_F(HiddenServiceTest, TestGenerateIntroSet) EXPECT_CALL(m_crypto, sign(I.Z, _, _)).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); ASSERT_TRUE(maybe.has_value()); ASSERT_TRUE(maybe->Verify(now)); @@ -75,6 +76,9 @@ TEST_F(ServiceIdentityTest, EnsureKeys) const SecretKey k; + EXPECT_CALL(m_crypto, derive_subkey_secret(_, _, _)) + .WillRepeatedly(Return(true)); + EXPECT_CALL(m_crypto, identity_keygen(_)) .WillOnce(WithArg< 0 >(FillArg< SecretKey >(0x02))); @@ -121,3 +125,61 @@ TEST_F(ServiceIdentityTest, EnsureKeysBrokenFile) service::Identity identity; ASSERT_FALSE(identity.EnsureKeys(p.string(), false)); } + +struct RealCryptographyTest : public ::testing::Test +{ + std::unique_ptr< CryptoManager > _manager; + + void + SetUp() + { + _manager = std::make_unique< CryptoManager >(new sodium::CryptoLibSodium()); + } + + void + TearDown() + { + _manager.reset(); + } +}; + +TEST_F(RealCryptographyTest, TestGenerateDeriveKey) +{ + SecretKey root_key; + SecretKey sub_key; + PubKey sub_pubkey; + auto crypto = CryptoManager::instance(); + crypto->identity_keygen(root_key); + ASSERT_TRUE(crypto->derive_subkey_secret(sub_key, root_key, 1)); + ASSERT_TRUE(crypto->derive_subkey(sub_pubkey, root_key.toPublic(), 1)); + ASSERT_EQ(sub_key.toPublic(), sub_pubkey); +} + +TEST_F(RealCryptographyTest, TestEncryptAndSignIntroSet) +{ + service::Identity ident; + ident.RegenerateKeys(); + service::Address addr; + ASSERT_TRUE(ident.pub.CalculateAddress(addr.as_array())); + service::IntroSet I; + auto now = time_now_ms(); + I.T = now; + while(I.I.size() < 10) + { + service::Introduction intro; + intro.expiresAt = now + (path::default_lifetime / 2); + intro.router.Randomize(); + intro.pathID.Randomize(); + I.I.emplace_back(std::move(intro)); + } + + const auto maybe = ident.EncryptAndSignIntroSet(I, now); + ASSERT_TRUE(maybe.has_value()); + llarp::LogInfo("introset=", maybe.value()); + ASSERT_TRUE(maybe->Verify(now)); + PubKey blind_key; + const PubKey root_key(addr.as_array()); + auto crypto = CryptoManager::instance(); + ASSERT_TRUE(crypto->derive_subkey(blind_key, root_key, 1)); + ASSERT_EQ(blind_key, root_key); +}