Skip to content

Commit

Permalink
Refactor keystore (#1584)
Browse files Browse the repository at this point in the history
Signed-off-by: turuslan <turuslan.devbox@gmail.com>
  • Loading branch information
turuslan authored May 2, 2023
1 parent 1f75bc0 commit 2d2f2e1
Show file tree
Hide file tree
Showing 143 changed files with 831 additions and 804 deletions.
2 changes: 1 addition & 1 deletion core/api/service/author/impl/author_api_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ namespace kagome::api {

outcome::result<bool> AuthorApiImpl::hasKey(
const gsl::span<const uint8_t> &public_key, crypto::KeyTypeId key_type) {
auto res = key_store_->searchForSeed(key_type, public_key);
auto res = key_store_->searchForPhrase(key_type, public_key);
if (not res) {
return res.error();
} else {
Expand Down
2 changes: 1 addition & 1 deletion core/application/app_configuration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ namespace kagome::application {
/**
* @return the secret key to use for libp2p networking
*/
virtual const std::optional<crypto::Ed25519PrivateKey> &nodeKey() const = 0;
virtual const std::optional<crypto::Ed25519Seed> &nodeKey() const = 0;

/**
* @return the path to key used for libp2p networking
Expand Down
27 changes: 10 additions & 17 deletions core/application/impl/app_configuration_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
#include "chain_spec_impl.hpp"
#include "common/hexutil.hpp"
#include "common/uri.hpp"
#include "crypto/crypto_store/dev_mnemonic_phrase.hpp"
#include "filesystem/directories.hpp"
#include "utils/read_file.hpp"

namespace {
namespace fs = kagome::filesystem;
Expand Down Expand Up @@ -185,16 +185,15 @@ namespace {
}

auto &devAccounts() {
static auto &dev = kagome::crypto::DevMnemonicPhrase::get();
using Account =
std::tuple<const char *, std::string_view, std::string_view>;
static const std::array<Account, 6> accounts{
Account{"alice", "Alice", dev.alice},
Account{"bob", "Bob", dev.bob},
Account{"charlie", "Charlie", dev.charlie},
Account{"dave", "Dave", dev.dave},
Account{"eve", "Eve", dev.eve},
Account{"ferdie", "Ferdie", dev.ferdie},
Account{"alice", "Alice", "//Alice"},
Account{"bob", "Bob", "//Bob"},
Account{"charlie", "Charlie", "//Charlie"},
Account{"dave", "Dave", "//Dave"},
Account{"eve", "Eve", "//Eve"},
Account{"ferdie", "Ferdie", "//Ferdie"},
};
return accounts;
}
Expand Down Expand Up @@ -251,7 +250,7 @@ namespace kagome::application {

boost::filesystem::path AppConfigurationImpl::chainPath(
std::string chain_id) const {
return base_path_ / chain_id;
return base_path_ / "chains" / chain_id;
}

fs::path AppConfigurationImpl::databasePath(std::string chain_id) const {
Expand Down Expand Up @@ -944,13 +943,7 @@ namespace kagome::application {
find_argument<std::string>(
vm, "node-wss-pem", [&](const std::string &path) {
std::string pem;
std::ifstream file{path, std::ios::ate};
if (file.good()) {
pem.resize(file.tellg());
file.seekg(0);
file.read(pem.data(), pem.size());
}
if (not file.good()) {
if (not readFile(pem, path)) {
SL_ERROR(logger_, "--node-wss-pem {}: read error", path);
return;
}
Expand Down Expand Up @@ -1041,7 +1034,7 @@ namespace kagome::application {
find_argument<std::string>(
vm, "node-key", [&](const std::string &val) { node_key.emplace(val); });
if (node_key.has_value()) {
auto key_res = crypto::Ed25519PrivateKey::fromHex(node_key.value());
auto key_res = crypto::Ed25519Seed::fromHex(node_key.value());
if (not key_res.has_value()) {
auto err_msg = fmt::format(
"Node key '{}' is invalid: {}", node_key.value(), key_res.error());
Expand Down
4 changes: 2 additions & 2 deletions core/application/impl/app_configuration_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ namespace kagome::application {
boost::filesystem::path databasePath(std::string chain_id) const override;
boost::filesystem::path keystorePath(std::string chain_id) const override;

const std::optional<crypto::Ed25519PrivateKey> &nodeKey() const override {
const std::optional<crypto::Ed25519Seed> &nodeKey() const override {
return node_key_;
}

Expand Down Expand Up @@ -293,7 +293,7 @@ namespace kagome::application {
log::Logger logger_;

network::Roles roles_;
std::optional<crypto::Ed25519PrivateKey> node_key_;
std::optional<crypto::Ed25519Seed> node_key_;
std::optional<std::string> node_key_file_;
bool save_node_key_;
std::vector<libp2p::multi::Multiaddress> listen_addresses_;
Expand Down
2 changes: 1 addition & 1 deletion core/assets/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ if(EMBEDDINGS)
)
target_sources(assets PRIVATE ${OUTPUT})

set(SOURCE ${PROJECT_SOURCE_DIR}/examples/first_kagome_chain/base_path/dev/keystore)
set(SOURCE ${PROJECT_SOURCE_DIR}/examples/first_kagome_chain/base_path/chains/dev/keystore)
if(NOT IS_DIRECTORY ${SOURCE})
fatal_error("Not found resource for embedded assets: ${SOURCE}")
endif()
Expand Down
5 changes: 4 additions & 1 deletion core/crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ add_library(ed25519_types
)
target_link_libraries(ed25519_types
blob
scale::scale
schnorrkel_crust::schnorrkel_crust
)
kagome_install(ed25519_types)
Expand Down Expand Up @@ -59,8 +60,9 @@ add_library(ecdsa_provider
ecdsa_types.cpp
)
target_link_libraries(ecdsa_provider
hasher
logger
p2p::p2p_ecdsa_provider
secp256k1_provider
)
kagome_install(ecdsa_provider)

Expand All @@ -69,6 +71,7 @@ add_library(ed25519_provider
)
target_link_libraries(ed25519_provider
ed25519_types
hasher
logger
schnorrkel_crust::schnorrkel_crust
)
Expand Down
2 changes: 2 additions & 0 deletions core/crypto/bip39/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ target_link_libraries(bip39_provider
PUBLIC OpenSSL::SSL
OpenSSL::Crypto
blob
hasher
logger
pbkdf2_provider
scale::scale
sha
)
kagome_install(bip39_provider)
2 changes: 1 addition & 1 deletion core/crypto/bip39/bip39_provider.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ namespace kagome::crypto {
virtual outcome::result<bip39::Bip39Seed> makeSeed(
gsl::span<const uint8_t> entropy, std::string_view password) const = 0;

virtual outcome::result<bip39::Bip39Seed> generateSeed(
virtual outcome::result<bip39::Bip39SeedAndJunctions> generateSeed(
std::string_view mnemonic_phrase) const = 0;
};

Expand Down
17 changes: 17 additions & 0 deletions core/crypto/bip39/bip39_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#ifndef KAGOME_BIP39_TYPES_HPP
#define KAGOME_BIP39_TYPES_HPP

#include "common/blob.hpp"
#include "common/buffer.hpp"

namespace kagome::crypto::bip39 {
Expand All @@ -14,6 +15,22 @@ namespace kagome::crypto::bip39 {
} // namespace constants

using Bip39Seed = common::Buffer;

struct RawJunction {
bool hard;
common::Hash256 cc;
};

struct Bip39SeedAndJunctions {
common::Buffer seed;
std::vector<RawJunction> junctions;

template <typename T>
outcome::result<T> as() const {
return T::fromSpan(
gsl::make_span(seed).first(std::min(seed.size(), T::size())));
}
};
} // namespace kagome::crypto::bip39

#endif // KAGOME_BIP39_TYPES_HPP
41 changes: 36 additions & 5 deletions core/crypto/bip39/impl/bip39_provider_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,33 @@

#include "crypto/bip39/impl/bip39_provider_impl.hpp"

#include <boost/algorithm/string/predicate.hpp>

#include "crypto/bip39/entropy_accumulator.hpp"
#include "crypto/bip39/mnemonic.hpp"

namespace kagome::crypto {

static const std::vector<std::string> kDevWords{
"bottom",
"drive",
"obey",
"lake",
"curtain",
"smoke",
"basket",
"hold",
"race",
"lonely",
"fit",
"walk",
};

Bip39ProviderImpl::Bip39ProviderImpl(
std::shared_ptr<Pbkdf2Provider> pbkdf2_provider)
: pbkdf2_provider_(std::move(pbkdf2_provider)),
std::shared_ptr<Pbkdf2Provider> pbkdf2_provider,
std::shared_ptr<Hasher> hasher)
: pbkdf2_provider_{std::move(pbkdf2_provider)},
hasher_{std::move(hasher)},
logger_{log::createLogger("Bip39Provider", "bip39")} {
dictionary_.initialize();
}
Expand Down Expand Up @@ -53,10 +72,22 @@ namespace kagome::crypto {
entropy, salt, iterations_count, bip39::constants::BIP39_SEED_LEN_512);
}

outcome::result<bip39::Bip39Seed> Bip39ProviderImpl::generateSeed(
outcome::result<bip39::Bip39SeedAndJunctions> Bip39ProviderImpl::generateSeed(
std::string_view mnemonic_phrase) const {
OUTCOME_TRY(mnemonic, bip39::Mnemonic::parse(mnemonic_phrase));
OUTCOME_TRY(entropy, calculateEntropy(mnemonic.words));
return makeSeed(entropy, mnemonic.password);
bip39::Bip39SeedAndJunctions result;
if (auto words = mnemonic.words()) {
if (words->empty()) {
words = &kDevWords;
}
OUTCOME_TRY(entropy, calculateEntropy(*words));
BOOST_OUTCOME_TRY(result.seed, makeSeed(entropy, mnemonic.password));
} else {
result.seed = std::move(boost::get<common::Buffer>(mnemonic.seed));
}
for (auto &junction : mnemonic.junctions) {
result.junctions.emplace_back(junction.raw(*hasher_));
}
return result;
}
} // namespace kagome::crypto
7 changes: 5 additions & 2 deletions core/crypto/bip39/impl/bip39_provider_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "crypto/bip39/bip39_provider.hpp"
#include "crypto/bip39/dictionary.hpp"

#include "crypto/hasher.hpp"
#include "crypto/pbkdf2/pbkdf2_provider.hpp"
#include "log/logger.hpp"

Expand All @@ -17,7 +18,8 @@ namespace kagome::crypto {
public:
~Bip39ProviderImpl() override = default;

explicit Bip39ProviderImpl(std::shared_ptr<Pbkdf2Provider> pbkdf2_provider);
explicit Bip39ProviderImpl(std::shared_ptr<Pbkdf2Provider> pbkdf2_provider,
std::shared_ptr<Hasher> hasher);

outcome::result<std::vector<uint8_t>> calculateEntropy(
const std::vector<std::string> &word_list) const override;
Expand All @@ -26,11 +28,12 @@ namespace kagome::crypto {
gsl::span<const uint8_t> entropy,
std::string_view password) const override;

outcome::result<bip39::Bip39Seed> generateSeed(
outcome::result<bip39::Bip39SeedAndJunctions> generateSeed(
std::string_view mnemonic_phrase) const override;

private:
std::shared_ptr<Pbkdf2Provider> pbkdf2_provider_;
std::shared_ptr<Hasher> hasher_;
bip39::Dictionary dictionary_;
log::Logger logger_;
};
Expand Down
74 changes: 59 additions & 15 deletions core/crypto/bip39/mnemonic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@

#include "crypto/bip39/mnemonic.hpp"

#include <charconv>
#include <codecvt>
#include <locale>

#include <boost/algorithm/string.hpp>

#include "common/visitor.hpp"
#include "crypto/bip39/bip39_types.hpp"
#include "crypto/hasher.hpp"
#include "log/logger.hpp"

namespace kagome::crypto::bip39 {
Expand All @@ -31,35 +35,75 @@ namespace kagome::crypto::bip39 {
}
} // namespace

RawJunction Junction::raw(const crypto::Hasher &hasher) const {
auto raw = visit_in_place(
index, [](const auto &x) { return scale::encode(x).value(); });
common::Hash256 result;
if (raw.size() > result.size()) {
result = hasher.blake2b_256(raw);
} else {
std::copy(raw.begin(), raw.end(), result.begin());
}
return RawJunction{hard, result};
}

outcome::result<Mnemonic> Mnemonic::parse(std::string_view phrase) {
if (phrase.empty() || !isValidUtf8(std::string(phrase))) {
if (!isValidUtf8(std::string(phrase))) {
return bip39::MnemonicError::INVALID_MNEMONIC;
}

Mnemonic mnemonic;

auto password_pos = phrase.find("///");
std::string_view mnemonic_list;
std::string_view password;
std::string_view seed;
if (password_pos != std::string_view::npos) {
// need to normalize password utf8 nfkd
password = phrase.substr(password_pos + 3);
mnemonic_list = phrase.substr(0, password_pos);
mnemonic.password = phrase.substr(password_pos + 3);
seed = phrase.substr(0, password_pos);
} else {
mnemonic_list = phrase;
seed = phrase;
}

if (mnemonic_list.find("/") != std::string_view::npos) {
log::createLogger("Mnemonic", "bip39")
->error("junctions are not supported yet");
return bip39::MnemonicError::INVALID_MNEMONIC;
auto path = seed;
auto slash_pos = path.find('/');
if (slash_pos != std::string_view::npos) {
seed = seed.substr(0, slash_pos);
path.remove_prefix(slash_pos);
while (not path.empty()) {
path.remove_prefix(1);
auto hard = not path.empty() and path[0] == '/';
if (hard) {
path.remove_prefix(1);
}
slash_pos = path.find('/');
if (slash_pos == std::string_view::npos) {
slash_pos = path.size();
}
auto index = path.substr(0, slash_pos);
auto end = index.data() + index.size();
uint64_t num;
auto parse = std::from_chars(index.data(), end, num);
if (parse.ec == std::errc{} and parse.ptr == end) {
mnemonic.junctions.emplace_back(Junction{hard, num});
} else {
mnemonic.junctions.emplace_back(Junction{hard, std::string{index}});
}
path.remove_prefix(slash_pos);
}
}

// split word list into separate words
std::vector<std::string> word_list;
boost::split(word_list, mnemonic_list, boost::algorithm::is_space());
if (boost::starts_with(seed, "0x")) {
OUTCOME_TRY(bytes, common::unhexWith0x(seed));
mnemonic.seed = common::Buffer{std::move(bytes)};
} else {
Words words;
if (not seed.empty()) {
boost::split(words, seed, boost::algorithm::is_space());
}
mnemonic.seed = std::move(words);
}

Mnemonic mnemonic{std::move(word_list), std::string(password)};
return mnemonic;
//
}
} // namespace kagome::crypto::bip39

Expand Down
Loading

0 comments on commit 2d2f2e1

Please sign in to comment.