diff --git a/Makefile b/Makefile index 1d3a06e0ec..7a2e636b79 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CONCORD_BFT_DOCKER_REPO?=concordbft/ CONCORD_BFT_DOCKER_IMAGE?=concord-bft -CONCORD_BFT_DOCKER_IMAGE_VERSION?=0.42 +CONCORD_BFT_DOCKER_IMAGE_VERSION?=0.45 CONCORD_BFT_DOCKER_CONTAINER?=concord-bft CONCORD_BFT_DOCKERFILE?=Dockerfile diff --git a/bftengine/include/bcstatetransfer/SimpleBCStateTransfer.hpp b/bftengine/include/bcstatetransfer/SimpleBCStateTransfer.hpp index 0ff95d511d..db9c718cb6 100644 --- a/bftengine/include/bcstatetransfer/SimpleBCStateTransfer.hpp +++ b/bftengine/include/bcstatetransfer/SimpleBCStateTransfer.hpp @@ -23,9 +23,6 @@ #include "kvstream.h" #include "digest.hpp" -using concord::util::digest::Digest; -using concord::util::digest::BlockDigest; - namespace concord { namespace storage { class IDBClient; @@ -48,7 +45,7 @@ namespace bcst { // blocks. // Blocks are numbered. The first block should be block number 1. -// represnts a digest +// represents a digest #pragma pack(push, 1) struct StateTransferDigest { char content[DIGEST_SIZE]; @@ -61,7 +58,9 @@ void computeBlockDigest(const uint64_t blockId, const uint32_t blockSize, StateTransferDigest *outDigest); -BlockDigest computeBlockDigest(const uint64_t blockId, const char *block, const uint32_t blockSize); +concord::util::digest::BlockDigest computeBlockDigest(const uint64_t blockId, + const char *block, + const uint32_t blockSize); // This interface should be implemented by the application/storage layer. // It is used by the state transfer module. diff --git a/bftengine/include/bftengine/IKeyExchanger.hpp b/bftengine/include/bftengine/IKeyExchanger.hpp index 2d2d1884e0..bd8c5d254b 100644 --- a/bftengine/include/bftengine/IKeyExchanger.hpp +++ b/bftengine/include/bftengine/IKeyExchanger.hpp @@ -10,7 +10,7 @@ // file. #pragma once -#include "crypto_utils.hpp" +#include "crypto.hpp" #include #include @@ -31,5 +31,5 @@ class IMultiSigKeyGenerator { class IClientPublicKeyStore { public: virtual ~IClientPublicKeyStore() = default; - virtual void setClientPublicKey(uint16_t clientId, const std::string& key, concord::util::crypto::KeyFormat) = 0; + virtual void setClientPublicKey(uint16_t clientId, const std::string& key, concord::crypto::KeyFormat) = 0; }; diff --git a/bftengine/include/bftengine/KeyExchangeManager.hpp b/bftengine/include/bftengine/KeyExchangeManager.hpp index b7bc72bcf2..f7235e88dc 100644 --- a/bftengine/include/bftengine/KeyExchangeManager.hpp +++ b/bftengine/include/bftengine/KeyExchangeManager.hpp @@ -18,7 +18,7 @@ #include "Metrics.hpp" #include "secrets_manager_impl.h" #include "SysConsts.hpp" -#include "crypto_utils.hpp" +#include "crypto.hpp" #include namespace bftEngine::impl { @@ -64,10 +64,10 @@ class KeyExchangeManager { void sendInitialClientsKeys(const std::string&); void onPublishClientsKeys(const std::string& keys, std::optional bootstrap_keys); // called on a new client key - void onClientPublicKeyExchange(const std::string& key, concord::util::crypto::KeyFormat, NodeIdType clientId); + void onClientPublicKeyExchange(const std::string& key, concord::crypto::KeyFormat, NodeIdType clientId); // called when client keys are loaded void loadClientPublicKey(const std::string& key, - concord::util::crypto::KeyFormat, + concord::crypto::KeyFormat, NodeIdType clientId, bool saveToReservedPages); ///////// end - Clients public keys interface/////////////// diff --git a/bftengine/include/bftengine/ReplicaConfig.hpp b/bftengine/include/bftengine/ReplicaConfig.hpp index 2d6177b08c..7bea6c7592 100644 --- a/bftengine/include/bftengine/ReplicaConfig.hpp +++ b/bftengine/include/bftengine/ReplicaConfig.hpp @@ -20,8 +20,7 @@ #include #include "string.hpp" #include "kvstream.h" - -#include "Serializable.h" +#include "crypto/factory.hpp" namespace bftEngine { @@ -281,6 +280,16 @@ class ReplicaConfig : public concord::serialize::SerializableFactorygetMySigLength()); - bftEngine::impl::SigManager::instance()->sign(data.data(), data.size(), out.data(), signatureLength()); + bftEngine::impl::SigManager::instance()->sign(data.data(), data.size(), out.data()); return out; } uint32_t signatureLength() const override { return bftEngine::impl::SigManager::instance()->getMySigLength(); } diff --git a/bftengine/src/bcstatetransfer/BCStateTran.cpp b/bftengine/src/bcstatetransfer/BCStateTran.cpp index 2d2410f07f..ef855f7fbd 100644 --- a/bftengine/src/bcstatetransfer/BCStateTran.cpp +++ b/bftengine/src/bcstatetransfer/BCStateTran.cpp @@ -23,7 +23,6 @@ #include "assertUtils.hpp" #include "hex_tools.h" #include "BCStateTran.hpp" -#include "digest.hpp" #include "InMemoryDataStore.hpp" #include "json_output.hpp" #include "ReservedPagesClient.hpp" @@ -52,6 +51,7 @@ using concord::util::digest::DigestGenerator; namespace bftEngine { namespace bcst { +using concord::util::digest::BlockDigest; void computeBlockDigest(const uint64_t blockId, const char *block, diff --git a/bftengine/src/bcstatetransfer/BCStateTran.hpp b/bftengine/src/bcstatetransfer/BCStateTran.hpp index 663520547a..db20cde186 100644 --- a/bftengine/src/bcstatetransfer/BCStateTran.hpp +++ b/bftengine/src/bcstatetransfer/BCStateTran.hpp @@ -518,7 +518,9 @@ class BCStateTran : public IStateTransfer { const uint32_t blockSize, Digest* outDigest); - static BlockDigest computeDigestOfBlock(const uint64_t blockNum, const char* block, const uint32_t blockSize); + static concord::util::digest::BlockDigest computeDigestOfBlock(const uint64_t blockNum, + const char* block, + const uint32_t blockSize); protected: // A wrapper function to get a block from the IAppState and compute its digest. diff --git a/bftengine/src/bftengine/BFTEngine.cpp b/bftengine/src/bftengine/BFTEngine.cpp index f930c4e9a1..b3cfd68658 100644 --- a/bftengine/src/bftengine/BFTEngine.cpp +++ b/bftengine/src/bftengine/BFTEngine.cpp @@ -25,22 +25,13 @@ #include "ReservedPagesClient.hpp" #include "bftengine/EpochManager.hpp" #include "bcstatetransfer/AsyncStateTransferCRE.hpp" +#include "util/filesystem.hpp" #include #include #include #include #include -#if __has_include() -#include -namespace fs = std::filesystem; -#elif __has_include() -#include -namespace fs = std::experimental::filesystem; -#else -#error "Missing filesystem support" -#endif - #include bftEngine::IReservedPages *bftEngine::ReservedPagesClientBase::res_pages_ = nullptr; diff --git a/bftengine/src/bftengine/ClientsManager.cpp b/bftengine/src/bftengine/ClientsManager.cpp old mode 100755 new mode 100644 index aab475973e..f8f36b08d5 --- a/bftengine/src/bftengine/ClientsManager.cpp +++ b/bftengine/src/bftengine/ClientsManager.cpp @@ -417,9 +417,7 @@ std::unique_ptr ClientsManager::allocateReplyFromSavedOne(NodeId return r; } -void ClientsManager::setClientPublicKey(NodeIdType clientId, - const std::string& key, - concord::util::crypto::KeyFormat fmt) { +void ClientsManager::setClientPublicKey(NodeIdType clientId, const std::string& key, concord::crypto::KeyFormat fmt) { LOG_INFO(CL_MNGR, "key: " << key << " fmt: " << (uint16_t)fmt << " client: " << clientId); ClientInfo& info = clientsInfo_[clientId]; info.pubKey = std::make_pair(key, fmt); diff --git a/bftengine/src/bftengine/ClientsManager.hpp b/bftengine/src/bftengine/ClientsManager.hpp index e76aaa80ee..4aaae476c2 100755 --- a/bftengine/src/bftengine/ClientsManager.hpp +++ b/bftengine/src/bftengine/ClientsManager.hpp @@ -190,7 +190,7 @@ class ClientsManager : public ResPagesClient, public IPendingReq // cases: // - The given NodeIdType parameter is not the ID of a valid client. // - The given public key does not fit in a single reserved page under ClientsManager's implementation. - void setClientPublicKey(NodeIdType, const std::string& key, concord::util::crypto::KeyFormat) override; + void setClientPublicKey(NodeIdType, const std::string& key, concord::crypto::KeyFormat) override; // General static uint32_t reservedPagesPerClient(const uint32_t& sizeOfReservedPage, const uint32_t& maxReplySize); @@ -258,7 +258,7 @@ class ClientsManager : public ResPagesClient, public IPendingReq struct ClientInfo { std::shared_ptr requestsInfo; std::shared_ptr repliesInfo; - std::pair pubKey; + std::pair pubKey; }; std::set proxyClients_; diff --git a/bftengine/src/bftengine/DbCheckpointManager.cpp b/bftengine/src/bftengine/DbCheckpointManager.cpp index 9d8530b942..264ff1f398 100644 --- a/bftengine/src/bftengine/DbCheckpointManager.cpp +++ b/bftengine/src/bftengine/DbCheckpointManager.cpp @@ -334,8 +334,7 @@ void DbCheckpointManager::sendInternalCreateDbCheckpointMsg(const SeqNum& seqNum std::vector data_vec; concord::messages::db_checkpoint_msg::serialize(data_vec, req); std::string sig(SigManager::instance()->getMySigLength(), '\0'); - uint16_t sig_length{0}; - SigManager::instance()->sign(reinterpret_cast(data_vec.data()), data_vec.size(), sig.data(), sig_length); + SigManager::instance()->sign(reinterpret_cast(data_vec.data()), data_vec.size(), sig.data()); req.signature = std::vector(sig.begin(), sig.end()); data_vec.clear(); concord::messages::db_checkpoint_msg::serialize(data_vec, req); diff --git a/bftengine/src/bftengine/KeyExchangeManager.cpp b/bftengine/src/bftengine/KeyExchangeManager.cpp index f0eb930691..5f89863cdc 100644 --- a/bftengine/src/bftengine/KeyExchangeManager.cpp +++ b/bftengine/src/bftengine/KeyExchangeManager.cpp @@ -20,9 +20,19 @@ #include "bftengine/EpochManager.hpp" #include "concord.cmf.hpp" #include "communication/StateControl.hpp" +#include "crypto/factory.hpp" +#include "crypto.hpp" +#include "openssl/utils.hpp" namespace bftEngine::impl { +using concord::crypto::KeyFormat; +using concord::crypto::SIGN_VERIFY_ALGO; +using concord::crypto::EdDSAHexToPem; +using concord::crypto::RsaHexToPem; +using concord::crypto::generateECDSAKeyPair; +using concord::crypto::generateSelfSignedCert; + KeyExchangeManager::KeyExchangeManager(InitData* id) : repID_{ReplicaConfig::instance().getreplicaId()}, clusterSize_{ReplicaConfig::instance().getnumReplicas()}, @@ -146,18 +156,22 @@ void KeyExchangeManager::loadClientPublicKeys() { } void KeyExchangeManager::exchangeTlsKeys(const std::string& type, const SeqNum& bft_sn) { - auto keys = concord::util::crypto::Crypto::instance().generateECDSAKeyPair( - concord::util::crypto::KeyFormat::PemFormat, concord::util::crypto::CurveType::secp384r1); + auto keys = generateECDSAKeyPair(concord::crypto::KeyFormat::PemFormat, concord::crypto::CurveType::secp384r1); bool use_unified_certs = bftEngine::ReplicaConfig::instance().useUnifiedCertificates; const std::string base_path = bftEngine::ReplicaConfig::instance().certificatesRootPath + "/" + std::to_string(repID_); std::string root_path = (use_unified_certs) ? base_path : base_path + "/" + type; - std::string cert_path = (use_unified_certs) ? root_path + "/node.cert" : root_path + "/" + type + ".cert"; - std::string prev_key_pem = concord::util::crypto::Crypto::instance() - .RsaHexToPem(std::make_pair(SigManager::instance()->getSelfPrivKey(), "")) - .first; - auto cert = concord::util::crypto::CertificateUtils::generateSelfSignedCert(cert_path, keys.second, prev_key_pem); + + std::string prev_key_pem; + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + prev_key_pem = RsaHexToPem(std::make_pair(SigManager::instance()->getSelfPrivKey(), "")).first; + } else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + prev_key_pem = EdDSAHexToPem(std::make_pair(SigManager::instance()->getSelfPrivKey(), "")).first; + } + + auto cert = + generateSelfSignedCert(cert_path, keys.second, prev_key_pem, ReplicaConfig::instance().replicaMsgSigningAlgo); // Now that we have generated new key pair and certificate, lets do the actual exchange on this replica std::string pk_path = root_path + "/pk.pem"; std::fstream nec_f(pk_path); @@ -186,8 +200,7 @@ void KeyExchangeManager::exchangeTlsKeys(const std::string& type, const SeqNum& std::vector data_vec; concord::messages::serialize(data_vec, req); std::string sig(SigManager::instance()->getMySigLength(), '\0'); - uint16_t sig_length{0}; - SigManager::instance()->sign(reinterpret_cast(data_vec.data()), data_vec.size(), sig.data(), sig_length); + SigManager::instance()->sign(reinterpret_cast(data_vec.data()), data_vec.size(), sig.data()); req.signature = std::vector(sig.begin(), sig.end()); data_vec.clear(); concord::messages::serialize(data_vec, req); @@ -212,8 +225,7 @@ void KeyExchangeManager::sendMainPublicKey() { std::vector data_vec; concord::messages::serialize(data_vec, req); std::string sig(SigManager::instance()->getMySigLength(), '\0'); - uint16_t sig_length{0}; - SigManager::instance()->sign(reinterpret_cast(data_vec.data()), data_vec.size(), sig.data(), sig_length); + SigManager::instance()->sign(reinterpret_cast(data_vec.data()), data_vec.size(), sig.data()); req.signature = std::vector(sig.begin(), sig.end()); data_vec.clear(); concord::messages::serialize(data_vec, req); @@ -294,9 +306,7 @@ void KeyExchangeManager::onPublishClientsKeys(const std::string& keys, std::opti if (save) saveClientsPublicKeys(keys); } -void KeyExchangeManager::onClientPublicKeyExchange(const std::string& key, - concord::util::crypto::KeyFormat fmt, - NodeIdType clientId) { +void KeyExchangeManager::onClientPublicKeyExchange(const std::string& key, KeyFormat fmt, NodeIdType clientId) { LOG_INFO(KEY_EX_LOG, "key: " << key << " fmt: " << (uint16_t)fmt << " client: " << clientId); // persist a new key clientPublicKeyStore_->setClientPublicKey(clientId, key, fmt); @@ -305,7 +315,7 @@ void KeyExchangeManager::onClientPublicKeyExchange(const std::string& key, } void KeyExchangeManager::loadClientPublicKey(const std::string& key, - concord::util::crypto::KeyFormat fmt, + KeyFormat fmt, NodeIdType clientId, bool saveToReservedPages) { LOG_INFO(KEY_EX_LOG, "key: " << key << " fmt: " << (uint16_t)fmt << " client: " << clientId); diff --git a/bftengine/src/bftengine/ReadOnlyReplica.cpp b/bftengine/src/bftengine/ReadOnlyReplica.cpp index 9abc2a9d02..1b054ebed0 100644 --- a/bftengine/src/bftengine/ReadOnlyReplica.cpp +++ b/bftengine/src/bftengine/ReadOnlyReplica.cpp @@ -62,9 +62,9 @@ ReadOnlyReplica::ReadOnlyReplica(const ReplicaConfig &config, SigManager::init(config_.replicaId, config_.replicaPrivateKey, config_.publicKeysOfReplicas, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, ReplicaConfig::instance().getPublicKeysOfClients(), - concord::util::crypto::KeyFormat::PemFormat, + concord::crypto::KeyFormat::PemFormat, *repsInfo); // Register status handler for Read-Only replica diff --git a/bftengine/src/bftengine/ReplicaImp.cpp b/bftengine/src/bftengine/ReplicaImp.cpp index 53b6e9511b..d9f9bc312d 100644 --- a/bftengine/src/bftengine/ReplicaImp.cpp +++ b/bftengine/src/bftengine/ReplicaImp.cpp @@ -4155,6 +4155,7 @@ ReplicaImp::ReplicaImp(const LoadedReplicaData &ld, Digest digest; e.getPrePrepareMsg()->digestOfRequests().digestOfDigest(digest); + CommitPartialMsg *c = CommitPartialMsg::create(getCurrentView(), s, config_.getreplicaId(), @@ -4425,9 +4426,9 @@ ReplicaImp::ReplicaImp(bool firstTime, sigManager_.reset(SigManager::init(config_.replicaId, config_.replicaPrivateKey, config_.publicKeysOfReplicas, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, ReplicaConfig::instance().getPublicKeysOfClients(), - concord::util::crypto::KeyFormat::PemFormat, + concord::crypto::KeyFormat::PemFormat, *repsInfo)); viewsManager = new ViewsManager(repsInfo); } else { @@ -4623,7 +4624,7 @@ void ReplicaImp::start() { if (ReplicaConfig::instance().getkeyExchangeOnStart() && !KeyExchangeManager::instance().exchanged()) { KeyExchangeManager::instance().sendInitialKey(currentPrimary()); } else { - // If key exchange is disabled, first publish the replica's main (rsa) key to clients + // If key exchange is disabled, first publish the replica's main (rsa/eddsa) key to clients if (ReplicaConfig::instance().publishReplicasMasterKeyOnStartup) KeyExchangeManager::instance().sendMainPublicKey(); } KeyExchangeManager::instance().sendInitialClientsKeys(SigManager::instance()->getClientsPublicKeys()); @@ -5335,8 +5336,7 @@ void ReplicaImp::onExecutionFinish() { std::vector data_vec; concord::messages::serialize(data_vec, req); std::string sig(SigManager::instance()->getMySigLength(), '\0'); - uint16_t sig_length{0}; - SigManager::instance()->sign(reinterpret_cast(data_vec.data()), data_vec.size(), sig.data(), sig_length); + SigManager::instance()->sign(reinterpret_cast(data_vec.data()), data_vec.size(), sig.data()); req.signature = std::vector(sig.begin(), sig.end()); data_vec.clear(); concord::messages::serialize(data_vec, req); @@ -5790,8 +5790,7 @@ void ReplicaImp::executeNextCommittedRequests(concordUtils::SpanWrapper &parent_ std::vector data_vec; concord::messages::serialize(data_vec, req); std::string sig(SigManager::instance()->getMySigLength(), '\0'); - uint16_t sig_length{0}; - SigManager::instance()->sign(reinterpret_cast(data_vec.data()), data_vec.size(), sig.data(), sig_length); + SigManager::instance()->sign(reinterpret_cast(data_vec.data()), data_vec.size(), sig.data()); req.signature = std::vector(sig.begin(), sig.end()); data_vec.clear(); concord::messages::serialize(data_vec, req); @@ -5822,8 +5821,7 @@ void ReplicaImp::executeNextCommittedRequests(concordUtils::SpanWrapper &parent_ std::vector data_vec; concord::messages::serialize(data_vec, req); std::string sig(SigManager::instance()->getMySigLength(), '\0'); - uint16_t sig_length{0}; - SigManager::instance()->sign(reinterpret_cast(data_vec.data()), data_vec.size(), sig.data(), sig_length); + SigManager::instance()->sign(reinterpret_cast(data_vec.data()), data_vec.size(), sig.data()); req.signature = std::vector(sig.begin(), sig.end()); data_vec.clear(); concord::messages::serialize(data_vec, req); diff --git a/bftengine/src/bftengine/ReplicaLoader.cpp b/bftengine/src/bftengine/ReplicaLoader.cpp index da0f960263..0fa1ab7a0f 100644 --- a/bftengine/src/bftengine/ReplicaLoader.cpp +++ b/bftengine/src/bftengine/ReplicaLoader.cpp @@ -52,9 +52,9 @@ ReplicaLoader::ErrorCode loadConfig(LoadedReplicaData &ld) { ld.sigManager = SigManager::init(config.replicaId, config.replicaPrivateKey, config.publicKeysOfReplicas, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, ReplicaConfig::instance().getPublicKeysOfClients(), - concord::util::crypto::KeyFormat::PemFormat, + concord::crypto::KeyFormat::PemFormat, *ld.repsInfo); std::unique_ptr cryptoSys = std::make_unique(ld.repConfig.thresholdSystemType_, diff --git a/bftengine/src/bftengine/RequestHandler.cpp b/bftengine/src/bftengine/RequestHandler.cpp index d8afb1f554..ad862b6d14 100644 --- a/bftengine/src/bftengine/RequestHandler.cpp +++ b/bftengine/src/bftengine/RequestHandler.cpp @@ -30,6 +30,37 @@ using namespace concord::performance; namespace bftEngine { +RequestHandler::RequestHandler(concord::performance::ISystemResourceEntity& resourceEntity, + std::shared_ptr aggregator_) + : reconfig_dispatcher_{}, resourceEntity_(resourceEntity) { + reconfig_handler_.push_back(std::make_shared()); + for (const auto& rh : reconfig_handler_) { + reconfig_dispatcher_.addReconfigurationHandler(rh); + } + reconfig_dispatcher_.addReconfigurationHandler( + std::make_shared()); + reconfig_dispatcher_.setAggregator(aggregator_); +} + +void RequestHandler::setUserRequestHandler(std::shared_ptr userHdlr) { + if (userHdlr) { + userRequestsHandler_ = userHdlr; + for (const auto& rh : userHdlr->getReconfigurationHandler()) { + reconfig_dispatcher_.addReconfigurationHandler(rh); + } + } +} + +void RequestHandler::setReconfigurationHandler(std::shared_ptr rh, + concord::reconfiguration::ReconfigurationHandlerType type) { + IRequestsHandler::setReconfigurationHandler(rh, type); + reconfig_dispatcher_.addReconfigurationHandler(rh, type); +} + +void RequestHandler::setCronTableRegistry(const std::shared_ptr& reg) { + cron_table_registry_ = reg; +} + void RequestHandler::execute(IRequestsHandler::ExecutionRequestsQueue& requests, std::optional timestamp, const std::string& batchCid, diff --git a/bftengine/src/bftengine/RequestHandler.h b/bftengine/src/bftengine/RequestHandler.h index 34227dd9a9..208cf05e86 100644 --- a/bftengine/src/bftengine/RequestHandler.h +++ b/bftengine/src/bftengine/RequestHandler.h @@ -26,16 +26,7 @@ class RequestHandler : public IRequestsHandler { public: RequestHandler( concord::performance::ISystemResourceEntity &resourceEntity, - std::shared_ptr aggregator_ = std::make_shared()) - : resourceEntity_(resourceEntity) { - using namespace concord::reconfiguration; - reconfig_handler_.push_back(std::make_shared()); - for (const auto &rh : reconfig_handler_) { - reconfig_dispatcher_.addReconfigurationHandler(rh); - } - reconfig_dispatcher_.addReconfigurationHandler(std::make_shared()); - reconfig_dispatcher_.setAggregator(aggregator_); - } + std::shared_ptr aggregator_ = std::make_shared()); void execute(ExecutionRequestsQueue &requests, std::optional timestamp, @@ -47,25 +38,13 @@ class RequestHandler : public IRequestsHandler { const std::string &batchCid, concordUtils::SpanWrapper &parent_span) override; - void setUserRequestHandler(std::shared_ptr userHdlr) { - if (userHdlr) { - userRequestsHandler_ = userHdlr; - for (const auto &rh : userHdlr->getReconfigurationHandler()) { - reconfig_dispatcher_.addReconfigurationHandler(rh); - } - } - } + void setUserRequestHandler(std::shared_ptr userHdlr); void setReconfigurationHandler(std::shared_ptr rh, concord::reconfiguration::ReconfigurationHandlerType type = - concord::reconfiguration::ReconfigurationHandlerType::REGULAR) override { - IRequestsHandler::setReconfigurationHandler(rh, type); - reconfig_dispatcher_.addReconfigurationHandler(rh, type); - } + concord::reconfiguration::ReconfigurationHandlerType::REGULAR) override; - void setCronTableRegistry(const std::shared_ptr ®) { - cron_table_registry_ = reg; - } + void setCronTableRegistry(const std::shared_ptr ®); void setPersistentStorage(const std::shared_ptr &persistent_storage) override; void onFinishExecutingReadWriteRequests() override { userRequestsHandler_->onFinishExecutingReadWriteRequests(); } std::shared_ptr getUserHandler() { return userRequestsHandler_; } diff --git a/bftengine/src/bftengine/SigManager.cpp b/bftengine/src/bftengine/SigManager.cpp index b65dd6b3b8..71792e0778 100644 --- a/bftengine/src/bftengine/SigManager.cpp +++ b/bftengine/src/bftengine/SigManager.cpp @@ -16,12 +16,17 @@ #include #include "keys_and_signatures.cmf.hpp" #include "ReplicaConfig.hpp" +#include "hex_tools.h" +#include "crypto/factory.hpp" using namespace std; namespace bftEngine { namespace impl { +using concord::crypto::IVerifier; +using concord::crypto::Factory; + concord::messages::keys_and_signatures::ClientsPublicKeys clientsPublicKeys_; std::string SigManager::getClientsPublicKeys() { @@ -34,11 +39,11 @@ std::string SigManager::getClientsPublicKeys() { SigManager* SigManager::initImpl(ReplicaId myId, const Key& mySigPrivateKey, const std::set>& publicKeysOfReplicas, - concord::util::crypto::KeyFormat replicasKeysFormat, + KeyFormat replicasKeysFormat, const std::set>>* publicKeysOfClients, - concord::util::crypto::KeyFormat clientsKeysFormat, + KeyFormat clientsKeysFormat, ReplicasInfo& replicasInfo) { - vector> publickeys; + vector> publickeys; map publicKeysMapping; size_t lowBound, highBound; auto numReplicas = replicasInfo.getNumberOfReplicas(); @@ -96,9 +101,9 @@ SigManager* SigManager::initImpl(ReplicaId myId, SigManager* SigManager::init(ReplicaId myId, const Key& mySigPrivateKey, const std::set>& publicKeysOfReplicas, - concord::util::crypto::KeyFormat replicasKeysFormat, + KeyFormat replicasKeysFormat, const std::set>>* publicKeysOfClients, - concord::util::crypto::KeyFormat clientsKeysFormat, + KeyFormat clientsKeysFormat, ReplicasInfo& replicasInfo) { SigManager* sm = initImpl(myId, mySigPrivateKey, @@ -112,8 +117,8 @@ SigManager* SigManager::init(ReplicaId myId, SigManager::SigManager(PrincipalId myId, uint16_t numReplicas, - const pair& mySigPrivateKey, - const vector>& publickeys, + const pair& mySigPrivateKey, + const vector>& publickeys, const map& publicKeysMapping, bool clientTransactionSigningEnabled, ReplicasInfo& replicasInfo) @@ -130,12 +135,14 @@ SigManager::SigManager(PrincipalId myId, metrics_component_.RegisterAtomicCounter("peer_replicas_signature_verification_failed"), metrics_component_.RegisterAtomicCounter("peer_replicas_signatures_verified"), metrics_component_.RegisterAtomicCounter("signature_verification_failed_on_unrecognized_participant_id")} { - map> publicKeyIndexToVerifier; + map> publicKeyIndexToVerifier; size_t numPublickeys = publickeys.size(); ConcordAssert(publicKeysMapping.size() >= numPublickeys); - if (!mySigPrivateKey.first.empty()) - mySigner_.reset(new concord::util::crypto::RSASigner(mySigPrivateKey.first.c_str(), mySigPrivateKey.second)); + if (!mySigPrivateKey.first.empty()) { + mySigner_ = Factory::getSigner( + mySigPrivateKey.first, ReplicaConfig::instance().replicaMsgSigningAlgo, mySigPrivateKey.second); + } for (const auto& p : publicKeysMapping) { ConcordAssert(verifiers_.count(p.first) == 0); ConcordAssert(p.second < numPublickeys); @@ -143,7 +150,8 @@ SigManager::SigManager(PrincipalId myId, auto iter = publicKeyIndexToVerifier.find(p.second); const auto& [key, format] = publickeys[p.second]; if (iter == publicKeyIndexToVerifier.end()) { - verifiers_[p.first] = std::make_shared(key.c_str(), format); + verifiers_[p.first] = std::shared_ptr( + Factory::getVerifier(key, ReplicaConfig::instance().replicaMsgSigningAlgo, format)); publicKeyIndexToVerifier[p.second] = verifiers_[p.first]; } else { verifiers_[p.first] = iter->second; @@ -237,22 +245,22 @@ bool SigManager::verifySig( return result; } -void SigManager::sign(const char* data, size_t dataLength, char* outSig, uint16_t outSigLength) const { +void SigManager::sign(const char* data, size_t dataLength, char* outSig) const { std::string str_data(data, dataLength); - std::string sig; - sig = mySigner_->sign(str_data); - outSigLength = sig.size(); - std::memcpy(outSig, sig.c_str(), outSigLength); + std::string sig = mySigner_->sign(str_data); + std::memcpy(outSig, sig.c_str(), sig.size()); } uint16_t SigManager::getMySigLength() const { return (uint16_t)mySigner_->signatureLength(); } -void SigManager::setClientPublicKey(const std::string& key, PrincipalId id, concord::util::crypto::KeyFormat format) { +void SigManager::setClientPublicKey(const std::string& key, PrincipalId id, KeyFormat format) { LOG_INFO(KEY_EX_LOG, "client: " << id << " key: " << key << " format: " << (uint16_t)format); if (replicasInfo_.isIdOfExternalClient(id) || replicasInfo_.isIdOfClientService(id)) { try { std::unique_lock lock(mutex_); - verifiers_.insert_or_assign(id, std::make_shared(key.c_str(), format)); + verifiers_.insert_or_assign(id, + std::shared_ptr(Factory::getVerifier( + key, ReplicaConfig::instance().replicaMsgSigningAlgo, format))); } catch (const std::exception& e) { LOG_ERROR(KEY_EX_LOG, "failed to add a key for client: " << id << " reason: " << e.what()); throw; diff --git a/bftengine/src/bftengine/SigManager.hpp b/bftengine/src/bftengine/SigManager.hpp index 5a0fae67b9..9927734659 100644 --- a/bftengine/src/bftengine/SigManager.hpp +++ b/bftengine/src/bftengine/SigManager.hpp @@ -13,7 +13,9 @@ #include "PrimitiveTypes.hpp" #include "assertUtils.hpp" #include "Metrics.hpp" -#include "crypto_utils.hpp" +#include "crypto.hpp" +#include "crypto/signer.hpp" +#include "crypto/verifier.hpp" #include #include @@ -27,6 +29,8 @@ using concordMetrics::AtomicCounterHandle; namespace bftEngine { namespace impl { +using concord::crypto::KeyFormat; + class ReplicasInfo; class SigManager { @@ -50,22 +54,22 @@ class SigManager { static SigManager* init(ReplicaId myId, const Key& mySigPrivateKey, const std::set>& publicKeysOfReplicas, - concord::util::crypto::KeyFormat replicasKeysFormat, + KeyFormat replicasKeysFormat, const std::set>>* publicKeysOfClients, - concord::util::crypto::KeyFormat clientsKeysFormat, + KeyFormat clientsKeysFormat, ReplicasInfo& replicasInfo); // returns 0 if pid is invalid - caller might consider throwing an exception uint16_t getSigLength(PrincipalId pid) const; // returns false if actual verification failed, or if pid is invalid bool verifySig(PrincipalId pid, const char* data, size_t dataLength, const char* sig, uint16_t sigLength) const; - void sign(const char* data, size_t dataLength, char* outSig, uint16_t outSigLength) const; + void sign(const char* data, size_t dataLength, char* outSig) const; uint16_t getMySigLength() const; bool isClientTransactionSigningEnabled() { return clientTransactionSigningEnabled_; } void SetAggregator(std::shared_ptr aggregator) { metrics_component_.SetAggregator(aggregator); } - void setClientPublicKey(const std::string& key, PrincipalId, concord::util::crypto::KeyFormat); + void setClientPublicKey(const std::string& key, PrincipalId, KeyFormat); bool hasVerifier(PrincipalId pid); SigManager(const SigManager&) = delete; SigManager& operator=(const SigManager&) = delete; @@ -84,8 +88,8 @@ class SigManager { SigManager(PrincipalId myId, uint16_t numReplicas, - const std::pair& mySigPrivateKey, - const std::vector>& publickeys, + const std::pair& mySigPrivateKey, + const std::vector>& publickeys, const std::map& publicKeysMapping, bool clientTransactionSigningEnabled, ReplicasInfo& replicasInfo); @@ -93,14 +97,14 @@ class SigManager { static SigManager* initImpl(ReplicaId myId, const Key& mySigPrivateKey, const std::set>& publicKeysOfReplicas, - concord::util::crypto::KeyFormat replicasKeysFormat, + KeyFormat replicasKeysFormat, const std::set>>* publicKeysOfClients, - concord::util::crypto::KeyFormat clientsKeysFormat, + KeyFormat clientsKeysFormat, ReplicasInfo& replicasInfo); const PrincipalId myId_; - std::unique_ptr mySigner_; - std::map> verifiers_; + std::unique_ptr mySigner_; + std::map> verifiers_; bool clientTransactionSigningEnabled_ = true; ReplicasInfo& replicasInfo_; @@ -126,9 +130,9 @@ class SigManager { ReplicaId myId, const Key& mySigPrivateKey, const std::set>& publicKeysOfReplicas, - concord::util::crypto::KeyFormat replicasKeysFormat, + KeyFormat replicasKeysFormat, const std::set>>* publicKeysOfClients, - concord::util::crypto::KeyFormat clientsKeysFormat, + KeyFormat clientsKeysFormat, ReplicasInfo& replicasInfo) { return initImpl(myId, mySigPrivateKey, diff --git a/bftengine/src/bftengine/messages/CheckpointMsg.cpp b/bftengine/src/bftengine/messages/CheckpointMsg.cpp index 7f563552c1..e951f53eec 100644 --- a/bftengine/src/bftengine/messages/CheckpointMsg.cpp +++ b/bftengine/src/bftengine/messages/CheckpointMsg.cpp @@ -43,7 +43,7 @@ CheckpointMsg::CheckpointMsg(ReplicaId genReplica, void CheckpointMsg::sign() { auto sigManager = SigManager::instance(); - sigManager->sign(body(), sizeof(Header), body() + sizeof(Header) + spanContextSize(), sigManager->getMySigLength()); + sigManager->sign(body(), sizeof(Header), body() + sizeof(Header) + spanContextSize()); } void CheckpointMsg::validate(const ReplicasInfo& repInfo) const { diff --git a/bftengine/src/bftengine/messages/ReplicaAsksToLeaveViewMsg.cpp b/bftengine/src/bftengine/messages/ReplicaAsksToLeaveViewMsg.cpp index 4cbafc18ed..34ceafd97a 100644 --- a/bftengine/src/bftengine/messages/ReplicaAsksToLeaveViewMsg.cpp +++ b/bftengine/src/bftengine/messages/ReplicaAsksToLeaveViewMsg.cpp @@ -46,7 +46,7 @@ ReplicaAsksToLeaveViewMsg* ReplicaAsksToLeaveViewMsg::create(ReplicaId senderId, std::memcpy(position, spanContext.data().data(), spanContext.data().size()); position += spanContext.data().size(); - sigManager->sign(m->body(), sizeof(Header), position, sigLen); + sigManager->sign(m->body(), sizeof(Header), position); return m; } diff --git a/bftengine/src/bftengine/messages/ReplicaRestartReadyMsg.cpp b/bftengine/src/bftengine/messages/ReplicaRestartReadyMsg.cpp index 6addd6edfc..5c235312fc 100644 --- a/bftengine/src/bftengine/messages/ReplicaRestartReadyMsg.cpp +++ b/bftengine/src/bftengine/messages/ReplicaRestartReadyMsg.cpp @@ -52,7 +52,7 @@ ReplicaRestartReadyMsg* ReplicaRestartReadyMsg::create(ReplicaId senderId, ReplicaRestartReadyMsg* m = new ReplicaRestartReadyMsg(senderId, s, sigLen, r, extraData, spanContext); auto dataSize = sizeof(Header) + m->getExtraDataLength() + spanContext.data().size(); auto position = m->body() + dataSize; - sigManager->sign(m->body(), dataSize, position, sigLen); + sigManager->sign(m->body(), dataSize, position); //+-----------+-----------+----------+ //| Header | extraData | Signature| //+-----------+-----------+----------+ diff --git a/bftengine/src/bftengine/messages/ViewChangeMsg.cpp b/bftengine/src/bftengine/messages/ViewChangeMsg.cpp index 40de987b2e..900183c652 100644 --- a/bftengine/src/bftengine/messages/ViewChangeMsg.cpp +++ b/bftengine/src/bftengine/messages/ViewChangeMsg.cpp @@ -162,7 +162,7 @@ void ViewChangeMsg::finalizeMessage() { // | Message Body | // +------------------------------------------+ - sigManager->sign(body(), bodySize, body() + bodySize, sigSize); + sigManager->sign(body(), bodySize, body() + bodySize); bool b = checkElements((uint16_t)sigSize) && checkComplaints((uint16_t)sigSize); diff --git a/bftengine/src/preprocessor/RequestProcessingState.cpp b/bftengine/src/preprocessor/RequestProcessingState.cpp index 9e2e2d52b1..4f968405b8 100644 --- a/bftengine/src/preprocessor/RequestProcessingState.cpp +++ b/bftengine/src/preprocessor/RequestProcessingState.cpp @@ -105,8 +105,7 @@ void RequestProcessingState::handlePrimaryPreProcessed(const char *preProcessRes std::vector sig(sm->getMySigLength()); sm->sign(reinterpret_cast(primaryPreProcessResultHash_.data()), primaryPreProcessResultHash_.size(), - sig.data(), - sig.size()); + sig.data()); if (!preProcessingResultHashes_[primaryPreProcessResultHash_] .emplace(std::move(sig), myReplicaId_, preProcessResult) .second) { @@ -228,8 +227,7 @@ void RequestProcessingState::modifyPrimaryResult( std::vector sig(sm->getMySigLength()); sm->sign(reinterpret_cast(primaryPreProcessResultHash_.data()), primaryPreProcessResultHash_.size(), - sig.data(), - sig.size()); + sig.data()); if (!preProcessingResultHashes_[primaryPreProcessResultHash_] .emplace(std::move(sig), myReplicaId_, primaryPreProcessResult_) .second) { diff --git a/bftengine/src/preprocessor/messages/PreProcessReplyMsg.cpp b/bftengine/src/preprocessor/messages/PreProcessReplyMsg.cpp index 71eb95e38b..69f140687d 100644 --- a/bftengine/src/preprocessor/messages/PreProcessReplyMsg.cpp +++ b/bftengine/src/preprocessor/messages/PreProcessReplyMsg.cpp @@ -154,7 +154,7 @@ void PreProcessReplyMsg::setupMsgBody(const char* preProcessResultBuf, memcpy(msgBody()->resultsHash, hash.data(), SHA3_256::SIZE_IN_BYTES); { concord::diagnostics::TimeRecorder scoped_timer(*preProcessorHistograms_->signPreProcessReplyHash); - sigManager->sign((char*)hash.data(), SHA3_256::SIZE_IN_BYTES, body() + sizeof(Header), sigSize); + sigManager->sign((char*)hash.data(), SHA3_256::SIZE_IN_BYTES, body() + sizeof(Header)); } setLeftMsgParams(reqCid, sigSize); } diff --git a/bftengine/src/preprocessor/messages/PreProcessResultMsg.cpp b/bftengine/src/preprocessor/messages/PreProcessResultMsg.cpp index 13c548b865..48d513168f 100644 --- a/bftengine/src/preprocessor/messages/PreProcessResultMsg.cpp +++ b/bftengine/src/preprocessor/messages/PreProcessResultMsg.cpp @@ -80,8 +80,7 @@ std::optional PreProcessResultMsg::validatePreProcessResultSignatur bool verificationResult = false; if (myReplicaId == sig.sender_replica) { std::vector mySignature(sigManager_->getMySigLength(), '\0'); - sigManager_->sign( - reinterpret_cast(hash.data()), hash.size(), mySignature.data(), mySignature.size()); + sigManager_->sign(reinterpret_cast(hash.data()), hash.size(), mySignature.data()); verificationResult = mySignature == sig.signature; } else { verificationResult = sigManager_->verifySig( diff --git a/bftengine/src/preprocessor/tests/messages/ClientPreProcessRequestMsg_test.cpp b/bftengine/src/preprocessor/tests/messages/ClientPreProcessRequestMsg_test.cpp index 32a2e04371..d09b8c9b3f 100644 --- a/bftengine/src/preprocessor/tests/messages/ClientPreProcessRequestMsg_test.cpp +++ b/bftengine/src/preprocessor/tests/messages/ClientPreProcessRequestMsg_test.cpp @@ -17,7 +17,7 @@ class ClientPreprocessRequestMsgTestFixture : public ::testing::Test { replicaInfo(config, false, false), sigManager(createSigManager(config.replicaId, config.replicaPrivateKey, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, config.publicKeysOfReplicas, replicaInfo)) {} diff --git a/bftengine/src/preprocessor/tests/messages/PreProcessReplyMsg_test.cpp b/bftengine/src/preprocessor/tests/messages/PreProcessReplyMsg_test.cpp index 7fdb11216d..9dd4bbda73 100644 --- a/bftengine/src/preprocessor/tests/messages/PreProcessReplyMsg_test.cpp +++ b/bftengine/src/preprocessor/tests/messages/PreProcessReplyMsg_test.cpp @@ -30,7 +30,7 @@ class PreProcessReplyMsgTestFixture : public testing::Test { replicaInfo{config, false, false}, sigManager(createSigManager(config.replicaId, config.replicaPrivateKey, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, config.publicKeysOfReplicas, replicaInfo)) { PreProcessReplyMsg::setPreProcessorHistograms(&preProcessorRecorder); @@ -110,7 +110,7 @@ TEST_F(PreProcessReplyMsgTestFixture, getResultHashSignature) { const auto hash = PreProcessResultHashCreator::create(preProcessResultBuf, preProcessResultBufLen, opResult, clientId, reqSeqNum); auto expected_signature = std::vector(sigManager->getMySigLength(), 0); - sigManager->sign((char*)hash.data(), sizeof(hash), expected_signature.data(), expected_signature.size()); + sigManager->sign((char*)hash.data(), sizeof(hash), expected_signature.data()); EXPECT_THAT(expected_signature, testing::ContainerEq(preProcessReplyMsg.getResultHashSignature())); clearDiagnosticsHandlers(); } diff --git a/bftengine/src/preprocessor/tests/messages/PreProcessResultMsg_test.cpp b/bftengine/src/preprocessor/tests/messages/PreProcessResultMsg_test.cpp index c660aa339b..e63ebd2e57 100644 --- a/bftengine/src/preprocessor/tests/messages/PreProcessResultMsg_test.cpp +++ b/bftengine/src/preprocessor/tests/messages/PreProcessResultMsg_test.cpp @@ -39,7 +39,7 @@ bftEngine::ReplicaConfig& createReplicaConfigWithExtClient(uint16_t fVal, bftEngine::impl::SigManager* createSigManagerWithSigning( size_t myId, std::string& myPrivateKey, - concord::util::crypto::KeyFormat replicasKeysFormat, + concord::crypto::KeyFormat replicasKeysFormat, std::set>& publicKeysOfReplicas, const std::set>>* publicKeysOfClients, ReplicasInfo& replicasInfo) { @@ -48,7 +48,7 @@ bftEngine::impl::SigManager* createSigManagerWithSigning( publicKeysOfReplicas, replicasKeysFormat, publicKeysOfClients, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, replicasInfo); } @@ -71,7 +71,7 @@ std::pair> getProcessResultSigBuff(const std::uni std::vector msgSig(msgSigSize, 0); auto hash = PreProcessResultHashCreator::create( p.result, sizeof(p.result), OperationResult::SUCCESS, p.senderId, p.reqSeqNum); - sigManager->sign(reinterpret_cast(hash.data()), hash.size(), msgSig.data(), msgSigSize); + sigManager->sign(reinterpret_cast(hash.data()), hash.size(), msgSig.data()); // for simplicity, copy the same signatures std::set resultSigs; @@ -111,7 +111,7 @@ class PreProcessResultMsgTestFixture : public testing::Test { replicaInfo{config, false, false}, sigManager(createSigManagerWithSigning(config.replicaId, config.replicaPrivateKey, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, config.publicKeysOfReplicas, &config.publicKeysOfClients, replicaInfo)) {} @@ -127,7 +127,7 @@ class PreProcessResultMsgTestFixture : public testing::Test { auto hash = PreProcessResultHashCreator::create( p.result, sizeof(p.result), OperationResult::SUCCESS, p.senderId, p.reqSeqNum); - sigManager->sign(reinterpret_cast(hash.data()), hash.size(), msgSig.data(), msgSigSize); + sigManager->sign(reinterpret_cast(hash.data()), hash.size(), msgSig.data()); // For simplicity, copy the same signatures std::list resultSigs; @@ -160,7 +160,7 @@ class PreProcessResultMsgTxSigningOffTestFixture : public testing::Test { replicaInfo{config, false, false}, sigManager(createSigManagerWithSigning(config.replicaId, config.replicaPrivateKey, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, config.publicKeysOfReplicas, &config.publicKeysOfClients, replicaInfo)) {} @@ -256,7 +256,7 @@ TEST_F(PreProcessResultMsgTestFixture, MsgDeserialisation) { std::vector msgSig(msgSigSize, 0); auto hash = PreProcessResultHashCreator::create( msg->requestBuf(), msg->requestLength(), OperationResult::SUCCESS, params.senderId, params.reqSeqNum); - sigManager->sign(reinterpret_cast(hash.data()), hash.size(), msgSig.data(), msgSigSize); + sigManager->sign(reinterpret_cast(hash.data()), hash.size(), msgSig.data()); auto i = 0; for (const auto& s : sigs) { ASSERT_EQ(s.sender_replica, i++); @@ -290,7 +290,7 @@ TEST_F(PreProcessResultMsgTestFixture, MsgDeserialisationFromBase) { std::vector msgSig(msgSigSize, 0); auto hash = PreProcessResultHashCreator::create( msg->requestBuf(), msg->requestLength(), OperationResult::SUCCESS, params.senderId, params.reqSeqNum); - sigManager->sign(reinterpret_cast(hash.data()), hash.size(), msgSig.data(), msgSigSize); + sigManager->sign(reinterpret_cast(hash.data()), hash.size(), msgSig.data()); auto i = 0; for (const auto& s : sigs) { ASSERT_EQ(s.sender_replica, i++); diff --git a/bftengine/src/preprocessor/tests/preprocessor_test.cpp b/bftengine/src/preprocessor/tests/preprocessor_test.cpp index 4d12fd3792..2fabbdf1bc 100644 --- a/bftengine/src/preprocessor/tests/preprocessor_test.cpp +++ b/bftengine/src/preprocessor/tests/preprocessor_test.cpp @@ -28,6 +28,7 @@ using namespace std; using namespace bft::communication; using namespace bftEngine; using namespace preprocessor; +using concord::crypto::SIGN_VERIFY_ALGO; namespace { @@ -53,6 +54,7 @@ const NodeIdType replica_1 = 1; const NodeIdType replica_2 = 2; const NodeIdType replica_3 = 3; const NodeIdType replica_4 = 4; +const NodeIdType replica_5 = 5; const ViewNum viewNum = 1; PreProcessorRecorder preProcessorRecorder; std::shared_ptr sdm = make_shared(); @@ -155,172 +157,178 @@ class DummyPreProcessor : public PreProcessor { }; // clang-format off -const vector privateKeys = { - { - "308204BA020100300D06092A864886F70D0101010500048204A4308204A00201000282010100C55B8F7979BF24B335017082BF33EE2960E3A0" - "68DCDB45CA3017214BFB3F32649400A2484E2108C7CD07AA7616290667AF7C7A1922C82B51CA01867EED9B60A57F5B6EE33783EC258B234748" - "8B0FA3F99B05CFFBB45F80960669594B58C993D07B94D9A89ED8266D9931EAE70BB5E9063DEA9EFAF744393DCD92F2F5054624AA048C7EE50B" - "EF374FCDCE1C8CEBCA1EF12AF492402A6F56DC9338834162F3773B119145BF4B72672E0CF2C7009EBC3D593DFE3715D942CA8749771B484F72" - "A2BC8C89F86DB52ECC40763B6298879DE686C9A2A78604A503609BA34B779C4F55E3BEB0C26B1F84D8FC4EB3C79693B25A77A158EF88292D4C" - "01F99EFE3CC912D09B020111028201001D05EF73BF149474B4F8AEA9D0D2EE5161126A69C6203EF8162184E586D4967833E1F9BF56C89F68AD" - "35D54D99D8DB4B7BB06C4EFD95E840BBD30C3FD7A5E890CEF6DB99E284576EEED07B6C8CEBB63B4B80DAD2311D1A706A5AC95DE768F017213B" - "896B9EE38D2E3C2CFCE5BDF51ABD27391761245CDB3DCB686F05EA2FF654FA91F89DA699F14ACFA7F0D8030F74DBFEC28D55C902A27E9C03AB" - "1CA2770EFC5BE541560D86FA376B1A688D92124496BB3E7A3B78A86EBF1B694683CDB32BC49431990A18B570C104E47AC6B0DE5616851F4309" - "CFE7D0E20B17C154A3D85F33C7791451FFF73BFC4CDC8C16387D184F42AD2A31FCF545C3F9A498FAAC6E94E902818100F40CF9152ED4854E1B" - "BF67C5EA185C52EBEA0C11875563AEE95037C2E61C8D988DDF71588A0B45C23979C5FBFD2C45F9416775E0A644CAD46792296FDC68A98148F7" - "BD3164D9A5E0D6A0C2DF0141D82D610D56CB7C53F3C674771ED9ED77C0B5BF3C936498218176DC9933F1215BC831E0D41285611F512F68327E" - "4FBD9E5C5902818100CF05519FD69D7C6B61324F0A201574C647792B80E5D4D56A51CF5988927A1D54DF9AE4EA656AE25961923A0EC046F1C5" - "69BAB53A64EB0E9F5AB2ABF1C9146935BA40F75E0EB68E0BE4BC29A5A0742B59DF5A55AB028F1CCC42243D2AEE4B74344CA33E72879EF2D1CD" - "D874A7F237202AC7EB57AEDCBD539DEFDA094476EAE613028180396C76D7CEC897D624A581D43714CA6DDD2802D6F2AAAE0B09B885974533E5" - "14D6167505C620C51EA41CA70E1D73D43AA5FA39DA81799922EB3173296109914B98B2C31AAE515434E734E28ED31E8D37DA99BA11C2E693B6" - "398570ABBF6778A33C0E40CC6007E23A15C9B1DE6233B6A25304B91053166D7490FCD26D1D8EAC5102818079C6E4B86020674E392CA6F6E5B2" - "44B0DEBFBF3CC36E232F7B6AE95F6538C5F5B0B57798F05CFD9DFD28D6DB8029BB6511046A9AD1F3AE3F9EC37433DFB1A74CC7E9FAEC08A79E" - "D9D1D8187F8B8FA107B08F7DAFE3633E1DCC8DC9A0C8689EB55A41E87F9B12347B6A06DB359D89D6AFC0E4CA2A9FF6E5E46EF8BA2845F39665" - "0281802A89B2BD4A665A0F07DCAFA6D9DB7669B1D1276FC3365173A53F0E0D5F9CB9C3E08E68503C62EA73EB8E0DA42CCF6B136BF4A85B0AC4" - "24730B4F3CAD8C31D34DD75EF2A39B6BCFE3985CCECC470CF479CF0E9B9D6C7CE1C6C70D853728925326A22352DF73B502D4D3CBC2A770DE27" - "6E1C5953DF7A9614C970C94D194CAE9188" - }, - { - "308204BC020100300D06092A864886F70D0101010500048204A6308204A20201000282010100CAF26C09B1F6F056F66B54AA0EA002EA236151" - "3A721A58E44472ADE74DBD833890ED9EE8E0CFF1B84C3DFE9E6226C8CEBFFEDFE71A6BCFE5A599D02FD9940997E864D400BF440BA7B1A568A5" - "ACF7688B025B5B207E5651E597141FAEF733FA9D87732B8FBA31E082BE777AEB992B00873764655C3B1F8FBF8DD2446F4F9F79883E21DBC1A1" - "7431E42AF01B9D4DE54B9880E7FB397655C79D7C3A5981CA64A32E2F05FCF0B127F4C6D349056276992B7403D36E03D14C45B6F5F66786280C" - "921236A17EE0F311821BDF925A47DCA590BB31C60646692014317BE0DD32248DF557A77F80F336C82461B659266F74F495BA5CE194043505B5" - "F0C363263BF73BB897020111028201005F8123C853BF8028EC6EBE6E2500015F1FB55366CC48A24D4D6324A915865BDE6251B4315ABC3583E7" - "A4B40E4C4E7C9D8786FFF448AB34A84DEE079E0C096DED221154B50EB69C12ADF37C8A334740416A85580F4A82F95CFBCD3C1619FA57D1A927" - "238EEE3596D41D656705754169A90B021194D08752B47EF9899DCB1DDED5DCDDA688D9FA88F9303E99CAB040D2E47DCE866717580C2CD01DB9" - "4E8FE215EAA254432E3B399B90260255DEE7FADED4643814C0DE41DE237BBB7173CFF16AC9237AADA4595FD95EB92E30D2127C7761C6A1CD75" - "C1F12F5B92B6602E1CDC06E112321B0A41C8A102D785B7C4C7D2441DA983346B81873984DD680FB4B1C9AD7102818100D5E41BE52CECFB7405" - "01B87C631DEFB3DD855EE95553A816BE8D3DFAE200086E1C12E9FBDDD8737F2CCE2CED1D82431ADC63C1B34EA59C27E98283EB20EAF8F5A29D" - "45ACE2E5C3173F396DF4356D54F3ED0CF9BBA222E3B9194CD15F88B6AB8FAFDFACACCC97D87555CD1E864D09DF795FB8BE3F9BE2CB8E52F641" - "FCEDC8E97902818100F2E6BDF9A552D35E9F695C52343D9BBF180BBEB50F6705A7836DF1BFF6A42C2D7A000432957516B555B5E1FBAC21CED5" - "D2788036AA5AB183A5859284ED409631289F8836D240111B56D6C4953FEFBE177EA137F08ADCABD5CAD07F709E83BB29B0F55AD09E65F5C656" - "8FE166FF4BE581F4F2066025E3902819EFC2DF0FA63E8F0281803EE8BCE90D36A44F4CC44551C2CC91CB7D637644A0A022610ADE3F67E81E20" - "98DB149F2BF5F45E347696FE279F446E16F586C080081297570871AE5436DBB2A2993D50BA60DA2A5221A77AB13CE3EBCF45B885AFA8286118" - "52BC3D94919F23667F058D23C3B4309AFB1E36278011F66EFE0928E58833A547FA486DC2DC8662C902818100AB75B346CF0D49E870869B8552" - "0D5EE13E26687FCEA3130CD53E8C8780EC5B6B652D3023B4CB1F1696DABDA2979F64D32B27E208784004D565C7B2B82F006A0495255117A378" - "848BC4D3D60EFFF4862EB3BD186D8F325B2D801AB44F7EF3932C7CE96D47F75707D74C2953D03BBD1A79DA1440BC56FAFC588AC75C6138391D" - "1902818100BBC05F561AEF4BDE1ECABB5CD313E6173F5E46AC85B4462A8CA689E4E84B95E66733081518DB01714B7B18E44B780DB5A6DA2612" - "506F46E4D91C8CB582AFD54C7509C9947EC754BFDD0D35FAECE2E729DBD21A62E33C3DEF556913ECF4C8D75910E860D36AFD0977FF9114ACEA" - "8F44882259C6F1D8314B653F64F4655CFD68A6" - }, - { - "308204BA020100300D06092A864886F70D0101010500048204A4308204A00201000282010100DA68B2830103028D0ECD911D20E732257F8A39" - "BC5214B670C8F1F836CD1D88E6421ABD3C47F16E37E07DCFE89FC11ECBED73896FC978B7E1519F59318F3E24BB5C8962B0EA44889C3A81021C" - "C9E8EAA94099B9305B0F7731C27CC528CFEE710066CB69229F8AA04DBD842FA8C3143CB0EF1164E45E34B114FBA610DBDFC7453DAD995743AD" - "1489AA131D0C730163ECA7317048C1AD1008ED31A32CB773D94B5317CAAF95674582DCA1AC9FEBE02079836B52E1E3C8D39571018A7657650D" - "52D2DF3363F88A690628D64DCBECB88BBA432F27C32E7BC5BC0F1D16D0A027D1D40362F8CEDBE8BED05C2BCE96F33A75CD70014626B32E5EE8" - "1EBD3116F6F1E5231B02011102820100201E749ACB716241EB96B375398B6941BFEEAE23393F480186F668444B572AB873220CC519A3812655" - "B8261AAE14DEE1C1097617F7FB2A199B0FE7783AB650B22432524731828C8F7203E9B8F08422824D43C868FE55190ED8D61CFE78EE5BE97887" - "5339CC2AF974D81AF7F32BBF361A050A165DD19E5646D9B68A02377F2FD417BE92D2722CEE33B3A0F7B111639C092B4024BB08ACEBE9F9BC28" - "C14BB611DBE627136B568493C6995D81442F09DFEFBA4378A34DEF28F3BD862F4C28BECA87A95551FC2DB48766F82752C7E8B34E8599590190" - "B12A648AC1E361FE28A3253EC615381A066BFD351C18F0B236429A950106DD4F1134A3DE6CEB1094B7CE5C7102818100EA51580294BB0FD7DA" - "FDC00364A9B3C4781F70C4BBE8BDE0D82895ADE549E25388E78A53EF83CF9A3D9528F70CB5A57A9A187D5AC68682F03B26C2F6A409E1554FED" - "061BDC944985102F2988A5A8CD639BA7890FD689D7171612159AAA818F5502EF80D5D13339826A98914A321B5B4512EC24AF3EE80F982D3418" - "0C85B3E38102818100EE9E7F43A98E593F72A584EEC014E0A46003116B82F5D3A21DAE4EB3F21FBC5B71D96E012B6F5FFBEACED4BEC6C147AA" - "AB6F9698F0592F3A8A6CD827ABF210497635639043D5F0B461E00914B152D6ECB3EFC9138A1B9FAEE09420AB9C2E1436B6AC36EEB8AD43709B" - "BFA0ED30FBF09C1A91BAB71410E49E11BE8E2A571C649B02818044EABF8849DCAA4E8BB40B4C4AC8802AB9EB212ACDDB0AAB8ADEC29C8EBB60" - "AF284419A0376300D3030DC0C121DB128D789DCA841C45AE0A6BC01B397B8A6F7371DC4D1740E051DBD79566919A2296C2F18BA0C86C46A8AC" - "6FE73387D7CBC0BEA682AD6C105A5C356AA557E8A553571450DC0ACA218F8C1DB2F1343FEB16CA71028180704A963DF57029FFBD7B11614B55" - "1E6B7879EA1479DD184C4A33E8CD26A585D0AE0BF7881470A5A3B9CABE77E50FA941419DEC8434DEACD04124297C14AE25C837A0A752F2BF07" - "DC6A4B4F91446337F6EB43A9EB13D0C39D96DC4B9C0D42DC55FB9C5615FC8DC5622B2D006F9E94AD76A31766ECBE26113B53A4F79B744998C1" - "028180124E2A5DAC7AC7017647FE1B6871484B7B38A3C060B992B871939C8A75BC35DB771F041910C0092E01B545E1910109AA827F34F56327" - "15E06819ADED60117FD8B9400C3F307EA022D5AC5394E65D28EF434DC068494D33ACF70B43791C1C13C35AC680E0038DB411ADEBBC067F477E" - "01E8CF793FB076AE47BD83B935B8041DC1" - }, - { - "308204BB020100300D06092A864886F70D0101010500048204A5308204A10201000282010100B4D984129ECC2F4350596DD602EB5337B78E33" - "C4D945C70C2CACFF6237037BEF897D6893079D1067F07FF023D66C77BB41F6D41215C9912D995215C6F7651F1728AAB65CF20CBE81E5E7F202" - "E474AF535E92BBC386A7A496263BC4189FD9DD5E801C3023038EFE5B5DE35AA3F70C10F87259D586C36D3DF524E9DA2140C481365985AD185E" - "1CF3E78B6B82FDD274CCD1267838A0B91F9B48544AFB2C71B158A26E6154CECB43ECEE13FFBD6CA91D8D115B6B91C55F3A88E3F389E9A2AF4B" - "C381D21F9ABF2EA16F58773514249B03A4775C6A10561AFC8CF54B551A43FD014F3C5FE12D96AC5F117645E26D125DC7430114FA60577BF7C9" - "AA1224D190B2D8A83B020111028201004FC95FEA18E19C6176459256E32B95A7A3CDCB8B8D08322B04A6ACE790BDC5BC806C087D19F2782DDB" - "0B444C0BC6710ED9564E8073061A66F0D163F5E59D8DB764C3C8ECC523BD758B13815BA1064D597C8C078AF7A450241FED30DDAFEF2CF4FC48" - "ABD336469D648B4DB70C1A2AF86D9BDC56AC6546C882BD763A963329844BF0E8C79E5E7A5C227A1CDB8473965090084BEAC728E4F86670BAE0" - "5DA589FAE1EBC98A26BF207261EECE5A92759DE516306B0B2F715370586EF45447F82CC37206F70D762AAB75215482A67FE6742E9D644AB765" - "4F02476EAE15A742FCB2266DAE437DC76FB17E1698D4987945C779A4B89F5FB3F5E1B194EFA4024BA3797F2502818100E2BDA6F0031EAA027B" - "1E8099D9D2CF408B8C9D83A22BFBAAD3BCFA952469A001C25E5E2E89DAF28636633E8D7C5E1E5FD8384767DB5B384DAB38147EA46871D5E31E" - "DC110026E42E90C44F02110A369ACF0445C617CC25CD1207F116B9AF2FA78A89E6C6345EAFD0607CB145410DD6619AC0C034B54283A0065B93" - "3550B8DACF02818100CC2FDB49EB3E45DB2EB644048C3C35E3BB50980453DB8EB54DD5595CA2DBC43A2F2912D0F696E6126AFBF5D7777BABB2" - "6AC931030B8896343BC19EA30B8EEBFECE2617A2564B3D66E29DF66708254877CC33E699501A2BA4D0D7D02F068B1DCF6C7A0794F24BEE83BE" - "2E8453D3E436C3B59D2D9BEEB5B38541EF170544EA46D502818100AD63DA02D5359110F4BCF8EE1F0A9E7CA6F30F0A4ED6570A29726544DF9C" - "10F2495738F6696B31EE29972FD59B57082B2CDFBE223E54D0B3DD49009D144FDE94808102A396B454239BE169982B25ED85712162886C8D0D" - "D90DC9D67ACA3AABF8971E28F1EBCFEFDB95140F16D764EF3B947547AFD5E791D4B9915274108D5C07028180300B42A7FB1DB61574671F1020" - "FF1BBD1D03E7888C33A91B99D7D8CA80AC2E2BCEDC7CE5DFAB08F546596705858682C09198C03CF3A7AADF1D1E7FADE49A196921725FE9F62F" - "D236537076365C4501FE11EE182412D8FB35D6C95E292EB7524EEC58F2B9A26C381EFF92797D22CC491EFD8E6515A1942A3D78ECF65B97BEA7" - "410281806625E51F70BB9E00D0260941C56B22CDCECC7EA6DBC2C28A1CDA0E1AFAACD39C5E962E40FCFC0F5BBA57A7291A1BDC5D3D29495B45" - "CE2B3BEC7748E6C351FF934537BCA246CA36B840CF68BE6D473F7EE079B0EFDFF6B1BB554B06093E18B269FC3BD3F9876376CA7C673A93F142" - "7088BF0990AB8E232F269B5DBCD446385A66" - }, - { - "308204BB020100300D06092A864886F70D0101010500048204A5308204A10201000282010100B4D984129ECC2F4350596DD602EB5337B78E33" - "C4D945C70C2CACFF6237037BEF897D6893079D1067F07FF023D66C77BB41F6D41215C9912D995215C6F7651F1728AAB65CF20CBE81E5E7F202" - "E474AF535E92BBC386A7A496263BC4189FD9DD5E801C3023038EFE5B5DE35AA3F70C10F87259D586C36D3DF524E9DA2140C481365985AD185E" - "1CF3E78B6B82FDD274CCD1267838A0B91F9B48544AFB2C71B158A26E6154CECB43ECEE13FFBD6CA91D8D115B6B91C55F3A88E3F389E9A2AF4B" - "C381D21F9ABF2EA16F58773514249B03A4775C6A10561AFC8CF54B551A43FD014F3C5FE12D96AC5F117645E26D125DC7430114FA60577BF7C9" - "AA1224D190B2D8A83B020111028201004FC95FEA18E19C6176459256E32B95A7A3CDCB8B8D08322B04A6ACE790BDC5BC806C087D19F2782DDB" - "0B444C0BC6710ED9564E8073061A66F0D163F5E59D8DB764C3C8ECC523BD758B13815BA1064D597C8C078AF7A450241FED30DDAFEF2CF4FC48" - "ABD336469D648B4DB70C1A2AF86D9BDC56AC6546C882BD763A963329844BF0E8C79E5E7A5C227A1CDB8473965090084BEAC728E4F86670BAE0" - "5DA589FAE1EBC98A26BF207261EECE5A92759DE516306B0B2F715370586EF45447F82CC37206F70D762AAB75215482A67FE6742E9D644AB765" - "4F02476EAE15A742FCB2266DAE437DC76FB17E1698D4987945C779A4B89F5FB3F5E1B194EFA4024BA3797F2502818100E2BDA6F0031EAA027B" - "1E8099D9D2CF408B8C9D83A22BFBAAD3BCFA952469A001C25E5E2E89DAF28636633E8D7C5E1E5FD8384767DB5B384DAB38147EA46871D5E31E" - "DC110026E42E90C44F02110A369ACF0445C617CC25CD1207F116B9AF2FA78A89E6C6345EAFD0607CB145410DD6619AC0C034B54283A0065B93" - "3550B8DACF02818100CC2FDB49EB3E45DB2EB644048C3C35E3BB50980453DB8EB54DD5595CA2DBC43A2F2912D0F696E6126AFBF5D7777BABB2" - "6AC931030B8896343BC19EA30B8EEBFECE2617A2564B3D66E29DF66708254877CC33E699501A2BA4D0D7D02F068B1DCF6C7A0794F24BEE83BE" - "2E8453D3E436C3B59D2D9BEEB5B38541EF170544EA46D502818100AD63DA02D5359110F4BCF8EE1F0A9E7CA6F30F0A4ED6570A29726544DF9C" - "10F2495738F6696B31EE29972FD59B57082B2CDFBE223E54D0B3DD49009D144FDE94808102A396B454239BE169982B25ED85712162886C8D0D" - "D90DC9D67ACA3AABF8971E28F1EBCFEFDB95140F16D764EF3B947547AFD5E791D4B9915274108D5C07028180300B42A7FB1DB61574671F1020" - "FF1BBD1D03E7888C33A91B99D7D8CA80AC2E2BCEDC7CE5DFAB08F546596705858682C09198C03CF3A7AADF1D1E7FADE49A196921725FE9F62F" - "D236537076365C4501FE11EE182412D8FB35D6C95E292EB7524EEC58F2B9A26C381EFF92797D22CC491EFD8E6515A1942A3D78ECF65B97BEA7" - "410281806625E51F70BB9E00D0260941C56B22CDCECC7EA6DBC2C28A1CDA0E1AFAACD39C5E962E40FCFC0F5BBA57A7291A1BDC5D3D29495B45" - "CE2B3BEC7748E6C351FF934537BCA246CA36B840CF68BE6D473F7EE079B0EFDFF6B1BB554B06093E18B269FC3BD3F9876376CA7C673A93F142" - "7088BF0990AB8E232F269B5DBCD446385A66" - }}; - -const vector publicKeys = { - { - "30820120300D06092A864886F70D01010105000382010D00308201080282010100C55B8F7979BF24B335017082BF33EE2960E3A068DCDB45CA" - "3017214BFB3F32649400A2484E2108C7CD07AA7616290667AF7C7A1922C82B51CA01867EED9B60A57F5B6EE33783EC258B2347488B0FA3F99B" - "05CFFBB45F80960669594B58C993D07B94D9A89ED8266D9931EAE70BB5E9063DEA9EFAF744393DCD92F2F5054624AA048C7EE50BEF374FCDCE" - "1C8CEBCA1EF12AF492402A6F56DC9338834162F3773B119145BF4B72672E0CF2C7009EBC3D593DFE3715D942CA8749771B484F72A2BC8C89F8" - "6DB52ECC40763B6298879DE686C9A2A78604A503609BA34B779C4F55E3BEB0C26B1F84D8FC4EB3C79693B25A77A158EF88292D4C01F99EFE3C" - "C912D09B020111" - }, - { - "30820120300D06092A864886F70D01010105000382010D00308201080282010100CAF26C09B1F6F056F66B54AA0EA002EA2361513A721A58E4" - "4472ADE74DBD833890ED9EE8E0CFF1B84C3DFE9E6226C8CEBFFEDFE71A6BCFE5A599D02FD9940997E864D400BF440BA7B1A568A5ACF7688B02" - "5B5B207E5651E597141FAEF733FA9D87732B8FBA31E082BE777AEB992B00873764655C3B1F8FBF8DD2446F4F9F79883E21DBC1A17431E42AF0" - "1B9D4DE54B9880E7FB397655C79D7C3A5981CA64A32E2F05FCF0B127F4C6D349056276992B7403D36E03D14C45B6F5F66786280C921236A17E" - "E0F311821BDF925A47DCA590BB31C60646692014317BE0DD32248DF557A77F80F336C82461B659266F74F495BA5CE194043505B5F0C363263B" - "F73BB897020111" - }, - { - "30820120300D06092A864886F70D01010105000382010D00308201080282010100DA68B2830103028D0ECD911D20E732257F8A39BC5214B670" - "C8F1F836CD1D88E6421ABD3C47F16E37E07DCFE89FC11ECBED73896FC978B7E1519F59318F3E24BB5C8962B0EA44889C3A81021CC9E8EAA940" - "99B9305B0F7731C27CC528CFEE710066CB69229F8AA04DBD842FA8C3143CB0EF1164E45E34B114FBA610DBDFC7453DAD995743AD1489AA131D" - "0C730163ECA7317048C1AD1008ED31A32CB773D94B5317CAAF95674582DCA1AC9FEBE02079836B52E1E3C8D39571018A7657650D52D2DF3363" - "F88A690628D64DCBECB88BBA432F27C32E7BC5BC0F1D16D0A027D1D40362F8CEDBE8BED05C2BCE96F33A75CD70014626B32E5EE81EBD3116F6" - "F1E5231B020111" - }, - { - "30820120300D06092A864886F70D01010105000382010D00308201080282010100B4D984129ECC2F4350596DD602EB5337B78E33C4D945C70C" - "2CACFF6237037BEF897D6893079D1067F07FF023D66C77BB41F6D41215C9912D995215C6F7651F1728AAB65CF20CBE81E5E7F202E474AF535E" - "92BBC386A7A496263BC4189FD9DD5E801C3023038EFE5B5DE35AA3F70C10F87259D586C36D3DF524E9DA2140C481365985AD185E1CF3E78B6B" - "82FDD274CCD1267838A0B91F9B48544AFB2C71B158A26E6154CECB43ECEE13FFBD6CA91D8D115B6B91C55F3A88E3F389E9A2AF4BC381D21F9A" - "BF2EA16F58773514249B03A4775C6A10561AFC8CF54B551A43FD014F3C5FE12D96AC5F117645E26D125DC7430114FA60577BF7C9AA1224D190" - "B2D8A83B020111" - }, - { - "30820120300D06092A864886F70D01010105000382010D00308201080282010100B4D984129ECC2F4350596DD602EB5337B78E33C4D945C70C" - "2CACFF6237037BEF897D6893079D1067F07FF023D66C77BB41F6D41215C9912D995215C6F7651F1728AAB65CF20CBE81E5E7F202E474AF535E" - "92BBC386A7A496263BC4189FD9DD5E801C3023038EFE5B5DE35AA3F70C10F87259D586C36D3DF524E9DA2140C481365985AD185E1CF3E78B6B" - "82FDD274CCD1267838A0B91F9B48544AFB2C71B158A26E6154CECB43ECEE13FFBD6CA91D8D115B6B91C55F3A88E3F389E9A2AF4BC381D21F9A" - "BF2EA16F58773514249B03A4775C6A10561AFC8CF54B551A43FD014F3C5FE12D96AC5F117645E26D125DC7430114FA60577BF7C9AA1224D190" - "B2D8A83B020111" - } +unordered_map replicaRSAPrivKeys = { + {replica_0, "308204BA020100300D06092A864886F70D0101010500048204A4308204A00201000282010100C55B8F7979BF24B335017082BF33EE2960E3A0" + "68DCDB45CA3017214BFB3F32649400A2484E2108C7CD07AA7616290667AF7C7A1922C82B51CA01867EED9B60A57F5B6EE33783EC258B234748" + "8B0FA3F99B05CFFBB45F80960669594B58C993D07B94D9A89ED8266D9931EAE70BB5E9063DEA9EFAF744393DCD92F2F5054624AA048C7EE50B" + "EF374FCDCE1C8CEBCA1EF12AF492402A6F56DC9338834162F3773B119145BF4B72672E0CF2C7009EBC3D593DFE3715D942CA8749771B484F72" + "A2BC8C89F86DB52ECC40763B6298879DE686C9A2A78604A503609BA34B779C4F55E3BEB0C26B1F84D8FC4EB3C79693B25A77A158EF88292D4C" + "01F99EFE3CC912D09B020111028201001D05EF73BF149474B4F8AEA9D0D2EE5161126A69C6203EF8162184E586D4967833E1F9BF56C89F68AD" + "35D54D99D8DB4B7BB06C4EFD95E840BBD30C3FD7A5E890CEF6DB99E284576EEED07B6C8CEBB63B4B80DAD2311D1A706A5AC95DE768F017213B" + "896B9EE38D2E3C2CFCE5BDF51ABD27391761245CDB3DCB686F05EA2FF654FA91F89DA699F14ACFA7F0D8030F74DBFEC28D55C902A27E9C03AB" + "1CA2770EFC5BE541560D86FA376B1A688D92124496BB3E7A3B78A86EBF1B694683CDB32BC49431990A18B570C104E47AC6B0DE5616851F4309" + "CFE7D0E20B17C154A3D85F33C7791451FFF73BFC4CDC8C16387D184F42AD2A31FCF545C3F9A498FAAC6E94E902818100F40CF9152ED4854E1B" + "BF67C5EA185C52EBEA0C11875563AEE95037C2E61C8D988DDF71588A0B45C23979C5FBFD2C45F9416775E0A644CAD46792296FDC68A98148F7" + "BD3164D9A5E0D6A0C2DF0141D82D610D56CB7C53F3C674771ED9ED77C0B5BF3C936498218176DC9933F1215BC831E0D41285611F512F68327E" + "4FBD9E5C5902818100CF05519FD69D7C6B61324F0A201574C647792B80E5D4D56A51CF5988927A1D54DF9AE4EA656AE25961923A0EC046F1C5" + "69BAB53A64EB0E9F5AB2ABF1C9146935BA40F75E0EB68E0BE4BC29A5A0742B59DF5A55AB028F1CCC42243D2AEE4B74344CA33E72879EF2D1CD" + "D874A7F237202AC7EB57AEDCBD539DEFDA094476EAE613028180396C76D7CEC897D624A581D43714CA6DDD2802D6F2AAAE0B09B885974533E5" + "14D6167505C620C51EA41CA70E1D73D43AA5FA39DA81799922EB3173296109914B98B2C31AAE515434E734E28ED31E8D37DA99BA11C2E693B6" + "398570ABBF6778A33C0E40CC6007E23A15C9B1DE6233B6A25304B91053166D7490FCD26D1D8EAC5102818079C6E4B86020674E392CA6F6E5B2" + "44B0DEBFBF3CC36E232F7B6AE95F6538C5F5B0B57798F05CFD9DFD28D6DB8029BB6511046A9AD1F3AE3F9EC37433DFB1A74CC7E9FAEC08A79E" + "D9D1D8187F8B8FA107B08F7DAFE3633E1DCC8DC9A0C8689EB55A41E87F9B12347B6A06DB359D89D6AFC0E4CA2A9FF6E5E46EF8BA2845F39665" + "0281802A89B2BD4A665A0F07DCAFA6D9DB7669B1D1276FC3365173A53F0E0D5F9CB9C3E08E68503C62EA73EB8E0DA42CCF6B136BF4A85B0AC4" + "24730B4F3CAD8C31D34DD75EF2A39B6BCFE3985CCECC470CF479CF0E9B9D6C7CE1C6C70D853728925326A22352DF73B502D4D3CBC2A770DE27" + "6E1C5953DF7A9614C970C94D194CAE9188"}, + {replica_1, "308204BC020100300D06092A864886F70D0101010500048204A6308204A20201000282010100CAF26C09B1F6F056F66B54AA0EA002EA236151" + "3A721A58E44472ADE74DBD833890ED9EE8E0CFF1B84C3DFE9E6226C8CEBFFEDFE71A6BCFE5A599D02FD9940997E864D400BF440BA7B1A568A5" + "ACF7688B025B5B207E5651E597141FAEF733FA9D87732B8FBA31E082BE777AEB992B00873764655C3B1F8FBF8DD2446F4F9F79883E21DBC1A1" + "7431E42AF01B9D4DE54B9880E7FB397655C79D7C3A5981CA64A32E2F05FCF0B127F4C6D349056276992B7403D36E03D14C45B6F5F66786280C" + "921236A17EE0F311821BDF925A47DCA590BB31C60646692014317BE0DD32248DF557A77F80F336C82461B659266F74F495BA5CE194043505B5" + "F0C363263BF73BB897020111028201005F8123C853BF8028EC6EBE6E2500015F1FB55366CC48A24D4D6324A915865BDE6251B4315ABC3583E7" + "A4B40E4C4E7C9D8786FFF448AB34A84DEE079E0C096DED221154B50EB69C12ADF37C8A334740416A85580F4A82F95CFBCD3C1619FA57D1A927" + "238EEE3596D41D656705754169A90B021194D08752B47EF9899DCB1DDED5DCDDA688D9FA88F9303E99CAB040D2E47DCE866717580C2CD01DB9" + "4E8FE215EAA254432E3B399B90260255DEE7FADED4643814C0DE41DE237BBB7173CFF16AC9237AADA4595FD95EB92E30D2127C7761C6A1CD75" + "C1F12F5B92B6602E1CDC06E112321B0A41C8A102D785B7C4C7D2441DA983346B81873984DD680FB4B1C9AD7102818100D5E41BE52CECFB7405" + "01B87C631DEFB3DD855EE95553A816BE8D3DFAE200086E1C12E9FBDDD8737F2CCE2CED1D82431ADC63C1B34EA59C27E98283EB20EAF8F5A29D" + "45ACE2E5C3173F396DF4356D54F3ED0CF9BBA222E3B9194CD15F88B6AB8FAFDFACACCC97D87555CD1E864D09DF795FB8BE3F9BE2CB8E52F641" + "FCEDC8E97902818100F2E6BDF9A552D35E9F695C52343D9BBF180BBEB50F6705A7836DF1BFF6A42C2D7A000432957516B555B5E1FBAC21CED5" + "D2788036AA5AB183A5859284ED409631289F8836D240111B56D6C4953FEFBE177EA137F08ADCABD5CAD07F709E83BB29B0F55AD09E65F5C656" + "8FE166FF4BE581F4F2066025E3902819EFC2DF0FA63E8F0281803EE8BCE90D36A44F4CC44551C2CC91CB7D637644A0A022610ADE3F67E81E20" + "98DB149F2BF5F45E347696FE279F446E16F586C080081297570871AE5436DBB2A2993D50BA60DA2A5221A77AB13CE3EBCF45B885AFA8286118" + "52BC3D94919F23667F058D23C3B4309AFB1E36278011F66EFE0928E58833A547FA486DC2DC8662C902818100AB75B346CF0D49E870869B8552" + "0D5EE13E26687FCEA3130CD53E8C8780EC5B6B652D3023B4CB1F1696DABDA2979F64D32B27E208784004D565C7B2B82F006A0495255117A378" + "848BC4D3D60EFFF4862EB3BD186D8F325B2D801AB44F7EF3932C7CE96D47F75707D74C2953D03BBD1A79DA1440BC56FAFC588AC75C6138391D" + "1902818100BBC05F561AEF4BDE1ECABB5CD313E6173F5E46AC85B4462A8CA689E4E84B95E66733081518DB01714B7B18E44B780DB5A6DA2612" + "506F46E4D91C8CB582AFD54C7509C9947EC754BFDD0D35FAECE2E729DBD21A62E33C3DEF556913ECF4C8D75910E860D36AFD0977FF9114ACEA" + "8F44882259C6F1D8314B653F64F4655CFD68A6"}, + {replica_2, "308204BA020100300D06092A864886F70D0101010500048204A4308204A00201000282010100DA68B2830103028D0ECD911D20E732257F8A39" + "BC5214B670C8F1F836CD1D88E6421ABD3C47F16E37E07DCFE89FC11ECBED73896FC978B7E1519F59318F3E24BB5C8962B0EA44889C3A81021C" + "C9E8EAA94099B9305B0F7731C27CC528CFEE710066CB69229F8AA04DBD842FA8C3143CB0EF1164E45E34B114FBA610DBDFC7453DAD995743AD" + "1489AA131D0C730163ECA7317048C1AD1008ED31A32CB773D94B5317CAAF95674582DCA1AC9FEBE02079836B52E1E3C8D39571018A7657650D" + "52D2DF3363F88A690628D64DCBECB88BBA432F27C32E7BC5BC0F1D16D0A027D1D40362F8CEDBE8BED05C2BCE96F33A75CD70014626B32E5EE8" + "1EBD3116F6F1E5231B02011102820100201E749ACB716241EB96B375398B6941BFEEAE23393F480186F668444B572AB873220CC519A3812655" + "B8261AAE14DEE1C1097617F7FB2A199B0FE7783AB650B22432524731828C8F7203E9B8F08422824D43C868FE55190ED8D61CFE78EE5BE97887" + "5339CC2AF974D81AF7F32BBF361A050A165DD19E5646D9B68A02377F2FD417BE92D2722CEE33B3A0F7B111639C092B4024BB08ACEBE9F9BC28" + "C14BB611DBE627136B568493C6995D81442F09DFEFBA4378A34DEF28F3BD862F4C28BECA87A95551FC2DB48766F82752C7E8B34E8599590190" + "B12A648AC1E361FE28A3253EC615381A066BFD351C18F0B236429A950106DD4F1134A3DE6CEB1094B7CE5C7102818100EA51580294BB0FD7DA" + "FDC00364A9B3C4781F70C4BBE8BDE0D82895ADE549E25388E78A53EF83CF9A3D9528F70CB5A57A9A187D5AC68682F03B26C2F6A409E1554FED" + "061BDC944985102F2988A5A8CD639BA7890FD689D7171612159AAA818F5502EF80D5D13339826A98914A321B5B4512EC24AF3EE80F982D3418" + "0C85B3E38102818100EE9E7F43A98E593F72A584EEC014E0A46003116B82F5D3A21DAE4EB3F21FBC5B71D96E012B6F5FFBEACED4BEC6C147AA" + "AB6F9698F0592F3A8A6CD827ABF210497635639043D5F0B461E00914B152D6ECB3EFC9138A1B9FAEE09420AB9C2E1436B6AC36EEB8AD43709B" + "BFA0ED30FBF09C1A91BAB71410E49E11BE8E2A571C649B02818044EABF8849DCAA4E8BB40B4C4AC8802AB9EB212ACDDB0AAB8ADEC29C8EBB60" + "AF284419A0376300D3030DC0C121DB128D789DCA841C45AE0A6BC01B397B8A6F7371DC4D1740E051DBD79566919A2296C2F18BA0C86C46A8AC" + "6FE73387D7CBC0BEA682AD6C105A5C356AA557E8A553571450DC0ACA218F8C1DB2F1343FEB16CA71028180704A963DF57029FFBD7B11614B55" + "1E6B7879EA1479DD184C4A33E8CD26A585D0AE0BF7881470A5A3B9CABE77E50FA941419DEC8434DEACD04124297C14AE25C837A0A752F2BF07" + "DC6A4B4F91446337F6EB43A9EB13D0C39D96DC4B9C0D42DC55FB9C5615FC8DC5622B2D006F9E94AD76A31766ECBE26113B53A4F79B744998C1" + "028180124E2A5DAC7AC7017647FE1B6871484B7B38A3C060B992B871939C8A75BC35DB771F041910C0092E01B545E1910109AA827F34F56327" + "15E06819ADED60117FD8B9400C3F307EA022D5AC5394E65D28EF434DC068494D33ACF70B43791C1C13C35AC680E0038DB411ADEBBC067F477E" + "01E8CF793FB076AE47BD83B935B8041DC1"}, + {replica_3, "308204BB020100300D06092A864886F70D0101010500048204A5308204A10201000282010100B4D984129ECC2F4350596DD602EB5337B78E33" + "C4D945C70C2CACFF6237037BEF897D6893079D1067F07FF023D66C77BB41F6D41215C9912D995215C6F7651F1728AAB65CF20CBE81E5E7F202" + "E474AF535E92BBC386A7A496263BC4189FD9DD5E801C3023038EFE5B5DE35AA3F70C10F87259D586C36D3DF524E9DA2140C481365985AD185E" + "1CF3E78B6B82FDD274CCD1267838A0B91F9B48544AFB2C71B158A26E6154CECB43ECEE13FFBD6CA91D8D115B6B91C55F3A88E3F389E9A2AF4B" + "C381D21F9ABF2EA16F58773514249B03A4775C6A10561AFC8CF54B551A43FD014F3C5FE12D96AC5F117645E26D125DC7430114FA60577BF7C9" + "AA1224D190B2D8A83B020111028201004FC95FEA18E19C6176459256E32B95A7A3CDCB8B8D08322B04A6ACE790BDC5BC806C087D19F2782DDB" + "0B444C0BC6710ED9564E8073061A66F0D163F5E59D8DB764C3C8ECC523BD758B13815BA1064D597C8C078AF7A450241FED30DDAFEF2CF4FC48" + "ABD336469D648B4DB70C1A2AF86D9BDC56AC6546C882BD763A963329844BF0E8C79E5E7A5C227A1CDB8473965090084BEAC728E4F86670BAE0" + "5DA589FAE1EBC98A26BF207261EECE5A92759DE516306B0B2F715370586EF45447F82CC37206F70D762AAB75215482A67FE6742E9D644AB765" + "4F02476EAE15A742FCB2266DAE437DC76FB17E1698D4987945C779A4B89F5FB3F5E1B194EFA4024BA3797F2502818100E2BDA6F0031EAA027B" + "1E8099D9D2CF408B8C9D83A22BFBAAD3BCFA952469A001C25E5E2E89DAF28636633E8D7C5E1E5FD8384767DB5B384DAB38147EA46871D5E31E" + "DC110026E42E90C44F02110A369ACF0445C617CC25CD1207F116B9AF2FA78A89E6C6345EAFD0607CB145410DD6619AC0C034B54283A0065B93" + "3550B8DACF02818100CC2FDB49EB3E45DB2EB644048C3C35E3BB50980453DB8EB54DD5595CA2DBC43A2F2912D0F696E6126AFBF5D7777BABB2" + "6AC931030B8896343BC19EA30B8EEBFECE2617A2564B3D66E29DF66708254877CC33E699501A2BA4D0D7D02F068B1DCF6C7A0794F24BEE83BE" + "2E8453D3E436C3B59D2D9BEEB5B38541EF170544EA46D502818100AD63DA02D5359110F4BCF8EE1F0A9E7CA6F30F0A4ED6570A29726544DF9C" + "10F2495738F6696B31EE29972FD59B57082B2CDFBE223E54D0B3DD49009D144FDE94808102A396B454239BE169982B25ED85712162886C8D0D" + "D90DC9D67ACA3AABF8971E28F1EBCFEFDB95140F16D764EF3B947547AFD5E791D4B9915274108D5C07028180300B42A7FB1DB61574671F1020" + "FF1BBD1D03E7888C33A91B99D7D8CA80AC2E2BCEDC7CE5DFAB08F546596705858682C09198C03CF3A7AADF1D1E7FADE49A196921725FE9F62F" + "D236537076365C4501FE11EE182412D8FB35D6C95E292EB7524EEC58F2B9A26C381EFF92797D22CC491EFD8E6515A1942A3D78ECF65B97BEA7" + "410281806625E51F70BB9E00D0260941C56B22CDCECC7EA6DBC2C28A1CDA0E1AFAACD39C5E962E40FCFC0F5BBA57A7291A1BDC5D3D29495B45" + "CE2B3BEC7748E6C351FF934537BCA246CA36B840CF68BE6D473F7EE079B0EFDFF6B1BB554B06093E18B269FC3BD3F9876376CA7C673A93F142" + "7088BF0990AB8E232F269B5DBCD446385A66"}, + {replica_4, "308204BB020100300D06092A864886F70D0101010500048204A5308204A10201000282010100B4D984129ECC2F4350596DD602EB5337B78E33" + "C4D945C70C2CACFF6237037BEF897D6893079D1067F07FF023D66C77BB41F6D41215C9912D995215C6F7651F1728AAB65CF20CBE81E5E7F202" + "E474AF535E92BBC386A7A496263BC4189FD9DD5E801C3023038EFE5B5DE35AA3F70C10F87259D586C36D3DF524E9DA2140C481365985AD185E" + "1CF3E78B6B82FDD274CCD1267838A0B91F9B48544AFB2C71B158A26E6154CECB43ECEE13FFBD6CA91D8D115B6B91C55F3A88E3F389E9A2AF4B" + "C381D21F9ABF2EA16F58773514249B03A4775C6A10561AFC8CF54B551A43FD014F3C5FE12D96AC5F117645E26D125DC7430114FA60577BF7C9" + "AA1224D190B2D8A83B020111028201004FC95FEA18E19C6176459256E32B95A7A3CDCB8B8D08322B04A6ACE790BDC5BC806C087D19F2782DDB" + "0B444C0BC6710ED9564E8073061A66F0D163F5E59D8DB764C3C8ECC523BD758B13815BA1064D597C8C078AF7A450241FED30DDAFEF2CF4FC48" + "ABD336469D648B4DB70C1A2AF86D9BDC56AC6546C882BD763A963329844BF0E8C79E5E7A5C227A1CDB8473965090084BEAC728E4F86670BAE0" + "5DA589FAE1EBC98A26BF207261EECE5A92759DE516306B0B2F715370586EF45447F82CC37206F70D762AAB75215482A67FE6742E9D644AB765" + "4F02476EAE15A742FCB2266DAE437DC76FB17E1698D4987945C779A4B89F5FB3F5E1B194EFA4024BA3797F2502818100E2BDA6F0031EAA027B" + "1E8099D9D2CF408B8C9D83A22BFBAAD3BCFA952469A001C25E5E2E89DAF28636633E8D7C5E1E5FD8384767DB5B384DAB38147EA46871D5E31E" + "DC110026E42E90C44F02110A369ACF0445C617CC25CD1207F116B9AF2FA78A89E6C6345EAFD0607CB145410DD6619AC0C034B54283A0065B93" + "3550B8DACF02818100CC2FDB49EB3E45DB2EB644048C3C35E3BB50980453DB8EB54DD5595CA2DBC43A2F2912D0F696E6126AFBF5D7777BABB2" + "6AC931030B8896343BC19EA30B8EEBFECE2617A2564B3D66E29DF66708254877CC33E699501A2BA4D0D7D02F068B1DCF6C7A0794F24BEE83BE" + "2E8453D3E436C3B59D2D9BEEB5B38541EF170544EA46D502818100AD63DA02D5359110F4BCF8EE1F0A9E7CA6F30F0A4ED6570A29726544DF9C" + "10F2495738F6696B31EE29972FD59B57082B2CDFBE223E54D0B3DD49009D144FDE94808102A396B454239BE169982B25ED85712162886C8D0D" + "D90DC9D67ACA3AABF8971E28F1EBCFEFDB95140F16D764EF3B947547AFD5E791D4B9915274108D5C07028180300B42A7FB1DB61574671F1020" + "FF1BBD1D03E7888C33A91B99D7D8CA80AC2E2BCEDC7CE5DFAB08F546596705858682C09198C03CF3A7AADF1D1E7FADE49A196921725FE9F62F" + "D236537076365C4501FE11EE182412D8FB35D6C95E292EB7524EEC58F2B9A26C381EFF92797D22CC491EFD8E6515A1942A3D78ECF65B97BEA7" + "410281806625E51F70BB9E00D0260941C56B22CDCECC7EA6DBC2C28A1CDA0E1AFAACD39C5E962E40FCFC0F5BBA57A7291A1BDC5D3D29495B45" + "CE2B3BEC7748E6C351FF934537BCA246CA36B840CF68BE6D473F7EE079B0EFDFF6B1BB554B06093E18B269FC3BD3F9876376CA7C673A93F142" + "7088BF0990AB8E232F269B5DBCD446385A66"} +}; + +unordered_map replicaRSAPubKeys = { + {replica_0, "30820120300D06092A864886F70D01010105000382010D00308201080282010100C55B8F7979BF24B335017082BF33EE2960E3A068DCDB45CA" + "3017214BFB3F32649400A2484E2108C7CD07AA7616290667AF7C7A1922C82B51CA01867EED9B60A57F5B6EE33783EC258B2347488B0FA3F99B" + "05CFFBB45F80960669594B58C993D07B94D9A89ED8266D9931EAE70BB5E9063DEA9EFAF744393DCD92F2F5054624AA048C7EE50BEF374FCDCE" + "1C8CEBCA1EF12AF492402A6F56DC9338834162F3773B119145BF4B72672E0CF2C7009EBC3D593DFE3715D942CA8749771B484F72A2BC8C89F8" + "6DB52ECC40763B6298879DE686C9A2A78604A503609BA34B779C4F55E3BEB0C26B1F84D8FC4EB3C79693B25A77A158EF88292D4C01F99EFE3C" + "C912D09B020111"}, + {replica_1, "30820120300D06092A864886F70D01010105000382010D00308201080282010100CAF26C09B1F6F056F66B54AA0EA002EA2361513A721A58E4" + "4472ADE74DBD833890ED9EE8E0CFF1B84C3DFE9E6226C8CEBFFEDFE71A6BCFE5A599D02FD9940997E864D400BF440BA7B1A568A5ACF7688B02" + "5B5B207E5651E597141FAEF733FA9D87732B8FBA31E082BE777AEB992B00873764655C3B1F8FBF8DD2446F4F9F79883E21DBC1A17431E42AF0" + "1B9D4DE54B9880E7FB397655C79D7C3A5981CA64A32E2F05FCF0B127F4C6D349056276992B7403D36E03D14C45B6F5F66786280C921236A17E" + "E0F311821BDF925A47DCA590BB31C60646692014317BE0DD32248DF557A77F80F336C82461B659266F74F495BA5CE194043505B5F0C363263B" + "F73BB897020111"}, + {replica_2, "30820120300D06092A864886F70D01010105000382010D00308201080282010100DA68B2830103028D0ECD911D20E732257F8A39BC5214B670" + "C8F1F836CD1D88E6421ABD3C47F16E37E07DCFE89FC11ECBED73896FC978B7E1519F59318F3E24BB5C8962B0EA44889C3A81021CC9E8EAA940" + "99B9305B0F7731C27CC528CFEE710066CB69229F8AA04DBD842FA8C3143CB0EF1164E45E34B114FBA610DBDFC7453DAD995743AD1489AA131D" + "0C730163ECA7317048C1AD1008ED31A32CB773D94B5317CAAF95674582DCA1AC9FEBE02079836B52E1E3C8D39571018A7657650D52D2DF3363" + "F88A690628D64DCBECB88BBA432F27C32E7BC5BC0F1D16D0A027D1D40362F8CEDBE8BED05C2BCE96F33A75CD70014626B32E5EE81EBD3116F6" + "F1E5231B020111"}, + {replica_3, "30820120300D06092A864886F70D01010105000382010D00308201080282010100B4D984129ECC2F4350596DD602EB5337B78E33C4D945C70C" + "2CACFF6237037BEF897D6893079D1067F07FF023D66C77BB41F6D41215C9912D995215C6F7651F1728AAB65CF20CBE81E5E7F202E474AF535E" + "92BBC386A7A496263BC4189FD9DD5E801C3023038EFE5B5DE35AA3F70C10F87259D586C36D3DF524E9DA2140C481365985AD185E1CF3E78B6B" + "82FDD274CCD1267838A0B91F9B48544AFB2C71B158A26E6154CECB43ECEE13FFBD6CA91D8D115B6B91C55F3A88E3F389E9A2AF4BC381D21F9A" + "BF2EA16F58773514249B03A4775C6A10561AFC8CF54B551A43FD014F3C5FE12D96AC5F117645E26D125DC7430114FA60577BF7C9AA1224D190" + "B2D8A83B020111"}, + {replica_4, "30820120300D06092A864886F70D01010105000382010D00308201080282010100B4D984129ECC2F4350596DD602EB5337B78E33C4D945C70C" + "2CACFF6237037BEF897D6893079D1067F07FF023D66C77BB41F6D41215C9912D995215C6F7651F1728AAB65CF20CBE81E5E7F202E474AF535E" + "92BBC386A7A496263BC4189FD9DD5E801C3023038EFE5B5DE35AA3F70C10F87259D586C36D3DF524E9DA2140C481365985AD185E1CF3E78B6B" + "82FDD274CCD1267838A0B91F9B48544AFB2C71B158A26E6154CECB43ECEE13FFBD6CA91D8D115B6B91C55F3A88E3F389E9A2AF4BC381D21F9A" + "BF2EA16F58773514249B03A4775C6A10561AFC8CF54B551A43FD014F3C5FE12D96AC5F117645E26D125DC7430114FA60577BF7C9AA1224D190" + "B2D8A83B020111"}, + {replica_5, "30820120300D06092A864886F70D01010105000382010D00308201080282010100B4D984129ECC2F4350596DD602EB5337B78E33C4D945C70C" + "2CACFF6237037BEF897D6893079D1067F07FF023D66C77BB41F6D41215C9912D995215C6F7651F1728AAB65CF20CBE81E5E7F202E474AF535E" + "92BBC386A7A496263BC4189FD9DD5E801C3023038EFE5B5DE35AA3F70C10F87259D586C36D3DF524E9DA2140C481365985AD185E1CF3E78B6B" + "82FDD274CCD1267838A0B91F9B48544AFB2C71B158A26E6154CECB43ECEE13FFBD6CA91D8D115B6B91C55F3A88E3F389E9A2AF4BC381D21F9A" + "BF2EA16F58773514249B03A4775C6A10561AFC8CF54B551A43FD014F3C5FE12D96AC5F117645E26D125DC7430114FA60577BF7C9AA1224D190" + "B2D8A83B020111"} +}; + +unordered_map replicaEdDSAPrivKeys = { + {replica_0, "61498efe1764b89357a02e2887d224154006ceacf26269f8695a4af561453eef"}, + {replica_1, "247a74ab3620ec6b9f5feab9ee1f86521da3fa2804ad45bb5bf2c5b21ef105bc"}, + {replica_2, "fb539bc3d66deda55524d903da26dbec1f4b6abf41ec5db521e617c64eb2c341"}, + {replica_3, "55ea66e855b83ec4a02bd8fcce6bb4426ad3db2a842fa2a2a6777f13e40a4717"}, + {replica_4, "f2f3d43da68329bfe31419636072e27cfd1a8fff259be4bfada667080eb00556"} +}; + +unordered_map replicaEdDSAPubKeys = { + {replica_0, "386f4fb049a5d8bb0706d3793096c8f91842ce380dfc342a2001d50dfbc901f4"}, + {replica_1, "3f9e7dbde90477c24c1bacf14e073a356c1eca482d352d9cc0b16560a4e7e469"}, + {replica_2, "2311c6013ff657844669d8b803b2e1ed33fe06eed445f966a800a8fbb8d790e8"}, + {replica_3, "1ba7449655784fc9ce193a7887de1e4d3d35f7c82b802440c4f28bf678a34b34"}, + {replica_4, "c426c524c92ad9d0b740f68ee312abf0298051a7e0364a867b940e9693ae6095"} }; // clang-format on +unordered_map replicaPrivKeys; +unordered_map replicaPubKeys; + void setUpConfiguration_4() { replicaConfig.replicaId = replica_0; replicaConfig.numReplicas = numOfReplicas_4; @@ -332,21 +340,20 @@ void setUpConfiguration_4() { replicaConfig.numOfExternalClients = 15; replicaConfig.clientBatchingEnabled = true; - replicaConfig.publicKeysOfReplicas.insert(pair(replica_0, publicKeys[replica_0])); - replicaConfig.publicKeysOfReplicas.insert(pair(replica_1, publicKeys[replica_1])); - replicaConfig.publicKeysOfReplicas.insert(pair(replica_2, publicKeys[replica_2])); - replicaConfig.publicKeysOfReplicas.insert(pair(replica_3, publicKeys[replica_3])); - replicaConfig.replicaPrivateKey = privateKeys[0]; + for (NodeIdType i = replica_0; i <= replica_3; ++i) { + replicaConfig.publicKeysOfReplicas.insert(pair(i, replicaPubKeys[i])); + } + replicaConfig.replicaPrivateKey = replicaPrivKeys[replica_0]; for (auto i = 0; i < replicaConfig.numReplicas; i++) { replicaConfig.replicaId = i; replicasInfo[i] = std::make_unique(replicaConfig, true, true); sigManager[i].reset(SigManager::initInTesting(i, - privateKeys[i], + replicaPrivKeys[i], replicaConfig.publicKeysOfReplicas, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, nullptr, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, *replicasInfo[i].get())); } replicaConfig.replicaId = replica_0; @@ -358,8 +365,8 @@ void setUpConfiguration_7() { replicaConfig.numReplicas = numOfReplicas_7; replicaConfig.fVal = fVal_7; - replicaConfig.publicKeysOfReplicas.insert(pair(replica_4, publicKeys[4])); - replicaConfig.replicaPrivateKey = privateKeys[4]; + replicaConfig.publicKeysOfReplicas.insert(pair(replica_4, replicaPubKeys[replica_4])); + replicaConfig.replicaPrivateKey = replicaPrivKeys[replica_4]; } void setUpCommunication() { @@ -1042,6 +1049,14 @@ TEST(requestPreprocessingState_test, rejectMsgWithInvalidView) { int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); logging::initLogger("logging.properties"); + + if (replicaConfig.replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + replicaPrivKeys = replicaRSAPrivKeys; + replicaPubKeys = replicaRSAPubKeys; + } else if (replicaConfig.replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + replicaPrivKeys = replicaEdDSAPrivKeys; + replicaPubKeys = replicaEdDSAPubKeys; + } setUpConfiguration_4(); RequestProcessingState::init(numOfRequiredReplies, &preProcessorRecorder); PreProcessReplyMsg::setPreProcessorHistograms(&preProcessorRecorder); diff --git a/bftengine/tests/SigManager/SigManager_test.cpp b/bftengine/tests/SigManager/SigManager_test.cpp index 50759adae0..8379b12ada 100644 --- a/bftengine/tests/SigManager/SigManager_test.cpp +++ b/bftengine/tests/SigManager/SigManager_test.cpp @@ -12,20 +12,18 @@ #include "SigManager.hpp" #include "helper.hpp" +#include #include #include #include #include #include #include "gtest/gtest.h" - -#include -#include -#include -#include -#include +#include "crypto/factory.hpp" +#include "crypto.hpp" using namespace std; +using concord::crypto::KeyFormat; constexpr char KEYS_BASE_PARENT_PATH[] = "/tmp/"; constexpr char KEYS_BASE_PATH[] = "/tmp/transaction_signing_keys"; @@ -37,6 +35,13 @@ constexpr size_t RANDOM_DATA_SIZE = 1000U; std::default_random_engine generator; +using concord::crypto::ISigner; +using concord::crypto::IVerifier; +using concord::crypto::Factory; +using bftEngine::ReplicaConfig; +using concord::crypto::SIGN_VERIFY_ALGO; +using concord::crypto::generateEdDSAKeyPair; + void generateKeyPairs(size_t count) { ostringstream cmd; @@ -47,8 +52,14 @@ void generateKeyPairs(size_t count) { cmd.str(""); cmd.clear(); + std::string algo; + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + algo = "rsa"; + } else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + algo = "eddsa"; + } cmd << KEYS_GEN_SCRIPT_PATH << " -n " << count << " -r " << PRIV_KEY_NAME << " -u " << PUB_KEY_NAME << " -o " - << KEYS_BASE_PARENT_PATH; + << KEYS_BASE_PARENT_PATH << " -a " << algo; ASSERT_EQ(0, system(cmd.str().c_str())); } @@ -73,7 +84,42 @@ void corrupt(char* data, size_t len) { } } -TEST(RsaSignerAndRsaVerifierTest, LoadSignVerifyFromPemfiles) { +TEST(SignerAndVerifierTest, LoadSignVerifyFromHexKeyPair) { + char data[RANDOM_DATA_SIZE]{0}; + + const auto keyPair = generateEdDSAKeyPair(); + generateRandomData(data, RANDOM_DATA_SIZE); + + const auto signer_ = Factory::getSigner(keyPair.first, ReplicaConfig::instance().replicaMsgSigningAlgo); + const auto verifier_ = Factory::getVerifier(keyPair.second, ReplicaConfig::instance().replicaMsgSigningAlgo); + + // sign with RSASigner/EdDSASigner + std::string sig; + size_t expectedSignerSigLen = signer_->signatureLength(); + sig.reserve(expectedSignerSigLen); + size_t lenRetData; + std::string str_data(data, RANDOM_DATA_SIZE); + sig = signer_->sign(str_data); + lenRetData = sig.size(); + ASSERT_EQ(lenRetData, expectedSignerSigLen); + + // validate with RSAVerifier/EdDSAVerifier + ASSERT_TRUE(verifier_->verify(str_data, sig)); + + // change data randomally, expect failure + char data1[RANDOM_DATA_SIZE]; + std::copy(std::begin(data), std::end(data), std::begin(data1)); + corrupt(data1 + 10, 1); + std::string str_data1(data1, RANDOM_DATA_SIZE); + ASSERT_FALSE(verifier_->verify(str_data1, sig)); + + // change signature randomally, expect failure + corrupt(sig.data(), 1); + str_data = std::string(data, RANDOM_DATA_SIZE); + ASSERT_FALSE(verifier_->verify(str_data, sig)); +} + +TEST(SignerAndVerifierTest, LoadSignVerifyFromPemfiles) { string publicKeyFullPath({string(KEYS_BASE_PATH) + string("/1/") + PUB_KEY_NAME}); string privateKeyFullPath({string(KEYS_BASE_PATH) + string("/1/") + PRIV_KEY_NAME}); @@ -81,15 +127,17 @@ TEST(RsaSignerAndRsaVerifierTest, LoadSignVerifyFromPemfiles) { char data[RANDOM_DATA_SIZE]{0}; generateKeyPairs(1); + generateRandomData(data, RANDOM_DATA_SIZE); readFile(privateKeyFullPath, privKey); readFile(publicKeyFullPath, pubkey); - auto verifier_ = unique_ptr( - new concord::util::crypto::RSAVerifier(pubkey, concord::util::crypto::KeyFormat::PemFormat)); - auto signer_ = unique_ptr( - new concord::util::crypto::RSASigner(privKey, concord::util::crypto::KeyFormat::PemFormat)); - // sign with RSASigner + const auto signer_ = + Factory::getSigner(privKey, ReplicaConfig::instance().replicaMsgSigningAlgo, KeyFormat::PemFormat); + const auto verifier_ = + Factory::getVerifier(pubkey, ReplicaConfig::instance().replicaMsgSigningAlgo, KeyFormat::PemFormat); + + // sign with RSASigner/EdDSASigner size_t expectedSignerSigLen = signer_->signatureLength(); sig.reserve(expectedSignerSigLen); size_t lenRetData; @@ -98,7 +146,7 @@ TEST(RsaSignerAndRsaVerifierTest, LoadSignVerifyFromPemfiles) { lenRetData = sig.size(); ASSERT_EQ(lenRetData, expectedSignerSigLen); - // validate with RSAVerifier + // validate with RSAVerifier/EdDSAVerifier ASSERT_TRUE(verifier_->verify(str_data, sig)); // change data randomally, expect failure @@ -118,7 +166,7 @@ TEST(SigManagerTest, ReplicasOnlyCheckVerify) { constexpr size_t numReplicas{4}; constexpr PrincipalId myId{0}; string myPrivKey; - unique_ptr signers[numReplicas]; + unique_ptr signers[numReplicas]; set> publicKeysOfReplicas; generateKeyPairs(numReplicas); @@ -134,21 +182,15 @@ TEST(SigManagerTest, ReplicasOnlyCheckVerify) { myPrivKey = privKey; continue; } - - signers[pid].reset(new concord::util::crypto::RSASigner(privKey, concord::util::crypto::KeyFormat::PemFormat)); + signers[pid] = Factory::getSigner(privKey, ReplicaConfig::instance().replicaMsgSigningAlgo, KeyFormat::PemFormat); string pubKeyFullPath({string(KEYS_BASE_PATH) + string("/") + to_string(i) + string("/") + PUB_KEY_NAME}); readFile(pubKeyFullPath, pubKey); publicKeysOfReplicas.insert(make_pair(pid, pubKey)); } ReplicasInfo replicaInfo(createReplicaConfig(), false, false); - unique_ptr sigManager(SigManager::init(myId, - myPrivKey, - publicKeysOfReplicas, - concord::util::crypto::KeyFormat::PemFormat, - nullptr, - concord::util::crypto::KeyFormat::PemFormat, - replicaInfo)); + unique_ptr sigManager(SigManager::init( + myId, myPrivKey, publicKeysOfReplicas, KeyFormat::PemFormat, nullptr, KeyFormat::PemFormat, replicaInfo)); for (size_t i{0}; i < numReplicas; ++i) { const auto& signer = signers[i]; @@ -159,7 +201,7 @@ TEST(SigManagerTest, ReplicasOnlyCheckVerify) { if (i == myId) continue; - // sign with RSASigner (other replicas, mock) + // sign with RSASigner/EdDSASigner (other replicas, mock) expectedSignerSigLen = signer->signatureLength(); sig.reserve(expectedSignerSigLen); generateRandomData(data, RANDOM_DATA_SIZE); @@ -188,7 +230,7 @@ TEST(SigManagerTest, ReplicasOnlyCheckSign) { constexpr size_t numReplicas{4}; constexpr PrincipalId myId{0}; string myPrivKey, privKey, pubKey, sig; - unique_ptr verifier; + unique_ptr verifier; set> publicKeysOfReplicas; char data[RANDOM_DATA_SIZE]{0}; size_t expectedSignerSigLen; @@ -202,7 +244,8 @@ TEST(SigManagerTest, ReplicasOnlyCheckSign) { // Load single other replica's verifier (mock) string pubKeyFullPath({string(KEYS_BASE_PATH) + string("/") + to_string(1) + string("/") + PUB_KEY_NAME}); readFile(pubKeyFullPath, pubKey); - verifier.reset(new concord::util::crypto::RSAVerifier(pubKey, concord::util::crypto::KeyFormat::PemFormat)); + + verifier = Factory::getVerifier(pubKey, ReplicaConfig::instance().replicaMsgSigningAlgo, KeyFormat::PemFormat); // load public key of other replicas, must be done for SigManager ctor for (size_t i{2}; i <= numReplicas; ++i) { @@ -212,18 +255,13 @@ TEST(SigManagerTest, ReplicasOnlyCheckSign) { } ReplicasInfo replicaInfo(createReplicaConfig(), false, false); - unique_ptr sigManager(SigManager::init(myId, - myPrivKey, - publicKeysOfReplicas, - concord::util::crypto::KeyFormat::PemFormat, - nullptr, - concord::util::crypto::KeyFormat::PemFormat, - replicaInfo)); + unique_ptr sigManager(SigManager::init( + myId, myPrivKey, publicKeysOfReplicas, KeyFormat::PemFormat, nullptr, KeyFormat::PemFormat, replicaInfo)); // sign with SigManager expectedSignerSigLen = sigManager->getSigLength(myId); generateRandomData(data, RANDOM_DATA_SIZE); sig.resize(expectedSignerSigLen); - sigManager->sign(data, RANDOM_DATA_SIZE, sig.data(), expectedSignerSigLen); + sigManager->sign(data, RANDOM_DATA_SIZE, sig.data()); // Validate with RSAVerifier (mock) std::string str_data(data, RANDOM_DATA_SIZE); @@ -253,8 +291,8 @@ TEST(SigManagerTest, ReplicasAndClientsCheckVerify) { constexpr PrincipalId myId{0}; string myPrivKey; size_t i, signerIndex{0}; - unique_ptr - signers[numReplicas + numParticipantNodes]; // only external clients and consensus replicas sign + unique_ptr signers[numReplicas + numParticipantNodes]; // only external clients and consensus replicas sign + set> publicKeysOfReplicas; set>> publicKeysOfClients; unordered_map principalIdToSignerIndex; @@ -272,8 +310,9 @@ TEST(SigManagerTest, ReplicasAndClientsCheckVerify) { myPrivKey = privKey; continue; } - signers[signerIndex].reset( - new concord::util::crypto::RSASigner(privKey, concord::util::crypto::KeyFormat::PemFormat)); + signers[signerIndex] = + Factory::getSigner(privKey, ReplicaConfig::instance().replicaMsgSigningAlgo, KeyFormat::PemFormat); + string pubKeyFullPath({string(KEYS_BASE_PATH) + string("/") + to_string(i) + string("/") + PUB_KEY_NAME}); readFile(pubKeyFullPath, pubKey); publicKeysOfReplicas.insert(make_pair(currPrincipalId, pubKey)); @@ -287,10 +326,8 @@ TEST(SigManagerTest, ReplicasAndClientsCheckVerify) { string privKey, pubKey; string privateKeyFullPath({string(KEYS_BASE_PATH) + string("/") + to_string(i) + string("/") + PRIV_KEY_NAME}); readFile(privateKeyFullPath, privKey); - - signers[signerIndex].reset( - new concord::util::crypto::RSASigner(privKey, concord::util::crypto::KeyFormat::PemFormat)); - + signers[signerIndex] = + Factory::getSigner(privKey, ReplicaConfig::instance().replicaMsgSigningAlgo, KeyFormat::PemFormat); string pubKeyFullPath({string(KEYS_BASE_PATH) + string("/") + to_string(i) + string("/") + PUB_KEY_NAME}); set principalIds; for (size_t j{0}; j < numBftClientsInParticipantNodes; ++j) { @@ -313,9 +350,9 @@ TEST(SigManagerTest, ReplicasAndClientsCheckVerify) { unique_ptr sigManager(SigManager::init(myId, myPrivKey, publicKeysOfReplicas, - concord::util::crypto::KeyFormat::PemFormat, + KeyFormat::PemFormat, &publicKeysOfClients, - concord::util::crypto::KeyFormat::PemFormat, + KeyFormat::PemFormat, replicaInfo)); // principalIdToSignerIndex carries all principal ids for replica, read only replicas and bft-clients. @@ -334,9 +371,9 @@ TEST(SigManagerTest, ReplicasAndClientsCheckVerify) { PrincipalId signerPrincipalId = static_cast(distribution(generator)); auto iter = principalIdToSignerIndex.find(signerPrincipalId); - if (iter != principalIdToSignerIndex.end()) + if (iter != principalIdToSignerIndex.end()) { signerIndex = iter->second; - else { + } else { signerIndex = 1; // sign with signer index 1, so we can check the target SigManager expectFailure = true; } @@ -345,8 +382,8 @@ TEST(SigManagerTest, ReplicasAndClientsCheckVerify) { expectedSignerSigLen = signers[signerIndex]->signatureLength(); sig.reserve(expectedSignerSigLen); generateRandomData(data, RANDOM_DATA_SIZE); - std::string str_date(data, RANDOM_DATA_SIZE); - sig = signers[signerIndex]->sign(str_date); + std::string str_data(data, RANDOM_DATA_SIZE); + sig = signers[signerIndex]->sign(str_data); lenRetData = sig.size(); ASSERT_EQ(lenRetData, expectedSignerSigLen); diff --git a/bftengine/tests/bcstatetransfer/bcstatetransfer_tests.cpp b/bftengine/tests/bcstatetransfer/bcstatetransfer_tests.cpp index 3dce4de715..48f9b3889f 100644 --- a/bftengine/tests/bcstatetransfer/bcstatetransfer_tests.cpp +++ b/bftengine/tests/bcstatetransfer/bcstatetransfer_tests.cpp @@ -57,6 +57,7 @@ using namespace bftEngine::bcst; using namespace concord::util; using concord::util::digest::DigestGenerator; +using concord::util::digest::DigestGenerator; using std::chrono::milliseconds; using random_bytes_engine = std::independent_bits_engine; diff --git a/bftengine/tests/clientsManager/ClientsManager_test.cpp b/bftengine/tests/clientsManager/ClientsManager_test.cpp index 976540684a..2b50969d95 100644 --- a/bftengine/tests/clientsManager/ClientsManager_test.cpp +++ b/bftengine/tests/clientsManager/ClientsManager_test.cpp @@ -16,7 +16,10 @@ #include "gtest/gtest.h" #include "messages/ClientReplyMsg.hpp" #include "ReservedPagesMock.hpp" +#include "crypto/factory.hpp" +#include "crypto.hpp" +using concord::crypto::Factory; using bftEngine::impl::ClientsManager; using bftEngine::impl::NodeIdType; using bftEngine::impl::ReplicasInfo; @@ -24,9 +27,7 @@ using bftEngine::impl::SigManager; using bftEngine::ReplicaConfig; using bftEngine::ReservedPagesClientBase; using bftEngine::test::ReservedPagesMock; -using concord::util::crypto::Crypto; -using concord::util::crypto::KeyFormat; -using concord::util::crypto::RSASigner; +using concord::crypto::KeyFormat; using concord::secretsmanager::ISecretsManagerImpl; using concordUtil::Timers; using std::chrono::milliseconds; @@ -43,13 +44,16 @@ using std::this_thread::sleep_for; using std::unique_ptr; using std::vector; +using concord::crypto::cryptopp::RSA_SIGNATURE_LENGTH; +using concord::crypto::SIGN_VERIFY_ALGO; +using concord::crypto::generateRsaKeyPair; +using concord::crypto::generateEdDSAKeyPair; + // Testing values to be used for certain Concord-BFT configuration that ClientsManager and/or its dependencies may // reference. const ReplicaId kReplicaIdForTesting = 0; -const uint32_t kRSASigLengthForTesting = 2048; const KeyFormat kKeyFormatForTesting = KeyFormat::HexaDecimalStrippedFormat; -const SigManager::Key kReplicaPrivateKeyForTesting( - Crypto::instance().generateRsaKeyPair(kRSASigLengthForTesting, kKeyFormatForTesting).first); + const set> kPublicKeysOfReplicasForTesting{}; const set>> kInitialPublicKeysOfClientsForTesting; unique_ptr sigManagerReplicasInfoForTesting; @@ -144,6 +148,12 @@ static void setMockReservedPages(shared_ptr>& } static void resetSigManager() { + SigManager::Key kReplicaPrivateKeyForTesting; + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + kReplicaPrivateKeyForTesting = generateRsaKeyPair(RSA_SIGNATURE_LENGTH).first; + } else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + kReplicaPrivateKeyForTesting = generateEdDSAKeyPair().first; + } sig_manager_for_key_exchange_manager.reset(SigManager::init(kReplicaIdForTesting, kReplicaPrivateKeyForTesting, kPublicKeysOfReplicasForTesting, @@ -224,8 +234,9 @@ static bool verifyClientPublicKeyLoadedToKEM(NodeIdType client_id, const pairhasVerifier(client_id))) { return false; } - RSASigner signer(expected_key.first, kKeyFormatForTesting); - string signature = signer.sign(kArbitraryMessageForTestingKeyAgreement); + const auto signer = + Factory::getSigner(expected_key.first, ReplicaConfig::instance().replicaMsgSigningAlgo, kKeyFormatForTesting); + string signature = signer->sign(kArbitraryMessageForTestingKeyAgreement); return SigManager::instance()->verifySig(client_id, kArbitraryMessageForTestingKeyAgreement.data(), kArbitraryMessageForTestingKeyAgreement.length(), @@ -310,7 +321,12 @@ TEST(ClientsManager, loadInfoFromReservedPagesLoadsCorrectInfo) { set internal_client_ids{}; map> client_keys; - client_keys[2] = Crypto::instance().generateRsaKeyPair(kRSASigLengthForTesting, kKeyFormatForTesting); + + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + client_keys[2] = generateRsaKeyPair(RSA_SIGNATURE_LENGTH); + } else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + client_keys[2] = generateEdDSAKeyPair(); + } map> client_replies; client_replies[2] = {9, "reply 9 to client 2"}; @@ -428,8 +444,13 @@ TEST(ClientsManager, loadInfoFromReservedPagesHandlesNoInfoAvailable) { } TEST(ClientsManager, loadInfoFromReservedPagesHandlesSingleClientClientsManager) { - pair client_key_pair = - Crypto::instance().generateRsaKeyPair(kRSASigLengthForTesting, kKeyFormatForTesting); + pair client_key_pair; + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + client_key_pair = generateRsaKeyPair(RSA_SIGNATURE_LENGTH); + } else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + client_key_pair = generateEdDSAKeyPair(); + } + string reply_message = "reply 1 to client 2"; resetMockReservedPages(); @@ -1305,10 +1326,16 @@ TEST(ClientsManager, isInternal) { TEST(ClientsManager, setClientPublicKey) { resetMockReservedPages(); map> client_keys; - pair client_2_key = - Crypto::instance().generateRsaKeyPair(kRSASigLengthForTesting, kKeyFormatForTesting); - pair client_7_key = - Crypto::instance().generateRsaKeyPair(kRSASigLengthForTesting, kKeyFormatForTesting); + + pair client_2_key; + pair client_7_key; + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + client_2_key = generateRsaKeyPair(RSA_SIGNATURE_LENGTH); + client_7_key = generateRsaKeyPair(RSA_SIGNATURE_LENGTH); + } else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + client_2_key = generateEdDSAKeyPair(); + client_7_key = generateEdDSAKeyPair(); + } unique_ptr cm(new ClientsManager({}, {4, 5, 7}, {}, {}, metrics)); cm->setClientPublicKey(7, client_7_key.second, kKeyFormatForTesting); diff --git a/bftengine/tests/messages/CheckpointMsg_test.cpp b/bftengine/tests/messages/CheckpointMsg_test.cpp index f9c50eead6..e3882fca95 100644 --- a/bftengine/tests/messages/CheckpointMsg_test.cpp +++ b/bftengine/tests/messages/CheckpointMsg_test.cpp @@ -32,7 +32,7 @@ class CheckpointMsgTestsFixture : public ::testing::Test { replicaInfo(config, false, false), sigManager(createSigManager(config.replicaId, config.replicaPrivateKey, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, config.publicKeysOfReplicas, replicaInfo)) diff --git a/bftengine/tests/messages/ClientRequestMsg_test.cpp b/bftengine/tests/messages/ClientRequestMsg_test.cpp index 535bd63bb2..7e8e336544 100644 --- a/bftengine/tests/messages/ClientRequestMsg_test.cpp +++ b/bftengine/tests/messages/ClientRequestMsg_test.cpp @@ -31,7 +31,7 @@ class ClientRequestMsgTestFixture : public ::testing::Test { replicaInfo(config, false, false), sigManager(createSigManager(config.replicaId, config.replicaPrivateKey, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, config.publicKeysOfReplicas, replicaInfo)) {} diff --git a/bftengine/tests/messages/PrePrepareMsg_test.cpp b/bftengine/tests/messages/PrePrepareMsg_test.cpp index df671aeb04..f203a9d2ce 100644 --- a/bftengine/tests/messages/PrePrepareMsg_test.cpp +++ b/bftengine/tests/messages/PrePrepareMsg_test.cpp @@ -100,7 +100,7 @@ class PrePrepareMsgTestFixture : public ::testing::Test { replicaInfo(config, false, false), sigManager(createSigManager(config.replicaId, config.replicaPrivateKey, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, config.publicKeysOfReplicas, replicaInfo)) {} diff --git a/bftengine/tests/messages/ReplicaAsksToLeaveViewMsg_test.cpp b/bftengine/tests/messages/ReplicaAsksToLeaveViewMsg_test.cpp index 58f60835e0..cbed0a82e6 100644 --- a/bftengine/tests/messages/ReplicaAsksToLeaveViewMsg_test.cpp +++ b/bftengine/tests/messages/ReplicaAsksToLeaveViewMsg_test.cpp @@ -36,7 +36,7 @@ TEST(ReplicaAsksToLeaveViewMsg, base_methods) { ReplicasInfo replicaInfo(config, true, true); std::unique_ptr sigManager(createSigManager(config.replicaId, config.replicaPrivateKey, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, config.publicKeysOfReplicas, replicaInfo)); ViewsManager manager(&replicaInfo); diff --git a/bftengine/tests/messages/ReplicaRestartReadyMsg_test.cpp b/bftengine/tests/messages/ReplicaRestartReadyMsg_test.cpp index 27845f8ae2..699600b24f 100644 --- a/bftengine/tests/messages/ReplicaRestartReadyMsg_test.cpp +++ b/bftengine/tests/messages/ReplicaRestartReadyMsg_test.cpp @@ -36,7 +36,7 @@ TEST(ReplicaRestartReadyMsg, base_methods) { ReplicasInfo replicaInfo(config, true, true); std::unique_ptr sigManager(createSigManager(config.replicaId, config.replicaPrivateKey, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, config.publicKeysOfReplicas, replicaInfo)); std::unique_ptr msg(ReplicaRestartReadyMsg::create( @@ -60,7 +60,7 @@ TEST(ReplicaRestartReadyMsg, with_extraData) { auto version = "latest"; std::unique_ptr sigManager(createSigManager(config.replicaId, config.replicaPrivateKey, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, config.publicKeysOfReplicas, replicaInfo)); std::unique_ptr msg(ReplicaRestartReadyMsg::create( diff --git a/bftengine/tests/messages/ViewChangeMsg_test.cpp b/bftengine/tests/messages/ViewChangeMsg_test.cpp index 5cac0c62a2..967a481904 100644 --- a/bftengine/tests/messages/ViewChangeMsg_test.cpp +++ b/bftengine/tests/messages/ViewChangeMsg_test.cpp @@ -49,7 +49,7 @@ void ViewChangeMsgTestsFixture::ViewChangeMsgTests(bool bAddElements, ReplicasInfo replicaInfo(config, true, true); std::unique_ptr sigManager(createSigManager(config.replicaId, config.replicaPrivateKey, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, config.publicKeysOfReplicas, replicaInfo)); ViewsManager manager(&replicaInfo); @@ -193,7 +193,7 @@ void ViewChangeMsgTestsFixture::ViewChangeMsgAddRemoveComplaints(const std::stri ReplicasInfo replicaInfo(config, true, true); std::unique_ptr sigManager(createSigManager(config.replicaId, config.replicaPrivateKey, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, config.publicKeysOfReplicas, replicaInfo)); ViewsManager manager(&replicaInfo); diff --git a/bftengine/tests/messages/helper.cpp b/bftengine/tests/messages/helper.cpp index 0e24df9f58..8359c5b951 100644 --- a/bftengine/tests/messages/helper.cpp +++ b/bftengine/tests/messages/helper.cpp @@ -10,10 +10,14 @@ // file. #include "helper.hpp" +#include "ReplicaConfig.hpp" typedef std::pair IdToKeyPair; -const char replicaPrivateKey[] = +using concord::crypto::SIGN_VERIFY_ALGO; +using bftEngine::ReplicaConfig; + +const std::string replicaRSAPrivateKey = { "308204BC020100300D06092A864886F70D0101010500048204A6308204A20201000282010100BCC5BEA607F4F52A493AA2F40C2D5482D7CE37" "DFC526E98131FDC92CE2ECA6035DB307B182EF52CA8471B78A65E445399816AFACB224F4CEA9597D4B6FE5E84030B7AF78A88BA0233263A9F0" "E2658A6E5BE57923D9093B7D6B70FDBAEC3CDA05C5EDE237674A598F5D607A50C1C528EEAE4B690C90820901A01BF4747C39FE6BD6DA535A9B" @@ -35,8 +39,8 @@ const char replicaPrivateKey[] = "4B1D3F7395D5D435E5D2071AD7AF5CB08758355C8686B890CDA88B798612CEFB57CCA85D5109B5A529ECAB80B79CC685D8836ECD6F7FD67D5F" "7502818100B33DC57C801E0824CF2C77D6D35EC51E321168DA1DED72238ECF69DF6BD485B19A2A67CFBE87F6819F5872463687295F4091C6D9" "9AE98AD08EB45931E761D42D9CE941CEF7DF8A493FEAD8EB571BBBA21EF6403151CB25C71A9BB457D3FB058AA34AB4C1AB474C86293A26D428" - "E77960457E2631215FF7B68013877ABCCE4322"; -const std::string pubKey = { + "E77960457E2631215FF7B68013877ABCCE4322"}; +const std::string replicaRSAPubKey = { "30820120300D06092A864886F70D01010105000382010D00308201080282010100B" "CC5BEA607F4F52A493AA2F40C2D5482D7CE37DFC526E981" "31FDC92CE2ECA6035DB307B182EF52CA8471B78A65E445399816AFACB224F4CEA95" @@ -48,14 +52,25 @@ const std::string pubKey = { "F6605C909F98B6C3F795354BBB988C9695F8A1E27FFC3CE4FFA64B549DD90727634" "04FBD352C5C1A05FA3D17377E113600B1EDCAEE17687BC4" "C1AA6F3D020111"}; -const std::vector replicasPubKeys = {pubKey, pubKey, pubKey, pubKey, pubKey, pubKey, pubKey}; +const std::string replicaEdDSAPrivateKey = {"09a30490ebf6f6685556046f2497fd9c7df4a552998c9a9b6ebec742e8183174"}; +const std::string replicaEdDSAPubKey = {"7363bc5ab96d7f85e71a5ffe0b284405ae38e2e0f032fb3ffe805d9f0e2d117b"}; void loadPrivateAndPublicKeys(std::string& myPrivateKey, std::set>& publicKeysOfReplicas, ReplicaId myId, size_t numReplicas) { ConcordAssert(numReplicas <= 7); - myPrivateKey = replicaPrivateKey; + + std::string pubKey; + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + myPrivateKey = replicaRSAPrivateKey; + pubKey = replicaRSAPubKey; + } else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + myPrivateKey = replicaEdDSAPrivateKey; + pubKey = replicaEdDSAPubKey; + } + const std::vector replicasPubKeys{pubKey, pubKey, pubKey, pubKey, pubKey, pubKey, pubKey}; + for (size_t i{0}; i < numReplicas; ++i) { if (i == myId) continue; publicKeysOfReplicas.insert(IdToKeyPair(i, replicasPubKeys[i].c_str())); @@ -92,7 +107,7 @@ bftEngine::ReplicaConfig& createReplicaConfig(uint16_t fVal, uint16_t cVal) { bftEngine::impl::SigManager* createSigManager(size_t myId, std::string& myPrivateKey, - concord::util::crypto::KeyFormat replicasKeysFormat, + concord::crypto::KeyFormat replicasKeysFormat, std::set>& publicKeysOfReplicas, ReplicasInfo& replicasInfo) { return SigManager::init(myId, @@ -100,6 +115,6 @@ bftEngine::impl::SigManager* createSigManager(size_t myId, publicKeysOfReplicas, replicasKeysFormat, nullptr, - concord::util::crypto::KeyFormat::PemFormat, + concord::crypto::KeyFormat::PemFormat, replicasInfo); } diff --git a/bftengine/tests/messages/helper.hpp b/bftengine/tests/messages/helper.hpp index 6aa748ea8c..b08c13a446 100644 --- a/bftengine/tests/messages/helper.hpp +++ b/bftengine/tests/messages/helper.hpp @@ -116,7 +116,7 @@ void testMessageBaseMethods(const MessageT &tested, MsgType type, NodeIdType sen bftEngine::impl::SigManager *createSigManager(size_t myId, std::string &myPrivateKey, - concord::util::crypto::KeyFormat replicasKeysFormat, + concord::crypto::KeyFormat replicasKeysFormat, std::set> &publicKeysOfReplicas, ReplicasInfo &replicasInfo); diff --git a/bftengine/tests/testMsgsCertificate/msgsCertificate_test.cpp b/bftengine/tests/testMsgsCertificate/msgsCertificate_test.cpp index d6c2862cda..828adce1f6 100644 --- a/bftengine/tests/testMsgsCertificate/msgsCertificate_test.cpp +++ b/bftengine/tests/testMsgsCertificate/msgsCertificate_test.cpp @@ -31,7 +31,7 @@ class msgsCertificateTestsFixture : public ::testing::Test { replicaInfo(config, false, false), sigManager(createSigManager(config.replicaId, config.replicaPrivateKey, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, config.publicKeysOfReplicas, replicaInfo)) diff --git a/bftengine/tests/testSerialization/TestSerialization.cpp b/bftengine/tests/testSerialization/TestSerialization.cpp index 4cfd4e7af2..42d957da92 100644 --- a/bftengine/tests/testSerialization/TestSerialization.cpp +++ b/bftengine/tests/testSerialization/TestSerialization.cpp @@ -395,7 +395,7 @@ int main() { ReplicasInfo replicaInfo(config, false, false); std::unique_ptr sigManager(createSigManager(config.replicaId, config.replicaPrivateKey, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, config.publicKeysOfReplicas, replicaInfo)); DescriptorOfLastNewView::setViewChangeMsgsNum(fVal, cVal); diff --git a/bftengine/tests/testViewChange/testViewChange.cpp b/bftengine/tests/testViewChange/testViewChange.cpp index c33135bf42..3953e7884f 100644 --- a/bftengine/tests/testViewChange/testViewChange.cpp +++ b/bftengine/tests/testViewChange/testViewChange.cpp @@ -87,7 +87,7 @@ void setUpConfiguration_4() { sigManager_.reset(createSigManager(0, replicaConfig[0].replicaPrivateKey, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, replicaConfig[0].publicKeysOfReplicas, *pRepInfo)); } diff --git a/bftengine/tests/testViewChange/test_views_manager.cpp b/bftengine/tests/testViewChange/test_views_manager.cpp index 58c79b16da..c51f7a37cc 100644 --- a/bftengine/tests/testViewChange/test_views_manager.cpp +++ b/bftengine/tests/testViewChange/test_views_manager.cpp @@ -53,7 +53,7 @@ class ViewsManagerTest : public ::testing::Test { replicasInfo(rc, dynamicCollectorForPartialProofs, dynamicCollectorForExecutionProofs), sigManager(createSigManager(rc.replicaId, rc.replicaPrivateKey, - concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, + concord::crypto::KeyFormat::HexaDecimalStrippedFormat, rc.publicKeysOfReplicas, replicasInfo)), viewsManager(std::make_unique(&replicasInfo)) {} diff --git a/client/bftclient/include/bftclient/bft_client.h b/client/bftclient/include/bftclient/bft_client.h index 700d386227..a5d7bf4c27 100644 --- a/client/bftclient/include/bftclient/bft_client.h +++ b/client/bftclient/include/bftclient/bft_client.h @@ -25,8 +25,8 @@ #include "exception.h" #include "metrics.h" #include "diagnostics.h" -#include "crypto_utils.hpp" #include "seq_num_generator.h" +#include "crypto/signer.hpp" namespace bft::client { @@ -59,7 +59,7 @@ class Client { // Useful for testing. Shouldn't be relied on in production. std::optional primary() { return primary_; } std::string signMessage(std::vector&); - void setTransactionSigner(concord::util::crypto::ISigner* signer) { transaction_signer_.reset(signer); } + void setTransactionSigner(concord::crypto::ISigner* signer) { transaction_signer_.reset(signer); } // thread safe version of send api Reply sendThreadSafe(const WriteConfig& config, Msg&& request); Reply sendThreadSafe(const ReadConfig& config, Msg&& request); @@ -123,8 +123,8 @@ class Client { Metrics metrics_; - // Transaction RSA signer - std::unique_ptr transaction_signer_; + // Transaction signer + std::unique_ptr transaction_signer_; static constexpr int64_t MAX_VALUE_NANOSECONDS = 1000 * 1000 * 1000; // 1 second static constexpr int64_t MAX_TRANSACTION_SIZE = 100 * 1024 * 1024; // 100MB diff --git a/client/bftclient/src/bft_client.cpp b/client/bftclient/src/bft_client.cpp index b881fb3192..cc54d60ada 100644 --- a/client/bftclient/src/bft_client.cpp +++ b/client/bftclient/src/bft_client.cpp @@ -16,11 +16,16 @@ #include "secrets_manager_enc.h" #include "secrets_manager_plain.h" #include "communication/StateControl.hpp" +#include "crypto/factory.hpp" +#include "ReplicaConfig.hpp" using namespace concord::diagnostics; using namespace concord::secretsmanager; using namespace bftEngine; using namespace bftEngine::impl; +using concord::crypto::KeyFormat; +using concord::crypto::Factory; +using bftEngine::ReplicaConfig; namespace bft::client { @@ -55,9 +60,11 @@ Client::Client(SharedCommPtr comm, const ClientConfig& config, std::shared_ptrdecryptFile(file_path); - if (!key_plaintext) throw InvalidPrivateKeyException(file_path, config.secrets_manager_config != std::nullopt); - transaction_signer_ = std::make_unique( - key_plaintext.value().c_str(), concord::util::crypto::KeyFormat::PemFormat); + if (!key_plaintext) { + throw InvalidPrivateKeyException(file_path, config.secrets_manager_config != std::nullopt); + } + transaction_signer_ = Factory::getSigner( + key_plaintext.value(), ReplicaConfig::instance().replicaMsgSigningAlgo, KeyFormat::PemFormat); } communication_->setReceiver(config_.id.val, &receiver_); communication_->start(); diff --git a/client/bftclient/test/bft_client_api_tests.cpp b/client/bftclient/test/bft_client_api_tests.cpp index bd3583b0f9..858aab44ac 100644 --- a/client/bftclient/test/bft_client_api_tests.cpp +++ b/client/bftclient/test/bft_client_api_tests.cpp @@ -32,15 +32,22 @@ #include "bftclient/bft_client.h" #include "bftclient/fake_comm.h" #include "msg_receiver.h" +#include "crypto/factory.hpp" +#include "Logger.hpp" +#include "ReplicaConfig.hpp" using namespace std; using namespace bft::client; using namespace bft::communication; -using namespace CryptoPP; using namespace bftEngine::impl; using namespace bftEngine; using namespace placeholders; using namespace concord::secretsmanager; +using concord::crypto::KeyFormat; +using concord::crypto::Factory; +using namespace CryptoPP; +using bftEngine::ReplicaConfig; + using ReplicaId_t = bft::client::ReplicaId; constexpr char KEYS_BASE_PARENT_PATH[] = "/tmp/"; @@ -146,7 +153,7 @@ class ClientApiTestParametrizedFixture : public ClientApiTestFixture, out = GetSecretData(); // return secret data } - unique_ptr transaction_verifier_; + unique_ptr transaction_verifier_; bool corrupt_request_ = false; }; @@ -175,27 +182,29 @@ TEST_P(ClientApiTestParametrizedFixture, print_received_messages_and_timeout) { test_config_.secrets_manager_config = sd; } - // initialize the test's RSAVerifier + // initialize the test's RSAVerifier/EdDSAVerifier string public_key_full_path({keypair_path + PUB_KEY_NAME}); std::ifstream file(public_key_full_path); std::stringstream stream; stream << file.rdbuf(); auto pub_key_str = stream.str(); - transaction_verifier_.reset( - new concord::util::crypto::RSAVerifier(pub_key_str, concord::util::crypto::KeyFormat::PemFormat)); + + transaction_verifier_ = + Factory::getVerifier(pub_key_str, ReplicaConfig::instance().replicaMsgSigningAlgo, KeyFormat::PemFormat); } unique_ptr comm; if (sign_transaction) { - if (scenario == "happy_flow") + if (scenario == "happy_flow") { comm = make_unique( bind(&ClientApiTestParametrizedFixture::PrintAndVerifySignatureBehavior, this, _1, _2)); - else if (scenario == "corrupt_in_dest") { + } else if (scenario == "corrupt_in_dest") { comm = make_unique( bind(&ClientApiTestParametrizedFixture::PrintAndFailVerifySignatureBehavior, this, _1, _2)); corrupt_request_ = true; } - } else + } else { comm = make_unique(bind(&ClientApiTestParametrizedFixture::PrintBehavior, this, _1, _2)); + } ASSERT_TRUE(comm); Client client(move(comm), test_config_); @@ -213,9 +222,9 @@ TEST_P(ClientApiTestParametrizedFixture, print_received_messages_and_timeout) { typedef tuple ClientApiTestParametrizedFixtureInput; INSTANTIATE_TEST_CASE_P(ClientApiTest, ClientApiTestParametrizedFixture, - ::testing::Values(ClientApiTestParametrizedFixtureInput(false, false, "happy_flow"), + ::testing::Values(ClientApiTestParametrizedFixtureInput(true, true, "happy_flow"), + ClientApiTestParametrizedFixtureInput(false, false, "happy_flow"), ClientApiTestParametrizedFixtureInput(true, false, "happy_flow"), - ClientApiTestParametrizedFixtureInput(true, true, "happy_flow"), ClientApiTestParametrizedFixtureInput(true, false, "corrupt_in_dest")), ); Msg replyFromRequest(const MsgFromClient& request) { diff --git a/client/reconfiguration/src/default_handlers.cpp b/client/reconfiguration/src/default_handlers.cpp index 37f2be04f0..bf5b847eb6 100644 --- a/client/reconfiguration/src/default_handlers.cpp +++ b/client/reconfiguration/src/default_handlers.cpp @@ -12,8 +12,9 @@ #include "client/reconfiguration/default_handlers.hpp" #include "bftclient/StateControl.hpp" #include "concord.cmf.hpp" -#include "crypto_utils.hpp" -#include "kvstream.h" +#include "crypto.hpp" +#include "ReplicaConfig.hpp" +#include "openssl/utils.hpp" #include #include @@ -22,6 +23,17 @@ namespace fs = std::experimental::filesystem; namespace concord::client::reconfiguration::handlers { +using bftEngine::ReplicaConfig; +using concord::crypto::SIGN_VERIFY_ALGO; +using concord::crypto::generateRsaKeyPair; +using concord::crypto::generateECDSAKeyPair; +using concord::crypto::RsaHexToPem; +using concord::crypto::generateEdDSAKeyPair; +using concord::crypto::EdDSAHexToPem; +using concord::crypto::generateSelfSignedCert; +using concord::crypto::KeyFormat; +using concord::crypto::CurveType; + template bool validateInputState(const State& state, std::optional init_block = std::nullopt) { concord::messages::ClientStateReply crep; @@ -64,14 +76,13 @@ void ClientTlsKeyExchangeHandler::exchangeTlsKeys(const std::string& pkey_path, const std::string& cert_path, const uint64_t blockid) { // Generate new key pair - auto new_cert_keys = concord::util::crypto::Crypto::instance().generateECDSAKeyPair( - concord::util::crypto::KeyFormat::PemFormat, concord::util::crypto::CurveType::secp384r1); + auto new_cert_keys = generateECDSAKeyPair(KeyFormat::PemFormat, CurveType::secp384r1); std::string master_key = sm_->decryptFile(master_key_path_).value_or(std::string()); if (master_key.empty()) master_key = psm_.decryptFile(master_key_path_).value_or(std::string()); if (master_key.empty()) LOG_FATAL(getLogger(), "unable to read the node master key"); - auto cert = - concord::util::crypto::CertificateUtils::generateSelfSignedCert(cert_path, new_cert_keys.second, master_key); + auto cert = generateSelfSignedCert( + cert_path, new_cert_keys.second, master_key, ReplicaConfig::instance().replicaMsgSigningAlgo); sm_->encryptFile(pkey_path, new_cert_keys.first); psm_.encryptFile(cert_path, cert); @@ -151,9 +162,18 @@ bool ClientMasterKeyExchangeHandler::validate(const State& state) const { bool ClientMasterKeyExchangeHandler::execute(const State& state, WriteState& out) { LOG_INFO(getLogger(), "execute transaction signing key exchange request"); // Generate new key pair - auto hex_keys = concord::util::crypto::Crypto::instance().generateRsaKeyPair( - 2048, concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat); - auto pem_keys = concord::util::crypto::Crypto::instance().RsaHexToPem(hex_keys); + std::pair hex_keys; + std::pair pem_keys; + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + hex_keys = generateRsaKeyPair(concord::crypto::cryptopp::RSA_SIGNATURE_LENGTH); + pem_keys = RsaHexToPem(hex_keys); + } + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + hex_keys = generateEdDSAKeyPair(); + pem_keys = EdDSAHexToPem(hex_keys); + } + + LOG_INFO(getLogger(), "Generated pem keys:" << KVLOG(pem_keys.first, pem_keys.second)); concord::messages::ReconfigurationRequest rreq; concord::messages::ClientExchangePublicKey creq; diff --git a/communication/src/AsyncTlsConnection.cpp b/communication/src/AsyncTlsConnection.cpp index 8cb912977b..83ef6e0e5b 100644 --- a/communication/src/AsyncTlsConnection.cpp +++ b/communication/src/AsyncTlsConnection.cpp @@ -19,16 +19,23 @@ #include #include +#include "crypto.hpp" #include "AsyncTlsConnection.h" #include "TlsDiagnostics.h" #include "TlsWriteQueue.h" #include "secrets_manager_enc.h" #include "secrets_manager_plain.h" -#include "crypto_utils.hpp" #include "communication/StateControl.hpp" #include "hex_tools.h" +#include "openssl/utils.hpp" namespace bft::communication::tls { +using bftEngine::ReplicaConfig; +using concord::crypto::SIGN_VERIFY_ALGO; +using concord::crypto::verifyCertificate; +using concord::crypto::EdDSAHexToPem; +using concord::crypto::RsaHexToPem; +using concord::crypto::getFormat; void AsyncTlsConnection::startReading() { auto self = shared_from_this(); @@ -405,7 +412,7 @@ bool AsyncTlsConnection::verifyCertificateClient(asio::ssl::verify_context& ctx, LOG_WARN(logger_, "No certificate from server at node " << expected_dest_id); return false; } - auto [valid, _] = checkCertificate(cert, expected_dest_id); + auto [valid, _] = checkCertificate(*cert, expected_dest_id); (void)_; // unused variable hack return valid; } @@ -419,37 +426,42 @@ bool AsyncTlsConnection::verifyCertificateServer(asio::ssl::verify_context& ctx) LOG_WARN(logger_, "No certificate from client"); return false; } - auto [valid, peer_id] = checkCertificate(cert, std::nullopt); + auto [valid, peer_id] = checkCertificate(*cert, std::nullopt); peer_id_ = peer_id; return valid; } -std::pair AsyncTlsConnection::checkCertificate(X509* received_cert, +std::pair AsyncTlsConnection::checkCertificate(X509& received_cert, std::optional expected_peer_id) { uint32_t peerId = UINT32_MAX; std::string conn_type; // (1) First, try to verify the certificate against the latest saved certificate - bool res = concord::util::crypto::CertificateUtils::verifyCertificate( + bool res = verifyCertificate( received_cert, config_.certificatesRootPath_, peerId, conn_type, config_.useUnifiedCertificates_); if (expected_peer_id.has_value() && peerId != expected_peer_id.value()) return std::make_pair(false, peerId); if (res) return std::make_pair(res, peerId); LOG_INFO(logger_, - "Unable to validate certificate against the local storage, falling back to validate against the RSA " - "public key"); + "Unable to validate certificate against the local storage, falling back to validate against the replica " + "main key"); std::string pem_pub_key = StateControl::instance().getPeerPubKey(peerId); if (pem_pub_key.empty()) return std::make_pair(false, peerId); - if (concord::util::crypto::Crypto::instance().getFormat(pem_pub_key) != concord::util::crypto::KeyFormat::PemFormat) { - pem_pub_key = concord::util::crypto::Crypto::instance() - .RsaHexToPem(std::make_pair("", StateControl::instance().getPeerPubKey(peerId))) - .second; + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + if (getFormat(pem_pub_key) != concord::crypto::KeyFormat::PemFormat) { + pem_pub_key = RsaHexToPem(std::make_pair("", StateControl::instance().getPeerPubKey(peerId))).second; + } + } else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + if (getFormat(pem_pub_key) != concord::crypto::KeyFormat::PemFormat) { + pem_pub_key = EdDSAHexToPem(std::make_pair("", StateControl::instance().getPeerPubKey(peerId))).second; + } } + // (2) Try to validate the certificate against the peer's public key - res = concord::util::crypto::CertificateUtils::verifyCertificate(received_cert, pem_pub_key); + res = verifyCertificate(received_cert, pem_pub_key); if (!res) return std::make_pair(false, peerId); // (3) If valid, exchange the stored certificate BIO* outbio = BIO_new(BIO_s_mem()); - if (!PEM_write_bio_X509(outbio, received_cert)) { + if (!PEM_write_bio_X509(outbio, &received_cert)) { BIO_free(outbio); return std::make_pair(false, peerId); } diff --git a/communication/src/AsyncTlsConnection.h b/communication/src/AsyncTlsConnection.h index de6b8d4b8e..b5c1c6482d 100644 --- a/communication/src/AsyncTlsConnection.h +++ b/communication/src/AsyncTlsConnection.h @@ -175,7 +175,7 @@ class AsyncTlsConnection : public std::enable_shared_from_this checkCertificate(X509* received_cert, std::optional expected_peer_id); + std::pair checkCertificate(X509& received_cert, std::optional expected_peer_id); const std::string decryptPrivateKey(const fs::path& path); diff --git a/install_deps.sh b/install_deps.sh index c2aec9c4bb..f215756ce1 100755 --- a/install_deps.sh +++ b/install_deps.sh @@ -67,7 +67,7 @@ apt-get ${APT_GET_FLAGS} install \ libz-dev \ libzstd-dev -pip3 install --upgrade wheel && pip3 install --upgrade trio +pip3 install --upgrade wheel && pip3 install --upgrade trio && pip3 install --upgrade pip pip3 install \ eliot eliot-tree \ tatsu==4.4.0 \ @@ -76,7 +76,8 @@ pip3 install \ ecdsa \ protobuf==3.15.8 \ grpcio==1.37.1 \ - grpcio-tools==1.37.1 + grpcio-tools==1.37.1 \ + cryptography==3.3.2 # Build 3rd parties wget ${WGET_FLAGS} -O cmake-linux.sh \ diff --git a/kvbc/include/db_adapter_interface.h b/kvbc/include/db_adapter_interface.h index 6ddc0837f4..ec5d37c1ca 100644 --- a/kvbc/include/db_adapter_interface.h +++ b/kvbc/include/db_adapter_interface.h @@ -8,14 +8,14 @@ #include #include "digest.hpp" -using concord::util::digest::BlockDigest; - namespace concord::storage { class IDBClient; } namespace concord::kvbc { +using concord::util::digest::BlockDigest; + class NotFoundException : public std::runtime_error { public: NotFoundException(const std::string& error) : std::runtime_error(("NotFoundException: " + error).c_str()) {} diff --git a/kvbc/include/direct_kv_block.h b/kvbc/include/direct_kv_block.h index 795796b24c..ba15c44107 100644 --- a/kvbc/include/direct_kv_block.h +++ b/kvbc/include/direct_kv_block.h @@ -15,19 +15,21 @@ #include "kv_types.hpp" #include "sliver.hpp" +#include "digest_type.hpp" #include "digest.hpp" #include #include #include -using concord::util::digest::BlockDigest; - namespace concord { namespace kvbc { namespace v1DirectKeyValue { namespace block { namespace detail { + +using concord::util::digest::BlockDigest; + // Creates a block with the user data appended at the end of the returned Sliver. The passed parentDigest buffer must be // of size DIGEST_SIZE bytes. concordUtils::Sliver create(const concord::kvbc::SetOfKeyValuePairs &updates, diff --git a/kvbc/include/merkle_tree_block.h b/kvbc/include/merkle_tree_block.h index 8f58b93658..5a842e7fd6 100644 --- a/kvbc/include/merkle_tree_block.h +++ b/kvbc/include/merkle_tree_block.h @@ -10,10 +10,10 @@ #include #include -using concord::util::digest::BlockDigest; - namespace concord::kvbc::v2MerkleTree::block::detail { +using concord::util::digest::BlockDigest; + // Creates a block that adds a set of key/values. RawBlock create(const SetOfKeyValuePairs &updates, const BlockDigest &parentDigest, diff --git a/kvbc/include/pruning_handler.hpp b/kvbc/include/pruning_handler.hpp index 6a54756792..4dc3c1b428 100644 --- a/kvbc/include/pruning_handler.hpp +++ b/kvbc/include/pruning_handler.hpp @@ -17,7 +17,6 @@ #include "concord.cmf.hpp" #include "db_interfaces.h" #include "reconfiguration/ireconfiguration.hpp" -#include "crypto_utils.hpp" #include "block_metadata.hpp" #include "kvbc_key_types.hpp" #include @@ -28,22 +27,22 @@ namespace concord::kvbc::pruning { // This class signs pruning messages via the replica's private key that it gets // through the configuration. Message contents used to generate the signature // are generated via the mechanisms provided in pruning_serialization.hpp/cpp . -class RSAPruningSigner { +class PruningSigner { public: // Construct by passing the configuration for the node the signer is running // on. - RSAPruningSigner(const std::string &key); + PruningSigner(const std::string &key); // Sign() methods sign the passed message and store the signature in the // 'signature' field of the message. An exception is thrown on error. // - // Note RSAPruningSigner does not handle signing of PruneRequest messages on + // Note PruningSigner does not handle signing of PruneRequest messages on // behalf of the operator, as the operator's signature is a dedicated-purpose - // application-level signature rather than a Concord-BFT Principal's RSA + // application-level signature rather than a Concord-BFT Principal's RSA/EdDSA // signature. void sign(concord::messages::LatestPrunableBlock &); private: - std::unique_ptr signer_; + std::unique_ptr signer_; }; // This class verifies pruning messages that were signed by serializing message @@ -52,27 +51,27 @@ class RSAPruningSigner { // // Idea is to use the principal_id as an ID that identifies senders in pruning // messages since it is unique across clients and replicas. -class RSAPruningVerifier { +class PruningVerifier { public: // Construct by passing the system configuration. - RSAPruningVerifier(const std::set> &replicasPublicKeys); + PruningVerifier(const std::set> &replicasPublicKeys); // Verify() methods verify that the message comes from the advertised sender. // Methods return true on successful verification and false on unsuccessful. // An exception is thrown on error. // - // Note RSAPruningVerifier::Verify(const com::vmware::concord::PruneRequest&) + // Note PruningVerifier::Verify(const com::vmware::concord::PruneRequest&) // handles verification of the LatestPrunableBlock message(s) contained within // the PruneRequest, but does not itself handle verification of the issuing // operator's signature of the pruning command, as the operator's signature is // a dedicated application-level signature rather than one of the Concord-BFT - // Principal's RSA signatures. + // Principal's RSA/EdDSA signatures. bool verify(const concord::messages::LatestPrunableBlock &) const; bool verify(const concord::messages::PruneRequest &) const; private: struct Replica { std::uint64_t principal_id{0}; - std::unique_ptr verifier; + std::unique_ptr verifier; }; bool verify(std::uint64_t sender, const std::string &ser, const std::string &signature) const; @@ -167,8 +166,8 @@ class PruningHandler : public concord::reconfiguration::BftReconfigurationHandle void pruneThroughBlockId(kvbc::BlockId block_id) const; uint64_t getBlockBftSequenceNumber(kvbc::BlockId) const; logging::Logger logger_; - RSAPruningSigner signer_; - RSAPruningVerifier verifier_; + PruningSigner signer_; + PruningVerifier verifier_; kvbc::IReader &ro_storage_; kvbc::IBlockAdder &blocks_adder_; kvbc::IBlocksDeleter &blocks_deleter_; @@ -231,7 +230,7 @@ class ReadOnlyReplicaPruningHandler : public concord::reconfiguration::BftReconf private: IReader &ro_storage_; - RSAPruningSigner signer_; + PruningSigner signer_; bool pruning_enabled_{false}; std::uint64_t replica_id_{0}; }; diff --git a/kvbc/include/v4blockchain/detail/blockchain.h b/kvbc/include/v4blockchain/detail/blockchain.h index a28c3dc860..29450b54ae 100644 --- a/kvbc/include/v4blockchain/detail/blockchain.h +++ b/kvbc/include/v4blockchain/detail/blockchain.h @@ -118,7 +118,7 @@ class Blockchain { std::atomic genesis_block_id_{INVALID_BLOCK_ID}; std::shared_ptr native_client_; util::ThreadPool thread_pool_{1}; - std::optional> future_digest_; + std::optional> future_digest_; }; } // namespace concord::kvbc::v4blockchain::detail diff --git a/kvbc/src/pruning_handler.cpp b/kvbc/src/pruning_handler.cpp index 282cd1ad11..3f14c04b09 100644 --- a/kvbc/src/pruning_handler.cpp +++ b/kvbc/src/pruning_handler.cpp @@ -16,10 +16,14 @@ #include "pruning_handler.hpp" #include "categorization/versioned_kv_category.h" #include "kvbc_key_types.hpp" +#include "crypto/factory.hpp" namespace concord::kvbc::pruning { -void RSAPruningSigner::sign(concord::messages::LatestPrunableBlock& block) { +using concord::crypto::Factory; +using bftEngine::ReplicaConfig; + +void PruningSigner::sign(concord::messages::LatestPrunableBlock& block) { std::ostringstream oss; std::string ser; oss << block.replica << block.block_id; @@ -28,19 +32,17 @@ void RSAPruningSigner::sign(concord::messages::LatestPrunableBlock& block) { block.signature = std::vector(signature.begin(), signature.end()); } -RSAPruningSigner::RSAPruningSigner(const std::string& key) - : signer_{std::make_unique( - key, concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat)} {} +PruningSigner::PruningSigner(const std::string& key) { + signer_ = Factory::getSigner(key, ReplicaConfig::instance().replicaMsgSigningAlgo); +} -RSAPruningVerifier::RSAPruningVerifier(const std::set>& replicasPublicKeys) { +PruningVerifier::PruningVerifier(const std::set>& replicasPublicKeys) { auto i = 0u; for (auto& [idx, pkey] : replicasPublicKeys) { - replicas_.push_back(Replica{idx, - std::make_unique( - pkey, concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat)}); + replicas_.push_back(Replica{idx, Factory::getVerifier(pkey, ReplicaConfig::instance().replicaMsgSigningAlgo)}); const auto ins_res = replica_ids_.insert(replicas_.back().principal_id); if (!ins_res.second) { - throw std::runtime_error{"RSAPruningVerifier found duplicate replica principal_id: " + + throw std::runtime_error{"PruningVerifier found duplicate replica principal_id: " + std::to_string(replicas_.back().principal_id)}; } @@ -50,7 +52,7 @@ RSAPruningVerifier::RSAPruningVerifier(const std::set(replica_ids_.size())) { return false; } @@ -78,7 +80,7 @@ bool RSAPruningVerifier::verify(const concord::messages::PruneRequest& request) return false; } - // Note RSAPruningVerifier does not handle verification of the operator's + // Note PruningVerifier does not handle verification of the operator's // signature authorizing this pruning order, as the operator's signature is a // dedicated application-level signature rather than one of the Concord-BFT // principals' RSA signatures. @@ -98,7 +100,7 @@ bool RSAPruningVerifier::verify(const concord::messages::PruneRequest& request) return replica_ids_to_verify.empty(); } -bool RSAPruningVerifier::verify(std::uint64_t sender, const std::string& ser, const std::string& signature) const { +bool PruningVerifier::verify(std::uint64_t sender, const std::string& ser, const std::string& signature) const { auto it = principal_to_replica_idx_.find(sender); if (it == std::cend(principal_to_replica_idx_)) { return false; @@ -107,7 +109,7 @@ bool RSAPruningVerifier::verify(std::uint64_t sender, const std::string& ser, co return getReplica(it->second).verifier->verify(ser, signature); } -const RSAPruningVerifier::Replica& RSAPruningVerifier::getReplica(ReplicaVector::size_type idx) const { +const PruningVerifier::Replica& PruningVerifier::getReplica(ReplicaVector::size_type idx) const { return replicas_[idx]; } diff --git a/kvbc/src/reconfiguration_kvbc_handler.cpp b/kvbc/src/reconfiguration_kvbc_handler.cpp index d743a4d909..cfe01be463 100644 --- a/kvbc/src/reconfiguration_kvbc_handler.cpp +++ b/kvbc/src/reconfiguration_kvbc_handler.cpp @@ -28,18 +28,23 @@ #include "categorized_kvbc_msgs.cmf.hpp" #include "metadata_block_id.h" #include "ReplicaResources.h" +#include "crypto.hpp" + #include #include #include namespace concord::kvbc::reconfiguration { - +using bftEngine::ReplicaConfig; +using concord::crypto::SIGN_VERIFY_ALGO; using bftEngine::impl::DbCheckpointManager; using bftEngine::impl::SigManager; using concord::kvbc::KvbAppFilter; using concord::kvbc::adapter::IdempotentReader; using concord::messages::SnapshotResponseStatus; using concord::storage::rocksdb::NativeClient; +using concord::crypto::RsaHexToPem; +using concord::crypto::EdDSAHexToPem; std::optional get(const std::string& key, BlockId id, kvbc::IReader& ro_storage) { auto opt_val = ro_storage.getLatest(concord::kvbc::categorization::kConcordReconfigurationCategoryId, key); @@ -186,8 +191,8 @@ bool StateSnapshotReconfigurationHandler::handle(const concord::messages::StateS uint32_t, const std::optional& timestamp, concord::messages::ReconfigurationResponse& rres) { - if (!bftEngine::ReplicaConfig::instance().dbCheckpointFeatureEnabled || - bftEngine::ReplicaConfig::instance().maxNumberOfDbCheckpoints == 0) { + if (!ReplicaConfig::instance().dbCheckpointFeatureEnabled || + ReplicaConfig::instance().maxNumberOfDbCheckpoints == 0) { const auto err = "StateSnapshotRequest(participant ID = " + cmd.participant_id + "): failed, the DB checkpoint feature is disabled"; LOG_WARN(getLogger(), err); @@ -209,7 +214,7 @@ bool StateSnapshotReconfigurationHandler::handle(const concord::messages::StateS const auto idempotent_kvbc = std::make_shared(db, link_st_chain); const auto reader = IdempotentReader{idempotent_kvbc}; const auto filter = KvbAppFilter{&reader, ""}; - if (bftEngine::ReplicaConfig::instance().enableEventGroups) { + if (ReplicaConfig::instance().enableEventGroups) { // TODO: We currently only support new participants and, therefore, the event group ID will always be the last // (newest) public event group ID. resp.data->blockchain_height = filter.getNewestPublicEventGroupId(); @@ -235,7 +240,7 @@ bool StateSnapshotReconfigurationHandler::handle(const concord::messages::StateS resp.data.emplace(); resp.data->snapshot_id = *checkpoint_id; const auto filter = KvbAppFilter{&ro_storage_, ""}; - if (bftEngine::ReplicaConfig::instance().enableEventGroups) { + if (ReplicaConfig::instance().enableEventGroups) { // TODO: We currently only support new participants and, therefore, the event group ID will always be the last // (newest) public event group ID. resp.data->blockchain_height = filter.getNewestPublicEventGroupId(); @@ -279,7 +284,6 @@ bool StateSnapshotReconfigurationHandler::handle(const concord::messages::Signed uint32_t, const std::optional&, concord::messages::ReconfigurationResponse& reconf_resp) { - using bftEngine::ReplicaConfig; using concord::kvbc::categorization::StateHash; using concord::kvbc::categorization::detail::deserialize; using concord::kvbc::categorization::detail::serialize; @@ -321,13 +325,9 @@ bool StateSnapshotReconfigurationHandler::handle(const concord::messages::Signed resp.data.hash = public_state_hash.hash; resp.signature.assign(SigManager::instance()->getMySigLength(), 0); const auto data_ser = serialize(resp.data); - // We pass 0 as the last parameter. At the time of writing this code, the last parameter's value is not used - // and is not a reference. Therefore, we pass a temporary here so that if the type is changed to a reference, - // it will break and will prompt the user to review it again. SigManager::instance()->sign(reinterpret_cast(data_ser.data()), data_ser.size(), - reinterpret_cast(resp.signature.data()), - 0); + reinterpret_cast(resp.signature.data())); LOG_INFO(getLogger(), "SignedPublicStateHashRequest: successful request for snapshot ID = " << req.snapshot_id << ", requesting participant ID = " << req.participant_id); @@ -464,8 +464,7 @@ bool KvbcClientReconfigurationHandler::handle(const concord::messages::ClientRec const std::optional& ts, concord::messages::ReconfigurationResponse& rres) { concord::messages::ClientReconfigurationStateReply rep; - uint16_t first_client_id = - bftEngine::ReplicaConfig::instance().numReplicas + bftEngine::ReplicaConfig::instance().numRoReplicas; + uint16_t first_client_id = ReplicaConfig::instance().numReplicas + ReplicaConfig::instance().numRoReplicas; if (sender_id > first_client_id) { for (uint8_t i = kvbc::keyTypes::CLIENT_COMMAND_TYPES::start_ + 1; i < kvbc::keyTypes::CLIENT_COMMAND_TYPES::end_; i++) { @@ -545,7 +544,7 @@ bool ReconfigurationHandler::handle(const concord::messages::ClientsAddRemoveSta const std::optional& ts, concord::messages::ReconfigurationResponse& rres) { concord::messages::ClientsAddRemoveStatusResponse stats; - for (const auto& gr : bftEngine::ReplicaConfig::instance().clientGroups) { + for (const auto& gr : ReplicaConfig::instance().clientGroups) { for (auto cid : gr.second) { std::string key = std::string{kvbc::keyTypes::reconfiguration_client_data_prefix, @@ -574,12 +573,11 @@ bool ReconfigurationHandler::handle(const concord::messages::ClientKeyExchangeSt concord::messages::ReconfigurationResponse& rres) { concord::messages::ClientKeyExchangeStatusResponse stats; concord::secretsmanager::SecretsManagerPlain psm; - for (const auto& gr : bftEngine::ReplicaConfig::instance().clientGroups) { + for (const auto& gr : ReplicaConfig::instance().clientGroups) { for (auto cid : gr.second) { if (command.tls) { - const std::string base_path = - bftEngine::ReplicaConfig::instance().certificatesRootPath + "/" + std::to_string(cid); - std::string client_cert_path = (bftEngine::ReplicaConfig::instance().useUnifiedCertificates) + const std::string base_path = ReplicaConfig::instance().certificatesRootPath + "/" + std::to_string(cid); + std::string client_cert_path = (ReplicaConfig::instance().useUnifiedCertificates) ? base_path + "/node.cert" : base_path + "/client/client.cert"; auto cert = psm.decryptFile(client_cert_path).value_or("invalid client id"); @@ -701,9 +699,7 @@ bool ReconfigurationHandler::handle(const concord::messages::AddRemoveWithWedgeC auto execute_key_prefix = std::string{kvbc::keyTypes::reconfiguration_client_data_prefix, static_cast(kvbc::keyTypes::CLIENT_COMMAND_TYPES::CLIENT_SCALING_EXECUTE_COMMAND)}; - for (uint64_t i = 0; - i < bftEngine::ReplicaConfig::instance().numReplicas + bftEngine::ReplicaConfig::instance().numRoReplicas; - i++) { + for (uint64_t i = 0; i < ReplicaConfig::instance().numReplicas + ReplicaConfig::instance().numRoReplicas; i++) { concord::messages::ClientsAddRemoveExecuteCommand cmd; cmd.config_descriptor = command.config_descriptor; if (token.find(i) == token.end()) continue; @@ -836,7 +832,7 @@ bool ReconfigurationHandler::handle(const concord::messages::ClientKeyExchangeCo LOG_INFO(getLogger(), "exchange client keys for all clients"); // We don't want to assume anything about the CRE client id. Hence, we write the update to all clients. // However, only the CRE client will be able to execute the requests. - for (const auto& cg : bftEngine::ReplicaConfig::instance().clientGroups) { + for (const auto& cg : ReplicaConfig::instance().clientGroups) { for (auto cid : cg.second) { target_clients.push_back(cid); } @@ -874,7 +870,7 @@ bool ReconfigurationHandler::handle(const concord::messages::ClientsAddRemoveCom std::map token; for (const auto& t : command.token) token.insert(t); - for (const auto& cg : bftEngine::ReplicaConfig::instance().clientGroups) { + for (const auto& cg : ReplicaConfig::instance().clientGroups) { for (auto cid : cg.second) { target_clients.push_back(cid); } @@ -916,7 +912,7 @@ bool ReconfigurationHandler::handle(const concord::messages::ClientsRestartComma std::vector serialized_command; concord::messages::serialize(serialized_command, command); std::vector target_clients; - for (const auto& cg : bftEngine::ReplicaConfig::instance().clientGroups) { + for (const auto& cg : ReplicaConfig::instance().clientGroups) { for (auto cid : cg.second) { target_clients.push_back(cid); } @@ -944,7 +940,7 @@ bool ReconfigurationHandler::handle(const concord::messages::ClientsRestartStatu const std::optional& ts, concord::messages::ReconfigurationResponse& rres) { concord::messages::ClientsRestartStatusResponse stats; - for (const auto& gr : bftEngine::ReplicaConfig::instance().clientGroups) { + for (const auto& gr : ReplicaConfig::instance().clientGroups) { for (auto cid : gr.second) { std::string key = std::string{kvbc::keyTypes::reconfiguration_client_data_prefix, static_cast(kvbc::keyTypes::CLIENT_COMMAND_TYPES::CLIENT_RESTART_STATUS)} + @@ -994,9 +990,8 @@ bool ReconfigurationHandler::handle(const messages::UnwedgeCommand& cmd, } LOG_INFO(getLogger(), "Unwedge command started " << KVLOG(cmd.bft_support)); auto curr_epoch = bftEngine::EpochManager::instance().getSelfEpochNumber(); - auto quorum_size = bftEngine::ReplicaConfig::instance().numReplicas; - if (cmd.bft_support) - quorum_size = 2 * bftEngine::ReplicaConfig::instance().fVal + bftEngine::ReplicaConfig::instance().cVal + 1; + auto quorum_size = ReplicaConfig::instance().numReplicas; + if (cmd.bft_support) quorum_size = 2 * ReplicaConfig::instance().fVal + ReplicaConfig::instance().cVal + 1; uint32_t valid_sigs{0}; for (auto const& [id, unwedge_stat] : cmd.unwedges) { if (unwedge_stat.curr_epoch < curr_epoch) continue; @@ -1033,7 +1028,7 @@ bool ReconfigurationHandler::handle(const messages::UnwedgeStatusRequest& req, const std::optional& ts, concord::messages::ReconfigurationResponse& rres) { concord::messages::UnwedgeStatusResponse response; - response.replica_id = bftEngine::ReplicaConfig::instance().replicaId; + response.replica_id = ReplicaConfig::instance().replicaId; if (bftEngine::ControlStateManager::instance().getCheckpointToStopAt().has_value()) { if ((!req.bft_support && !bftEngine::IControlHandler::instance()->isOnNOutOfNCheckpoint()) || (req.bft_support && !bftEngine::IControlHandler::instance()->isOnStableCheckpoint())) { @@ -1044,11 +1039,10 @@ bool ReconfigurationHandler::handle(const messages::UnwedgeStatusRequest& req, } } auto curr_epoch = bftEngine::EpochManager::instance().getSelfEpochNumber(); - std::string sig_data = - std::to_string(bftEngine::ReplicaConfig::instance().getreplicaId()) + std::to_string(curr_epoch); + std::string sig_data = std::to_string(ReplicaConfig::instance().getreplicaId()) + std::to_string(curr_epoch); auto sig_manager = bftEngine::impl::SigManager::instance(); std::string sig(sig_manager->getMySigLength(), '\0'); - sig_manager->sign(sig_data.c_str(), sig_data.size(), sig.data(), sig.size()); + sig_manager->sign(sig_data.c_str(), sig_data.size(), sig.data()); response.can_unwedge = true; response.curr_epoch = curr_epoch; response.signature = std::vector(sig.begin(), sig.end()); @@ -1142,7 +1136,7 @@ bool ReconfigurationHandler::handle(const concord::messages::PruneStatusRequest& bool InternalKvReconfigurationHandler::verifySignature(uint32_t sender_id, const std::string& data, const std::string& signature) const { - if (sender_id >= bftEngine::ReplicaConfig::instance().numReplicas) return false; + if (sender_id >= ReplicaConfig::instance().numReplicas) return false; return bftEngine::impl::SigManager::instance()->verifySig( sender_id, data.data(), data.size(), signature.data(), signature.size()); } @@ -1247,18 +1241,24 @@ bool InternalPostKvReconfigurationHandler::handle(const concord::messages::Clien LOG_INFO(getLogger(), "Writing client keys to block [" << id << "] after key exchange, keys " << std::hash{}(updated_client_keys)); - if (!bftEngine::ReplicaConfig::instance().saveClinetKeyFile) return true; + if (!ReplicaConfig::instance().saveClinetKeyFile) return true; // Now that keys have exchanged, lets persist the new key in the file system uint32_t group_id = 0; - for (const auto& [gid, cgr] : bftEngine::ReplicaConfig::instance().clientGroups) { + for (const auto& [gid, cgr] : ReplicaConfig::instance().clientGroups) { if (std::find(cgr.begin(), cgr.end(), sender_id) != cgr.end()) { group_id = gid; break; } } - std::string path = bftEngine::ReplicaConfig::instance().clientsKeysPrefix + "/" + std::to_string(group_id) + - "/transaction_signing_pub.pem"; - auto pem_key = concord::util::crypto::Crypto::instance().RsaHexToPem(std::make_pair("", command.pub_key)); + std::string path = + ReplicaConfig::instance().clientsKeysPrefix + "/" + std::to_string(group_id) + "/transaction_signing_pub.pem"; + std::pair pem_key; + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + pem_key = RsaHexToPem(std::make_pair("", command.pub_key)); + } else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + pem_key = EdDSAHexToPem(std::make_pair("", command.pub_key)); + } + concord::secretsmanager::SecretsManagerPlain sm; LOG_INFO(getLogger(), KVLOG(path, pem_key.second, sender_id)); return sm.encryptFile(path, pem_key.second); diff --git a/kvbc/src/resources-manager/AdaptivePruningManager.cpp b/kvbc/src/resources-manager/AdaptivePruningManager.cpp index b20cc610b2..2bad3f1be3 100644 --- a/kvbc/src/resources-manager/AdaptivePruningManager.cpp +++ b/kvbc/src/resources-manager/AdaptivePruningManager.cpp @@ -70,9 +70,7 @@ void AdaptivePruningManager::notifyReplicas(const PruneInfo &pruneInfo) { const std::string cid = "adaptive-pruning-manager-cid"; std::string sig(SigManager::instance()->getMySigLength(), '\0'); - uint16_t sig_length{0}; - SigManager::instance()->sign( - reinterpret_cast(serialized_req.data()), serialized_req.size(), sig.data(), sig_length); + SigManager::instance()->sign(reinterpret_cast(serialized_req.data()), serialized_req.size(), sig.data()); rreq.signature = std::vector(sig.begin(), sig.end()); serialized_req.clear(); concord::messages::serialize(serialized_req, rreq); diff --git a/kvbc/test/CMakeLists.txt b/kvbc/test/CMakeLists.txt index 94a97497dd..ca9bbe815e 100644 --- a/kvbc/test/CMakeLists.txt +++ b/kvbc/test/CMakeLists.txt @@ -23,7 +23,7 @@ target_link_libraries(kvbc_filter_test ${yaml-cpp_LIBRARIES} kvbc concord-kvbc-proto - concordbft_reconfiguration + corebft logging) add_executable(order_test order_test.cpp ) diff --git a/kvbc/test/kvbc_dbadapter_test.cpp b/kvbc/test/kvbc_dbadapter_test.cpp index 20ec7c0795..4b3e7bbaee 100644 --- a/kvbc/test/kvbc_dbadapter_test.cpp +++ b/kvbc/test/kvbc_dbadapter_test.cpp @@ -21,10 +21,9 @@ using concord::kvbc::KeysVector; using concord::kvbc::KeyValuePair; using concord::kvbc::SetOfKeyValuePairs; using concord::kvbc::BlockId; -// using concord::storage::rocksdb::Client; -// using concord::storage::rocksdb::KeyComparator; using concord::kvbc::v1DirectKeyValue::block::detail::create; using concord::kvbc::v1DirectKeyValue::block::detail::getUserData; +using concord::util::digest::BlockDigest; namespace { diff --git a/kvbc/test/pruning_test.cpp b/kvbc/test/pruning_test.cpp index 0f2e1d83ff..93aee5163f 100644 --- a/kvbc/test/pruning_test.cpp +++ b/kvbc/test/pruning_test.cpp @@ -36,304 +36,40 @@ using concord::kvbc::BlockId; using namespace concord::kvbc; using namespace concord::kvbc::categorization; using namespace concord::kvbc::pruning; +using concord::crypto::cryptopp::RSA_SIGNATURE_LENGTH; +using concord::crypto::SIGN_VERIFY_ALGO; +using bftEngine::ReplicaConfig; +using concord::crypto::generateRsaKeyPair; +using concord::crypto::generateEdDSAKeyPair; namespace { const NodeIdType replica_0 = 0; const NodeIdType replica_1 = 1; const NodeIdType replica_2 = 2; const NodeIdType replica_3 = 3; -std::string privateKey_0 = - "308204BA020100300D06092A864886F70D0101010500048204A4308204A00201000282010100C55B8F7979BF24B335017082BF33EE2960E3" - "A0" - "68DCDB45CA3017214BFB3F32649400A2484E2108C7CD07AA7616290667AF7C7A1922C82B51CA01867EED9B60A57F5B6EE33783EC258B2347" - "48" - "8B0FA3F99B05CFFBB45F80960669594B58C993D07B94D9A89ED8266D9931EAE70BB5E9063DEA9EFAF744393DCD92F2F5054624AA048C7EE5" - "0B" - "EF374FCDCE1C8CEBCA1EF12AF492402A6F56DC9338834162F3773B119145BF4B72672E0CF2C7009EBC3D593DFE3715D942CA8749771B484F" - "72" - "A2BC8C89F86DB52ECC40763B6298879DE686C9A2A78604A503609BA34B779C4F55E3BEB0C26B1F84D8FC4EB3C79693B25A77A158EF88292D" - "4C" - "01F99EFE3CC912D09B020111028201001D05EF73BF149474B4F8AEA9D0D2EE5161126A69C6203EF8162184E586D4967833E1F9BF56C89F68" - "AD" - "35D54D99D8DB4B7BB06C4EFD95E840BBD30C3FD7A5E890CEF6DB99E284576EEED07B6C8CEBB63B4B80DAD2311D1A706A5AC95DE768F01721" - "3B" - "896B9EE38D2E3C2CFCE5BDF51ABD27391761245CDB3DCB686F05EA2FF654FA91F89DA699F14ACFA7F0D8030F74DBFEC28D55C902A27E9C03" - "AB" - "1CA2770EFC5BE541560D86FA376B1A688D92124496BB3E7A3B78A86EBF1B694683CDB32BC49431990A18B570C104E47AC6B0DE5616851F43" - "09" - "CFE7D0E20B17C154A3D85F33C7791451FFF73BFC4CDC8C16387D184F42AD2A31FCF545C3F9A498FAAC6E94E902818100F40CF9152ED4854E" - "1B" - "BF67C5EA185C52EBEA0C11875563AEE95037C2E61C8D988DDF71588A0B45C23979C5FBFD2C45F9416775E0A644CAD46792296FDC68A98148" - "F7" - "BD3164D9A5E0D6A0C2DF0141D82D610D56CB7C53F3C674771ED9ED77C0B5BF3C936498218176DC9933F1215BC831E0D41285611F512F6832" - "7E" - "4FBD9E5C5902818100CF05519FD69D7C6B61324F0A201574C647792B80E5D4D56A51CF5988927A1D54DF9AE4EA656AE25961923A0EC046F1" - "C5" - "69BAB53A64EB0E9F5AB2ABF1C9146935BA40F75E0EB68E0BE4BC29A5A0742B59DF5A55AB028F1CCC42243D2AEE4B74344CA33E72879EF2D1" - "CD" - "D874A7F237202AC7EB57AEDCBD539DEFDA094476EAE613028180396C76D7CEC897D624A581D43714CA6DDD2802D6F2AAAE0B09B885974533" - "E5" - "14D6167505C620C51EA41CA70E1D73D43AA5FA39DA81799922EB3173296109914B98B2C31AAE515434E734E28ED31E8D37DA99BA11C2E693" - "B6" - "398570ABBF6778A33C0E40CC6007E23A15C9B1DE6233B6A25304B91053166D7490FCD26D1D8EAC5102818079C6E4B86020674E392CA6F6E5" - "B2" - "44B0DEBFBF3CC36E232F7B6AE95F6538C5F5B0B57798F05CFD9DFD28D6DB8029BB6511046A9AD1F3AE3F9EC37433DFB1A74CC7E9FAEC08A7" - "9E" - "D9D1D8187F8B8FA107B08F7DAFE3633E1DCC8DC9A0C8689EB55A41E87F9B12347B6A06DB359D89D6AFC0E4CA2A9FF6E5E46EF8BA2845F396" - "65" - "0281802A89B2BD4A665A0F07DCAFA6D9DB7669B1D1276FC3365173A53F0E0D5F9CB9C3E08E68503C62EA73EB8E0DA42CCF6B136BF4A85B0A" - "C4" - "24730B4F3CAD8C31D34DD75EF2A39B6BCFE3985CCECC470CF479CF0E9B9D6C7CE1C6C70D853728925326A22352DF73B502D4D3CBC2A770DE" - "27" - "6E1C5953DF7A9614C970C94D194CAE9188"; -std::string privateKey_1 = - "308204BC020100300D06092A864886F70D0101010500048204A6308204A20201000282010100CAF26C09B1F6F056F66B54AA0EA002EA2361" - "51" - "3A721A58E44472ADE74DBD833890ED9EE8E0CFF1B84C3DFE9E6226C8CEBFFEDFE71A6BCFE5A599D02FD9940997E864D400BF440BA7B1A568" - "A5" - "ACF7688B025B5B207E5651E597141FAEF733FA9D87732B8FBA31E082BE777AEB992B00873764655C3B1F8FBF8DD2446F4F9F79883E21DBC1" - "A1" - "7431E42AF01B9D4DE54B9880E7FB397655C79D7C3A5981CA64A32E2F05FCF0B127F4C6D349056276992B7403D36E03D14C45B6F5F6678628" - "0C" - "921236A17EE0F311821BDF925A47DCA590BB31C60646692014317BE0DD32248DF557A77F80F336C82461B659266F74F495BA5CE194043505" - "B5" - "F0C363263BF73BB897020111028201005F8123C853BF8028EC6EBE6E2500015F1FB55366CC48A24D4D6324A915865BDE6251B4315ABC3583" - "E7" - "A4B40E4C4E7C9D8786FFF448AB34A84DEE079E0C096DED221154B50EB69C12ADF37C8A334740416A85580F4A82F95CFBCD3C1619FA57D1A9" - "27" - "238EEE3596D41D656705754169A90B021194D08752B47EF9899DCB1DDED5DCDDA688D9FA88F9303E99CAB040D2E47DCE866717580C2CD01D" - "B9" - "4E8FE215EAA254432E3B399B90260255DEE7FADED4643814C0DE41DE237BBB7173CFF16AC9237AADA4595FD95EB92E30D2127C7761C6A1CD" - "75" - "C1F12F5B92B6602E1CDC06E112321B0A41C8A102D785B7C4C7D2441DA983346B81873984DD680FB4B1C9AD7102818100D5E41BE52CECFB74" - "05" - "01B87C631DEFB3DD855EE95553A816BE8D3DFAE200086E1C12E9FBDDD8737F2CCE2CED1D82431ADC63C1B34EA59C27E98283EB20EAF8F5A2" - "9D" - "45ACE2E5C3173F396DF4356D54F3ED0CF9BBA222E3B9194CD15F88B6AB8FAFDFACACCC97D87555CD1E864D09DF795FB8BE3F9BE2CB8E52F6" - "41" - "FCEDC8E97902818100F2E6BDF9A552D35E9F695C52343D9BBF180BBEB50F6705A7836DF1BFF6A42C2D7A000432957516B555B5E1FBAC21CE" - "D5" - "D2788036AA5AB183A5859284ED409631289F8836D240111B56D6C4953FEFBE177EA137F08ADCABD5CAD07F709E83BB29B0F55AD09E65F5C6" - "56" - "8FE166FF4BE581F4F2066025E3902819EFC2DF0FA63E8F0281803EE8BCE90D36A44F4CC44551C2CC91CB7D637644A0A022610ADE3F67E81E" - "20" - "98DB149F2BF5F45E347696FE279F446E16F586C080081297570871AE5436DBB2A2993D50BA60DA2A5221A77AB13CE3EBCF45B885AFA82861" - "18" - "52BC3D94919F23667F058D23C3B4309AFB1E36278011F66EFE0928E58833A547FA486DC2DC8662C902818100AB75B346CF0D49E870869B85" - "52" - "0D5EE13E26687FCEA3130CD53E8C8780EC5B6B652D3023B4CB1F1696DABDA2979F64D32B27E208784004D565C7B2B82F006A0495255117A3" - "78" - "848BC4D3D60EFFF4862EB3BD186D8F325B2D801AB44F7EF3932C7CE96D47F75707D74C2953D03BBD1A79DA1440BC56FAFC588AC75C613839" - "1D" - "1902818100BBC05F561AEF4BDE1ECABB5CD313E6173F5E46AC85B4462A8CA689E4E84B95E66733081518DB01714B7B18E44B780DB5A6DA26" - "12" - "506F46E4D91C8CB582AFD54C7509C9947EC754BFDD0D35FAECE2E729DBD21A62E33C3DEF556913ECF4C8D75910E860D36AFD0977FF9114AC" - "EA" - "8F44882259C6F1D8314B653F64F4655CFD68A6"; -std::string privateKey_2 = - "308204BA020100300D06092A864886F70D0101010500048204A4308204A00201000282010100DA68B2830103028D0ECD911D20E732257F8A" - "39" - "BC5214B670C8F1F836CD1D88E6421ABD3C47F16E37E07DCFE89FC11ECBED73896FC978B7E1519F59318F3E24BB5C8962B0EA44889C3A8102" - "1C" - "C9E8EAA94099B9305B0F7731C27CC528CFEE710066CB69229F8AA04DBD842FA8C3143CB0EF1164E45E34B114FBA610DBDFC7453DAD995743" - "AD" - "1489AA131D0C730163ECA7317048C1AD1008ED31A32CB773D94B5317CAAF95674582DCA1AC9FEBE02079836B52E1E3C8D39571018A765765" - "0D" - "52D2DF3363F88A690628D64DCBECB88BBA432F27C32E7BC5BC0F1D16D0A027D1D40362F8CEDBE8BED05C2BCE96F33A75CD70014626B32E5E" - "E8" - "1EBD3116F6F1E5231B02011102820100201E749ACB716241EB96B375398B6941BFEEAE23393F480186F668444B572AB873220CC519A38126" - "55" - "B8261AAE14DEE1C1097617F7FB2A199B0FE7783AB650B22432524731828C8F7203E9B8F08422824D43C868FE55190ED8D61CFE78EE5BE978" - "87" - "5339CC2AF974D81AF7F32BBF361A050A165DD19E5646D9B68A02377F2FD417BE92D2722CEE33B3A0F7B111639C092B4024BB08ACEBE9F9BC" - "28" - "C14BB611DBE627136B568493C6995D81442F09DFEFBA4378A34DEF28F3BD862F4C28BECA87A95551FC2DB48766F82752C7E8B34E85995901" - "90" - "B12A648AC1E361FE28A3253EC615381A066BFD351C18F0B236429A950106DD4F1134A3DE6CEB1094B7CE5C7102818100EA51580294BB0FD7" - "DA" - "FDC00364A9B3C4781F70C4BBE8BDE0D82895ADE549E25388E78A53EF83CF9A3D9528F70CB5A57A9A187D5AC68682F03B26C2F6A409E1554F" - "ED" - "061BDC944985102F2988A5A8CD639BA7890FD689D7171612159AAA818F5502EF80D5D13339826A98914A321B5B4512EC24AF3EE80F982D34" - "18" - "0C85B3E38102818100EE9E7F43A98E593F72A584EEC014E0A46003116B82F5D3A21DAE4EB3F21FBC5B71D96E012B6F5FFBEACED4BEC6C147" - "AA" - "AB6F9698F0592F3A8A6CD827ABF210497635639043D5F0B461E00914B152D6ECB3EFC9138A1B9FAEE09420AB9C2E1436B6AC36EEB8AD4370" - "9B" - "BFA0ED30FBF09C1A91BAB71410E49E11BE8E2A571C649B02818044EABF8849DCAA4E8BB40B4C4AC8802AB9EB212ACDDB0AAB8ADEC29C8EBB" - "60" - "AF284419A0376300D3030DC0C121DB128D789DCA841C45AE0A6BC01B397B8A6F7371DC4D1740E051DBD79566919A2296C2F18BA0C86C46A8" - "AC" - "6FE73387D7CBC0BEA682AD6C105A5C356AA557E8A553571450DC0ACA218F8C1DB2F1343FEB16CA71028180704A963DF57029FFBD7B11614B" - "55" - "1E6B7879EA1479DD184C4A33E8CD26A585D0AE0BF7881470A5A3B9CABE77E50FA941419DEC8434DEACD04124297C14AE25C837A0A752F2BF" - "07" - "DC6A4B4F91446337F6EB43A9EB13D0C39D96DC4B9C0D42DC55FB9C5615FC8DC5622B2D006F9E94AD76A31766ECBE26113B53A4F79B744998" - "C1" - "028180124E2A5DAC7AC7017647FE1B6871484B7B38A3C060B992B871939C8A75BC35DB771F041910C0092E01B545E1910109AA827F34F563" - "27" - "15E06819ADED60117FD8B9400C3F307EA022D5AC5394E65D28EF434DC068494D33ACF70B43791C1C13C35AC680E0038DB411ADEBBC067F47" - "7E" - "01E8CF793FB076AE47BD83B935B8041DC1"; -std::string privateKey_3 = - "308204BB020100300D06092A864886F70D0101010500048204A5308204A10201000282010100B4D984129ECC2F4350596DD602EB5337B78E" - "33" - "C4D945C70C2CACFF6237037BEF897D6893079D1067F07FF023D66C77BB41F6D41215C9912D995215C6F7651F1728AAB65CF20CBE81E5E7F2" - "02" - "E474AF535E92BBC386A7A496263BC4189FD9DD5E801C3023038EFE5B5DE35AA3F70C10F87259D586C36D3DF524E9DA2140C481365985AD18" - "5E" - "1CF3E78B6B82FDD274CCD1267838A0B91F9B48544AFB2C71B158A26E6154CECB43ECEE13FFBD6CA91D8D115B6B91C55F3A88E3F389E9A2AF" - "4B" - "C381D21F9ABF2EA16F58773514249B03A4775C6A10561AFC8CF54B551A43FD014F3C5FE12D96AC5F117645E26D125DC7430114FA60577BF7" - "C9" - "AA1224D190B2D8A83B020111028201004FC95FEA18E19C6176459256E32B95A7A3CDCB8B8D08322B04A6ACE790BDC5BC806C087D19F2782D" - "DB" - "0B444C0BC6710ED9564E8073061A66F0D163F5E59D8DB764C3C8ECC523BD758B13815BA1064D597C8C078AF7A450241FED30DDAFEF2CF4FC" - "48" - "ABD336469D648B4DB70C1A2AF86D9BDC56AC6546C882BD763A963329844BF0E8C79E5E7A5C227A1CDB8473965090084BEAC728E4F86670BA" - "E0" - "5DA589FAE1EBC98A26BF207261EECE5A92759DE516306B0B2F715370586EF45447F82CC37206F70D762AAB75215482A67FE6742E9D644AB7" - "65" - "4F02476EAE15A742FCB2266DAE437DC76FB17E1698D4987945C779A4B89F5FB3F5E1B194EFA4024BA3797F2502818100E2BDA6F0031EAA02" - "7B" - "1E8099D9D2CF408B8C9D83A22BFBAAD3BCFA952469A001C25E5E2E89DAF28636633E8D7C5E1E5FD8384767DB5B384DAB38147EA46871D5E3" - "1E" - "DC110026E42E90C44F02110A369ACF0445C617CC25CD1207F116B9AF2FA78A89E6C6345EAFD0607CB145410DD6619AC0C034B54283A0065B" - "93" - "3550B8DACF02818100CC2FDB49EB3E45DB2EB644048C3C35E3BB50980453DB8EB54DD5595CA2DBC43A2F2912D0F696E6126AFBF5D7777BAB" - "B2" - "6AC931030B8896343BC19EA30B8EEBFECE2617A2564B3D66E29DF66708254877CC33E699501A2BA4D0D7D02F068B1DCF6C7A0794F24BEE83" - "BE" - "2E8453D3E436C3B59D2D9BEEB5B38541EF170544EA46D502818100AD63DA02D5359110F4BCF8EE1F0A9E7CA6F30F0A4ED6570A29726544DF" - "9C" - "10F2495738F6696B31EE29972FD59B57082B2CDFBE223E54D0B3DD49009D144FDE94808102A396B454239BE169982B25ED85712162886C8D" - "0D" - "D90DC9D67ACA3AABF8971E28F1EBCFEFDB95140F16D764EF3B947547AFD5E791D4B9915274108D5C07028180300B42A7FB1DB61574671F10" - "20" - "FF1BBD1D03E7888C33A91B99D7D8CA80AC2E2BCEDC7CE5DFAB08F546596705858682C09198C03CF3A7AADF1D1E7FADE49A196921725FE9F6" - "2F" - "D236537076365C4501FE11EE182412D8FB35D6C95E292EB7524EEC58F2B9A26C381EFF92797D22CC491EFD8E6515A1942A3D78ECF65B97BE" - "A7" - "410281806625E51F70BB9E00D0260941C56B22CDCECC7EA6DBC2C28A1CDA0E1AFAACD39C5E962E40FCFC0F5BBA57A7291A1BDC5D3D29495B" - "45" - "CE2B3BEC7748E6C351FF934537BCA246CA36B840CF68BE6D473F7EE079B0EFDFF6B1BB554B06093E18B269FC3BD3F9876376CA7C673A93F1" - "42" - "7088BF0990AB8E232F269B5DBCD446385A66"; -std::string privateKey_4 = - "308204BB020100300D06092A864886F70D0101010500048204A5308204A10201000282010100B4D984129ECC2F4350596DD602EB5337B78E" - "33" - "C4D945C70C2CACFF6237037BEF897D6893079D1067F07FF023D66C77BB41F6D41215C9912D995215C6F7651F1728AAB65CF20CBE81E5E7F2" - "02" - "E474AF535E92BBC386A7A496263BC4189FD9DD5E801C3023038EFE5B5DE35AA3F70C10F87259D586C36D3DF524E9DA2140C481365985AD18" - "5E" - "1CF3E78B6B82FDD274CCD1267838A0B91F9B48544AFB2C71B158A26E6154CECB43ECEE13FFBD6CA91D8D115B6B91C55F3A88E3F389E9A2AF" - "4B" - "C381D21F9ABF2EA16F58773514249B03A4775C6A10561AFC8CF54B551A43FD014F3C5FE12D96AC5F117645E26D125DC7430114FA60577BF7" - "C9" - "AA1224D190B2D8A83B020111028201004FC95FEA18E19C6176459256E32B95A7A3CDCB8B8D08322B04A6ACE790BDC5BC806C087D19F2782D" - "DB" - "0B444C0BC6710ED9564E8073061A66F0D163F5E59D8DB764C3C8ECC523BD758B13815BA1064D597C8C078AF7A450241FED30DDAFEF2CF4FC" - "48" - "ABD336469D648B4DB70C1A2AF86D9BDC56AC6546C882BD763A963329844BF0E8C79E5E7A5C227A1CDB8473965090084BEAC728E4F86670BA" - "E0" - "5DA589FAE1EBC98A26BF207261EECE5A92759DE516306B0B2F715370586EF45447F82CC37206F70D762AAB75215482A67FE6742E9D644AB7" - "65" - "4F02476EAE15A742FCB2266DAE437DC76FB17E1698D4987945C779A4B89F5FB3F5E1B194EFA4024BA3797F2502818100E2BDA6F0031EAA02" - "7B" - "1E8099D9D2CF408B8C9D83A22BFBAAD3BCFA952469A001C25E5E2E89DAF28636633E8D7C5E1E5FD8384767DB5B384DAB38147EA46871D5E3" - "1E" - "DC110026E42E90C44F02110A369ACF0445C617CC25CD1207F116B9AF2FA78A89E6C6345EAFD0607CB145410DD6619AC0C034B54283A0065B" - "93" - "3550B8DACF02818100CC2FDB49EB3E45DB2EB644048C3C35E3BB50980453DB8EB54DD5595CA2DBC43A2F2912D0F696E6126AFBF5D7777BAB" - "B2" - "6AC931030B8896343BC19EA30B8EEBFECE2617A2564B3D66E29DF66708254877CC33E699501A2BA4D0D7D02F068B1DCF6C7A0794F24BEE83" - "BE" - "2E8453D3E436C3B59D2D9BEEB5B38541EF170544EA46D502818100AD63DA02D5359110F4BCF8EE1F0A9E7CA6F30F0A4ED6570A29726544DF" - "9C" - "10F2495738F6696B31EE29972FD59B57082B2CDFBE223E54D0B3DD49009D144FDE94808102A396B454239BE169982B25ED85712162886C8D" - "0D" - "D90DC9D67ACA3AABF8971E28F1EBCFEFDB95140F16D764EF3B947547AFD5E791D4B9915274108D5C07028180300B42A7FB1DB61574671F10" - "20" - "FF1BBD1D03E7888C33A91B99D7D8CA80AC2E2BCEDC7CE5DFAB08F546596705858682C09198C03CF3A7AADF1D1E7FADE49A196921725FE9F6" - "2F" - "D236537076365C4501FE11EE182412D8FB35D6C95E292EB7524EEC58F2B9A26C381EFF92797D22CC491EFD8E6515A1942A3D78ECF65B97BE" - "A7" - "410281806625E51F70BB9E00D0260941C56B22CDCECC7EA6DBC2C28A1CDA0E1AFAACD39C5E962E40FCFC0F5BBA57A7291A1BDC5D3D29495B" - "45" - "CE2B3BEC7748E6C351FF934537BCA246CA36B840CF68BE6D473F7EE079B0EFDFF6B1BB554B06093E18B269FC3BD3F9876376CA7C673A93F1" - "42" - "7088BF0990AB8E232F269B5DBCD446385A66"; -std::string publicKey_0 = - "30820120300D06092A864886F70D01010105000382010D00308201080282010100C55B8F7979BF24B335017082BF33EE2960E3A068DCDB45" - "CA" - "3017214BFB3F32649400A2484E2108C7CD07AA7616290667AF7C7A1922C82B51CA01867EED9B60A57F5B6EE33783EC258B2347488B0FA3F9" - "9B" - "05CFFBB45F80960669594B58C993D07B94D9A89ED8266D9931EAE70BB5E9063DEA9EFAF744393DCD92F2F5054624AA048C7EE50BEF374FCD" - "CE" - "1C8CEBCA1EF12AF492402A6F56DC9338834162F3773B119145BF4B72672E0CF2C7009EBC3D593DFE3715D942CA8749771B484F72A2BC8C89" - "F8" - "6DB52ECC40763B6298879DE686C9A2A78604A503609BA34B779C4F55E3BEB0C26B1F84D8FC4EB3C79693B25A77A158EF88292D4C01F99EFE" - "3C" - "C912D09B020111"; -std::string publicKey_1 = - "30820120300D06092A864886F70D01010105000382010D00308201080282010100CAF26C09B1F6F056F66B54AA0EA002EA2361513A721A58" - "E4" - "4472ADE74DBD833890ED9EE8E0CFF1B84C3DFE9E6226C8CEBFFEDFE71A6BCFE5A599D02FD9940997E864D400BF440BA7B1A568A5ACF7688B" - "02" - "5B5B207E5651E597141FAEF733FA9D87732B8FBA31E082BE777AEB992B00873764655C3B1F8FBF8DD2446F4F9F79883E21DBC1A17431E42A" - "F0" - "1B9D4DE54B9880E7FB397655C79D7C3A5981CA64A32E2F05FCF0B127F4C6D349056276992B7403D36E03D14C45B6F5F66786280C921236A1" - "7E" - "E0F311821BDF925A47DCA590BB31C60646692014317BE0DD32248DF557A77F80F336C82461B659266F74F495BA5CE194043505B5F0C36326" - "3B" - "F73BB897020111"; -std::string publicKey_2 = - "30820120300D06092A864886F70D01010105000382010D00308201080282010100DA68B2830103028D0ECD911D20E732257F8A39BC5214B6" - "70" - "C8F1F836CD1D88E6421ABD3C47F16E37E07DCFE89FC11ECBED73896FC978B7E1519F59318F3E24BB5C8962B0EA44889C3A81021CC9E8EAA9" - "40" - "99B9305B0F7731C27CC528CFEE710066CB69229F8AA04DBD842FA8C3143CB0EF1164E45E34B114FBA610DBDFC7453DAD995743AD1489AA13" - "1D" - "0C730163ECA7317048C1AD1008ED31A32CB773D94B5317CAAF95674582DCA1AC9FEBE02079836B52E1E3C8D39571018A7657650D52D2DF33" - "63" - "F88A690628D64DCBECB88BBA432F27C32E7BC5BC0F1D16D0A027D1D40362F8CEDBE8BED05C2BCE96F33A75CD70014626B32E5EE81EBD3116" - "F6" - "F1E5231B020111"; -std::string publicKey_3 = - "30820120300D06092A864886F70D01010105000382010D00308201080282010100B4D984129ECC2F4350596DD602EB5337B78E33C4D945C7" - "0C" - "2CACFF6237037BEF897D6893079D1067F07FF023D66C77BB41F6D41215C9912D995215C6F7651F1728AAB65CF20CBE81E5E7F202E474AF53" - "5E" - "92BBC386A7A496263BC4189FD9DD5E801C3023038EFE5B5DE35AA3F70C10F87259D586C36D3DF524E9DA2140C481365985AD185E1CF3E78B" - "6B" - "82FDD274CCD1267838A0B91F9B48544AFB2C71B158A26E6154CECB43ECEE13FFBD6CA91D8D115B6B91C55F3A88E3F389E9A2AF4BC381D21F" - "9A" - "BF2EA16F58773514249B03A4775C6A10561AFC8CF54B551A43FD014F3C5FE12D96AC5F117645E26D125DC7430114FA60577BF7C9AA1224D1" - "90" - "B2D8A83B020111"; -std::string publicKey_4 = - "30820120300D06092A864886F70D01010105000382010D00308201080282010100B4D984129ECC2F4350596DD602EB5337B78E33C4D945C7" - "0C" - "2CACFF6237037BEF897D6893079D1067F07FF023D66C77BB41F6D41215C9912D995215C6F7651F1728AAB65CF20CBE81E5E7F202E474AF53" - "5E" - "92BBC386A7A496263BC4189FD9DD5E801C3023038EFE5B5DE35AA3F70C10F87259D586C36D3DF524E9DA2140C481365985AD185E1CF3E78B" - "6B" - "82FDD274CCD1267838A0B91F9B48544AFB2C71B158A26E6154CECB43ECEE13FFBD6CA91D8D115B6B91C55F3A88E3F389E9A2AF4BC381D21F" - "9A" - "BF2EA16F58773514249B03A4775C6A10561AFC8CF54B551A43FD014F3C5FE12D96AC5F117645E26D125DC7430114FA60577BF7C9AA1224D1" - "90" - "B2D8A83B020111"; +constexpr uint8_t noOfReplicas = 4U; +std::pair keyPair[noOfReplicas]; bftEngine::ReplicaConfig &replicaConfig = bftEngine::ReplicaConfig::instance(); std::map private_keys_of_replicas; + void setUpKeysConfiguration_4() { - replicaConfig.publicKeysOfReplicas.insert(std::pair(replica_0, publicKey_0)); - replicaConfig.publicKeysOfReplicas.insert(std::pair(replica_1, publicKey_1)); - replicaConfig.publicKeysOfReplicas.insert(std::pair(replica_2, publicKey_2)); - replicaConfig.publicKeysOfReplicas.insert(std::pair(replica_3, publicKey_3)); - private_keys_of_replicas[replica_0] = privateKey_0; - private_keys_of_replicas[replica_1] = privateKey_1; - private_keys_of_replicas[replica_2] = privateKey_2; - private_keys_of_replicas[replica_3] = privateKey_3; + for (auto i = 0; i < noOfReplicas; ++i) { + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + keyPair[i] = generateRsaKeyPair(RSA_SIGNATURE_LENGTH); + } else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + keyPair[i] = generateEdDSAKeyPair(); + } + } + + replicaConfig.publicKeysOfReplicas.insert(std::pair(replica_0, keyPair[0].second)); + replicaConfig.publicKeysOfReplicas.insert(std::pair(replica_1, keyPair[1].second)); + replicaConfig.publicKeysOfReplicas.insert(std::pair(replica_2, keyPair[2].second)); + replicaConfig.publicKeysOfReplicas.insert(std::pair(replica_3, keyPair[3].second)); + private_keys_of_replicas[replica_0] = keyPair[0].first; + private_keys_of_replicas[replica_1] = keyPair[1].first; + private_keys_of_replicas[replica_2] = keyPair[2].first; + private_keys_of_replicas[replica_3] = keyPair[3].first; } class test_rocksdb : public ::testing::Test { @@ -468,7 +204,7 @@ TestStateTransfer state_transfer; void CheckLatestPrunableResp(const concord::messages::LatestPrunableBlock &latest_prunable_resp, int replica_idx, - const RSAPruningVerifier &verifier) { + const PruningVerifier &verifier) { ASSERT_EQ(latest_prunable_resp.replica, replica_idx); ASSERT_TRUE(verifier.verify(latest_prunable_resp)); } @@ -529,7 +265,7 @@ concord::messages::PruneRequest ConstructPruneRequest(std::size_t client_idx, // Send different block IDs. latest_block.block_id = min_prunable_block_id + i; - auto block_signer = RSAPruningSigner{pkey}; + auto block_signer = PruningSigner{pkey}; block_signer.sign(latest_block); i++; } @@ -542,11 +278,11 @@ TEST_F(test_rocksdb, sign_verify_correct) { const auto replica_count = 4; uint64_t sending_id = 0; uint64_t client_proxy_count = 4; - const auto verifier = RSAPruningVerifier{replicaConfig.publicKeysOfReplicas}; - std::vector signers; + const auto verifier = PruningVerifier{replicaConfig.publicKeysOfReplicas}; + std::vector signers; signers.reserve(replica_count); for (auto i = 0; i < replica_count; ++i) { - signers.emplace_back(RSAPruningSigner{private_keys_of_replicas[i]}); + signers.emplace_back(PruningSigner{private_keys_of_replicas[i]}); } // Sign and verify a LatestPrunableBlock message. @@ -579,11 +315,11 @@ TEST_F(test_rocksdb, verify_malformed_messages) { const auto replica_count = 4; const auto client_proxy_count = replica_count; const auto sending_id = 1; - const auto verifier = RSAPruningVerifier{replicaConfig.publicKeysOfReplicas}; - std::vector signers; + const auto verifier = PruningVerifier{replicaConfig.publicKeysOfReplicas}; + std::vector signers; signers.reserve(replica_count); for (auto i = 0; i < replica_count; ++i) { - signers.emplace_back(RSAPruningSigner{private_keys_of_replicas[i]}); + signers.emplace_back(PruningSigner{private_keys_of_replicas[i]}); } // Break verification of LatestPrunableBlock messages. @@ -693,8 +429,8 @@ TEST_F(test_rocksdb, sm_latest_prunable_request_correct_num_bocks_to_keep) { replicaConfig.pruningEnabled_ = true; TestStorage storage(db); auto &blocks_deleter = storage; - const auto verifier = RSAPruningVerifier{replicaConfig.publicKeysOfReplicas}; - replicaConfig.replicaPrivateKey = privateKey_1; + const auto verifier = PruningVerifier{replicaConfig.publicKeysOfReplicas}; + replicaConfig.replicaPrivateKey = keyPair[1].first; InitBlockchainStorage(replica_count, storage); // Construct the pruning state machine with a nullptr TimeContract to verify @@ -715,10 +451,10 @@ TEST_F(test_rocksdb, sm_latest_prunable_request_big_num_blocks_to_keep) { replicaConfig.numBlocksToKeep_ = num_blocks_to_keep; replicaConfig.replicaId = 1; replicaConfig.pruningEnabled_ = true; - replicaConfig.replicaPrivateKey = privateKey_1; + replicaConfig.replicaPrivateKey = keyPair[1].first; TestStorage storage(db); auto &blocks_deleter = storage; - const auto verifier = RSAPruningVerifier{replicaConfig.publicKeysOfReplicas}; + const auto verifier = PruningVerifier{replicaConfig.publicKeysOfReplicas}; auto sm = PruningHandler{storage, storage, blocks_deleter, false}; @@ -740,10 +476,10 @@ TEST_F(test_rocksdb, sm_latest_prunable_request_no_pruning_conf) { replicaConfig.numBlocksToKeep_ = num_blocks_to_keep; replicaConfig.replicaId = 1; replicaConfig.pruningEnabled_ = true; - replicaConfig.replicaPrivateKey = privateKey_1; + replicaConfig.replicaPrivateKey = keyPair[1].first; TestStorage storage(db); auto &blocks_deleter = storage; - const auto verifier = RSAPruningVerifier{replicaConfig.publicKeysOfReplicas}; + const auto verifier = PruningVerifier{replicaConfig.publicKeysOfReplicas}; InitBlockchainStorage(replica_count, storage); @@ -767,10 +503,10 @@ TEST_F(test_rocksdb, sm_latest_prunable_request_pruning_disabled) { replicaConfig.numBlocksToKeep_ = num_blocks_to_keep; replicaConfig.replicaId = replica_idx; replicaConfig.pruningEnabled_ = false; - replicaConfig.replicaPrivateKey = privateKey_1; + replicaConfig.replicaPrivateKey = keyPair[1].first; auto storage = TestStorage(db); auto &blocks_deleter = storage; - const auto verifier = RSAPruningVerifier{replicaConfig.publicKeysOfReplicas}; + const auto verifier = PruningVerifier{replicaConfig.publicKeysOfReplicas}; InitBlockchainStorage(replica_count, storage); @@ -791,7 +527,7 @@ TEST_F(test_rocksdb, sm_handle_prune_request_on_pruning_disabled) { replicaConfig.numBlocksToKeep_ = num_blocks_to_keep; replicaConfig.replicaId = replica_idx; replicaConfig.pruningEnabled_ = false; - replicaConfig.replicaPrivateKey = privateKey_1; + replicaConfig.replicaPrivateKey = keyPair[1].first; TestStorage storage(db); auto &blocks_deleter = storage; @@ -810,7 +546,7 @@ TEST_F(test_rocksdb, sm_handle_correct_prune_request) { replicaConfig.numBlocksToKeep_ = num_blocks_to_keep; replicaConfig.replicaId = replica_idx; replicaConfig.pruningEnabled_ = true; - replicaConfig.replicaPrivateKey = privateKey_1; + replicaConfig.replicaPrivateKey = keyPair[1].first; TestStorage storage(db); auto &blocks_deleter = storage; @@ -834,7 +570,7 @@ TEST_F(test_rocksdb, sm_handle_incorrect_prune_request) { replicaConfig.numBlocksToKeep_ = num_blocks_to_keep; replicaConfig.replicaId = replica_idx; replicaConfig.pruningEnabled_ = true; - replicaConfig.replicaPrivateKey = privateKey_1; + replicaConfig.replicaPrivateKey = keyPair[1].first; TestStorage storage(db); auto &blocks_deleter = storage; InitBlockchainStorage(replica_count, storage); diff --git a/kvbc/tools/db_editor/include/kv_blockchain_db_editor.hpp b/kvbc/tools/db_editor/include/kv_blockchain_db_editor.hpp index ea2770a85a..a0ca71473b 100644 --- a/kvbc/tools/db_editor/include/kv_blockchain_db_editor.hpp +++ b/kvbc/tools/db_editor/include/kv_blockchain_db_editor.hpp @@ -30,7 +30,7 @@ #include "bcstatetransfer/SimpleBCStateTransfer.hpp" #include "bftengine/PersistentStorageImp.hpp" #include "bftengine/DbMetadataStorage.hpp" -#include "crypto_utils.hpp" +#include "crypto/factory.hpp" #include "json_output.hpp" #include "bftengine/ReplicaSpecificInfoManager.hpp" #include "kvbc_adapter/replica_adapter.hpp" @@ -365,9 +365,10 @@ struct VerifyBlockRequests { out << "\t\t\"signature_digest\": \"" << hex_digest << "\",\n"; out << "\t\t\"persistency_type\": \"" << persistencyType(req.requestPersistencyType) << "\",\n"; std::string verification_result; - auto verifier = std::make_unique( + const auto verifier = concord::crypto::Factory::getVerifier( client_keys.ids_to_keys[req.clientId].key, - (concord::util::crypto::KeyFormat)client_keys.ids_to_keys[req.clientId].format); + bftEngine::ReplicaConfig::instance().replicaMsgSigningAlgo, + (concord::crypto::KeyFormat)client_keys.ids_to_keys[req.clientId].format); if (req.requestPersistencyType == concord::messages::execution_data::EPersistecyType::RAW_ON_CHAIN) { auto result = verifier->verify(req.request, req.signature); @@ -1057,9 +1058,8 @@ struct VerifyDbCheckpoint { using CheckPointMsgStatus = std::vector>; using CheckpointDesc = bftEngine::bcst::impl::DataStore::CheckpointDesc; using BlockHashData = std::tuple; // - using IVerifier = concord::util::crypto::IVerifier; - using RSAVerifier = concord::util::crypto::RSAVerifier; - using KeyFormat = concord::util::crypto::KeyFormat; + using IVerifier = concord::crypto::IVerifier; + using KeyFormat = concord::crypto::KeyFormat; using ReplicaId = uint16_t; const bool read_only = true; std::string description() const { @@ -1106,7 +1106,11 @@ struct VerifyDbCheckpoint { auto format = cmd.format; transform(format.begin(), format.end(), format.begin(), ::tolower); auto key_format = ((format == "hex") ? KeyFormat::HexaDecimalStrippedFormat : KeyFormat::PemFormat); - replica_keys.emplace(repId, std::make_unique(cmd.key, key_format)); + + replica_keys.emplace( + repId, + concord::crypto::Factory::getVerifier( + cmd.key, bftEngine::ReplicaConfig::instance().replicaMsgSigningAlgo, key_format)); }, *val); } diff --git a/kvbc/tools/object_store_utility/integrity_checker.cpp b/kvbc/tools/object_store_utility/integrity_checker.cpp index f081ea815e..3bc6690584 100644 --- a/kvbc/tools/object_store_utility/integrity_checker.cpp +++ b/kvbc/tools/object_store_utility/integrity_checker.cpp @@ -26,6 +26,7 @@ using namespace std::placeholders; using concordUtils::Status; using bftEngine::bcst::impl::BCStateTran; using kvbc::v1DirectKeyValue::S3StorageFactory; +using crypto::KeyFormat; void IntegrityChecker::initKeysConfig(const fs::path& keys_file) { LOG_DEBUG(logger_, keys_file); @@ -37,13 +38,14 @@ void IntegrityChecker::initKeysConfig(const fs::path& keys_file) { config.fVal = parser.get_value("f_val"); config.cVal = parser.get_value("c_val"); config.publicKeysOfReplicas.clear(); - auto rsaPublicKeys = parser.get_values("rsa_public_keys"); - if (rsaPublicKeys.size() < config.numReplicas) + const auto txnSignerPublicKeys = parser.get_values("replica_public_keys"); + + if (txnSignerPublicKeys.size() < config.numReplicas) throw std::runtime_error("number of replicas and number of replicas don't match: " + keys_file.string()); for (size_t i = 0; i < config.numReplicas; ++i) - config.publicKeysOfReplicas.insert(std::pair(i, rsaPublicKeys[i])); + config.publicKeysOfReplicas.insert(std::pair(i, txnSignerPublicKeys[i])); config.replicaId = config.numReplicas; // "my" replica id shouldn't match one of the regular replicas @@ -52,9 +54,9 @@ void IntegrityChecker::initKeysConfig(const fs::path& keys_file) { bftEngine::impl::SigManager::init(config.replicaId, "", /*private key*/ config.publicKeysOfReplicas, - util::crypto::KeyFormat::HexaDecimalStrippedFormat, + KeyFormat::HexaDecimalStrippedFormat, nullptr /*publicKeysOfClients*/, - util::crypto::KeyFormat::PemFormat, + KeyFormat::PemFormat, *repsInfo_); } diff --git a/logging/include/Logger.hpp b/logging/include/Logger.hpp index 16c9c334f6..b9947180ba 100644 --- a/logging/include/Logger.hpp +++ b/logging/include/Logger.hpp @@ -32,8 +32,10 @@ uint64_t getSeq(); extern logging::Logger GL; extern logging::Logger CNSUS; extern logging::Logger THRESHSIGN_LOG; +extern logging::Logger OPENSSL_LOG; extern logging::Logger BLS_LOG; extern logging::Logger EDDSA_MULTISIG_LOG; +extern logging::Logger EDDSA_SIG_LOG; extern logging::Logger KEY_EX_LOG; extern logging::Logger CAT_BLOCK_LOG; extern logging::Logger V4_BLOCK_LOG; diff --git a/logging/src/Logger.cpp b/logging/src/Logger.cpp index 11c3e609a4..0c364d1f30 100644 --- a/logging/src/Logger.cpp +++ b/logging/src/Logger.cpp @@ -30,6 +30,8 @@ logging::Logger CNSUS = logging::getLogger("concord.bft.consensus"); logging::Logger THRESHSIGN_LOG = logging::getLogger("concord.bft.threshsign"); logging::Logger BLS_LOG = logging::getLogger("concord.bft.threshsign.bls"); logging::Logger EDDSA_MULTISIG_LOG = logging::getLogger("threshsign.eddsa"); +logging::Logger OPENSSL_LOG = logging::getLogger("concord.bft.openssl"); +logging::Logger EDDSA_SIG_LOG = logging::getLogger("singlesig.eddsa"); logging::Logger KEY_EX_LOG = logging::getLogger("concord.bft.key-exchange"); logging::Logger CAT_BLOCK_LOG = logging::getLogger("concord.kvbc.categorized-blockchain"); logging::Logger V4_BLOCK_LOG = logging::getLogger("concord.kvbc.v4-blockchain"); diff --git a/reconfiguration/include/reconfiguration/reconfiguration_handler.hpp b/reconfiguration/include/reconfiguration/reconfiguration_handler.hpp index bc7353a672..01dcd84c6d 100644 --- a/reconfiguration/include/reconfiguration/reconfiguration_handler.hpp +++ b/reconfiguration/include/reconfiguration/reconfiguration_handler.hpp @@ -18,7 +18,6 @@ #include "ireconfiguration.hpp" #include "OpenTracing.hpp" #include "SigManager.hpp" -#include "crypto_utils.hpp" namespace concord::reconfiguration { class BftReconfigurationHandler : public IReconfigurationHandler { @@ -26,7 +25,7 @@ class BftReconfigurationHandler : public IReconfigurationHandler { BftReconfigurationHandler(); bool verifySignature(uint32_t sender_id, const std::string &data, const std::string &signature) const override; - std::unique_ptr verifier_; + std::unique_ptr verifier_; }; class ReconfigurationHandler : public BftReconfigurationHandler { public: diff --git a/reconfiguration/src/reconfiguration_handler.cpp b/reconfiguration/src/reconfiguration_handler.cpp index 9b6e27221e..da33edd3dd 100644 --- a/reconfiguration/src/reconfiguration_handler.cpp +++ b/reconfiguration/src/reconfiguration_handler.cpp @@ -21,12 +21,17 @@ #include "communication/StateControl.hpp" #include "secrets_manager_plain.h" #include "bftengine/DbCheckpointManager.hpp" +#include "ReplicaConfig.hpp" +#include "crypto/factory.hpp" #include -using namespace concord::messages; namespace concord::reconfiguration { +using namespace concord::messages; +using concord::crypto::KeyFormat; +using concord::crypto::Factory; + bool ReconfigurationHandler::handle(const WedgeCommand& cmd, uint64_t bft_seq_num, uint32_t, @@ -329,8 +334,10 @@ BftReconfigurationHandler::BftReconfigurationHandler() { key_str.append(buf, 0, key_content.gcount()); } key_str.append(buf, 0, key_content.gcount()); - verifier_.reset(new concord::util::crypto::ECDSAVerifier(key_str, concord::util::crypto::KeyFormat::PemFormat)); + verifier_ = + Factory::getVerifier(key_str, bftEngine::ReplicaConfig::instance().operatorMsgSigningAlgo, KeyFormat::PemFormat); } + bool BftReconfigurationHandler::verifySignature(uint32_t sender_id, const std::string& data, const std::string& signature) const { @@ -363,7 +370,7 @@ bool ClientReconfigurationHandler::handle(const concord::messages::ClientExchang // assuming we always send hex DER over the wire for (const auto& clientId : affected_clients) bftEngine::impl::KeyExchangeManager::instance().onClientPublicKeyExchange( - msg.pub_key, concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat, clientId); + msg.pub_key, KeyFormat::HexaDecimalStrippedFormat, clientId); return true; } } // namespace concord::reconfiguration diff --git a/scripts/linux/create_concord_clients_transaction_signing_keys.sh b/scripts/linux/create_concord_clients_transaction_signing_keys.sh index d379cd1618..60c7c0b673 100755 --- a/scripts/linux/create_concord_clients_transaction_signing_keys.sh +++ b/scripts/linux/create_concord_clients_transaction_signing_keys.sh @@ -20,8 +20,10 @@ usage() { printf "\n-----\nhelp:\n-----\n" printf "%s\n\n" "-h --help, print this message" printf "%s\n\n" "-n --num_participants , mandatory" + printf "%s\n\n" "-a --algo_name, optional, default: eddsa" printf "%s\n\n" "-r --private_key_name , optional, default: transaction_signing_priv.pem" printf "%s\n\n" "-u --public_key_name , optional, default: transaction_signing_pub.pem" + printf "%s\n\n" "-d --output_folder , optional, default: transaction_signing_keys" printf "%s\n\t\t\t\t%s\n\t\t\t\t%s\n" "-o --output_base_path , optional, base path in relative/absolute format" \ "output is redirected to output_base_path/transaction_signing_keys folder" \ "default: ./transaction_signing_keys" @@ -33,6 +35,7 @@ parser() { output_folder="transaction_signing_keys" private_key_name="transaction_signing_priv.pem" public_key_name="transaction_signing_pub.pem" + algo_name="eddsa" while [ $1 ]; do case $1 in @@ -63,6 +66,16 @@ parser() { shift 2 ;; + -d | --output_folder) + output_folder="$2" + shift 2 + ;; + + -a | --algo_name) + algo_name="$2" + shift 2 + ;; + *) echo "error: unknown input $1!" >&2 usage @@ -107,15 +120,26 @@ parser $@ mkdir -p ${output_path} -for ((i=1; i<=${num_participants}; i++)); do - current_path=${output_path}/${i} - mkdir ${current_path} - openssl genrsa -out ${current_path}/${private_key_name} 2048 > /dev/null - openssl rsa -in ${current_path}/${private_key_name} \ - -pubout \ - -out ${current_path}/${public_key_name} > /dev/null -done +case "$algo_name" in + "rsa") + for ((i=1; i<=${num_participants}; i++)); do + current_path=${output_path}/${i} + mkdir ${current_path} + openssl genrsa -out ${current_path}/${private_key_name} 2048 > /dev/null + openssl rsa -in ${current_path}/${private_key_name} \ + -pubout \ + -out ${current_path}/${public_key_name} > /dev/null + done;; + + "eddsa") + for ((i=1; i<=${num_participants}; i++)); do + current_path=${output_path}/${i} + mkdir ${current_path} + openssl genpkey -algorithm ed25519 -outform PEM -out ${current_path}/${private_key_name} > /dev/null + openssl pkey -in ${current_path}/${private_key_name} \ + -pubout \ + -out ${current_path}/${public_key_name} > /dev/null + done;; +esac echo "Done, keys are under ${output_path}" - - diff --git a/secretsmanager/CMakeLists.txt b/secretsmanager/CMakeLists.txt index ac27ecf4f2..b2120006ac 100644 --- a/secretsmanager/CMakeLists.txt +++ b/secretsmanager/CMakeLists.txt @@ -21,12 +21,14 @@ else() find_package(cryptopp REQUIRED) endif() -target_link_libraries(secretsmanager PUBLIC ${CRYPTOPP_LIBRARIES}) +target_link_libraries(secretsmanager PUBLIC util ${CRYPTOPP_LIBRARIES}) target_include_directories(secretsmanager PUBLIC include ${CRYPTOPP_INCLUDE_DIRS}) target_include_directories(secretsmanager PRIVATE src) +target_include_directories(secretsmanager PUBLIC ../bftengine/include/bftengine) -target_link_libraries(secretsmanager_shared PUBLIC ${CRYPTOPP_LIBRARIES}) +target_link_libraries(secretsmanager_shared PUBLIC util_shared ${CRYPTOPP_LIBRARIES}) target_include_directories(secretsmanager_shared PUBLIC include ${CRYPTOPP_INCLUDE_DIRS}) +target_include_directories(secretsmanager_shared PUBLIC ../bftengine/include/bftengine) if (USE_JSON AND USE_HTTPLIB) add_subdirectory(secretretriever) diff --git a/secretsmanager/src/aes.cpp b/secretsmanager/src/aes.cpp index f8644d7bf6..bd3f60b3fd 100644 --- a/secretsmanager/src/aes.cpp +++ b/secretsmanager/src/aes.cpp @@ -14,31 +14,104 @@ // This convenience header combines different block implementations. #include "aes.h" +#include "openssl_crypto.hpp" +#include "assertUtils.hpp" +#include "ReplicaConfig.hpp" +#include #include -#include "assertUtils.hpp" - namespace concord::secretsmanager { +using std::vector; +using std::string; +using std::unique_ptr; +using concord::util::openssl_utils::OPENSSL_SUCCESS; +using concord::util::openssl_utils::UniqueOpenSSLCipherContext; +using bftEngine::ReplicaConfig; +using concord::crypto::SIGN_VERIFY_ALGO; -AES_CBC::AES_CBC(KeyParams& params) { - ConcordAssertEQ(params.key.size(), 256 / 8); - aesEncryption = CryptoPP::AES::Encryption(params.key.data(), params.key.size()); - aesDecryption = CryptoPP::AES::Decryption(params.key.data(), params.key.size()); - enc = CryptoPP::CBC_Mode_ExternalCipher::Encryption(aesEncryption, params.iv.data()); - dec = CryptoPP::CBC_Mode_ExternalCipher::Decryption(aesDecryption, params.iv.data()); +AES_CBC::AES_CBC(const KeyParams& params) { + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + ConcordAssertEQ(params.key.size(), 256 / 8); + aesEncryption = CryptoPP::AES::Encryption(params.key.data(), params.key.size()); + aesDecryption = CryptoPP::AES::Decryption(params.key.data(), params.key.size()); + enc = CryptoPP::CBC_Mode_ExternalCipher::Encryption(aesEncryption, params.iv.data()); + dec = CryptoPP::CBC_Mode_ExternalCipher::Decryption(aesDecryption, params.iv.data()); + } else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + key = params.key; + iv = params.iv; + } } -std::vector AES_CBC::encrypt(const std::string& input) { - std::vector cipher; - CryptoPP::StringSource ss( - input, true, new CryptoPP::StreamTransformationFilter(enc, new CryptoPP::VectorSink(cipher))); - return cipher; -} -std::string AES_CBC::decrypt(const std::vector& cipher) { - std::string pt; - CryptoPP::VectorSource ss(cipher, true, new CryptoPP::StreamTransformationFilter(dec, new CryptoPP::StringSink(pt))); - return pt; +vector AES_CBC::encrypt(const string& input) { + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + vector cipher; + CryptoPP::StringSource ss( + input, true, new CryptoPP::StreamTransformationFilter(enc, new CryptoPP::VectorSink(cipher))); + return cipher; + } else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + if (input.empty()) { + return {}; + } + + unique_ptr ciphertext(new unsigned char[input.size() + AES_BLOCK_SIZE]); + unique_ptr plaintext(new unsigned char[input.size() + 1]); + + for (size_t i{0UL}; i < input.size(); ++i) { + plaintext.get()[i] = (unsigned char)input[i]; + } + + UniqueOpenSSLCipherContext ctx(EVP_CIPHER_CTX_new()); + ConcordAssert(nullptr != ctx); + + int c_len{0}; + int f_len{0}; + + ConcordAssert(OPENSSL_SUCCESS == EVP_EncryptInit_ex(ctx.get(), EVP_aes_256_cbc(), nullptr, key.data(), iv.data())); + ConcordAssert(OPENSSL_SUCCESS == + EVP_EncryptUpdate(ctx.get(), ciphertext.get(), &c_len, plaintext.get(), input.size())); + ConcordAssert(OPENSSL_SUCCESS == EVP_EncryptFinal_ex(ctx.get(), ciphertext.get() + c_len, &f_len)); + + const int encryptedMsgLen = c_len + f_len; + vector cipher(encryptedMsgLen); + memcpy(&cipher[0], ciphertext.get(), encryptedMsgLen); + return cipher; + } + return {}; } -} // namespace concord::secretsmanager \ No newline at end of file +string AES_CBC::decrypt(const vector& cipher) { + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + string pt; + CryptoPP::VectorSource ss( + cipher, true, new CryptoPP::StreamTransformationFilter(dec, new CryptoPP::StringSink(pt))); + return pt; + } else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + if (cipher.capacity() == 0) { + return {}; + } + + const int cipherLength = cipher.capacity(); + int c_len{0}, f_len{0}; + + unique_ptr plaintext(new unsigned char[cipherLength]); + UniqueOpenSSLCipherContext ctx(EVP_CIPHER_CTX_new()); + ConcordAssert(nullptr != ctx); + + ConcordAssert(OPENSSL_SUCCESS == EVP_DecryptInit_ex(ctx.get(), EVP_aes_256_cbc(), nullptr, key.data(), iv.data())); + EVP_CIPHER_CTX_set_key_length(ctx.get(), EVP_MAX_KEY_LENGTH); + ConcordAssert( + OPENSSL_SUCCESS == + EVP_DecryptUpdate(ctx.get(), plaintext.get(), &c_len, (const unsigned char*)cipher.data(), cipherLength)); + ConcordAssert(OPENSSL_SUCCESS == EVP_DecryptFinal_ex(ctx.get(), plaintext.get() + c_len, &f_len)); + + const int plainMsgLen = c_len + f_len; + plaintext.get()[plainMsgLen] = 0; + + vector plaintxt(plainMsgLen); + memcpy(&plaintxt[0], plaintext.get(), plainMsgLen); + return string(plaintxt.begin(), plaintxt.end()); + } + return {}; +} +} // namespace concord::secretsmanager diff --git a/secretsmanager/src/aes.h b/secretsmanager/src/aes.h index f7c966d29f..9899d87e46 100644 --- a/secretsmanager/src/aes.h +++ b/secretsmanager/src/aes.h @@ -31,12 +31,13 @@ class AES_CBC { CryptoPP::AES::Decryption aesDecryption; CryptoPP::CBC_Mode_ExternalCipher::Encryption enc; CryptoPP::CBC_Mode_ExternalCipher::Decryption dec; + std::vector key; + std::vector iv; public: - static size_t getBlockSize() { return CryptoPP::AES::BLOCKSIZE; } - AES_CBC(KeyParams& params); + AES_CBC(const KeyParams& params); std::vector encrypt(const std::string& input); std::string decrypt(const std::vector& cipher); }; -} // namespace concord::secretsmanager \ No newline at end of file +} // namespace concord::secretsmanager diff --git a/secretsmanager/src/base64.cpp b/secretsmanager/src/base64.cpp index 2c9dd9f321..ece23c5fa4 100644 --- a/secretsmanager/src/base64.cpp +++ b/secretsmanager/src/base64.cpp @@ -14,27 +14,102 @@ // This convenience header combines different block implementations. #include "base64.h" +#include "ReplicaConfig.hpp" #include #include namespace concord::secretsmanager { +using std::string; +using std::vector; +using std::string_view; +using bftEngine::ReplicaConfig; +using concord::crypto::SIGN_VERIFY_ALGO; -std::string base64Enc(const std::vector& cipher_text) { - CryptoPP::Base64Encoder encoder; - encoder.Put(cipher_text.data(), cipher_text.size()); - encoder.MessageEnd(); - uint64_t output_size = encoder.MaxRetrievable(); - std::string output(output_size, '0'); - encoder.Get((unsigned char*)output.data(), output.size()); +string base64Enc(const vector& msgBytes) { + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + CryptoPP::Base64Encoder encoder; + encoder.Put(msgBytes.data(), msgBytes.size()); + encoder.MessageEnd(); + uint64_t output_size = encoder.MaxRetrievable(); + string output(output_size, '0'); + encoder.Get((unsigned char*)output.data(), output.size()); - return output; + return output; + } else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + if (msgBytes.capacity() == 0) { + return {}; + } + BIO* b64 = BIO_new(BIO_f_base64()); + BIO* bio = BIO_new(BIO_s_mem()); + bio = BIO_push(b64, bio); + BIO_write(bio, msgBytes.data(), msgBytes.capacity()); + + BUF_MEM* bufferPtr{nullptr}; + BIO_get_mem_ptr(bio, &bufferPtr); + BIO_set_close(bio, BIO_NOCLOSE); + BIO_flush(bio); + BIO_free_all(bio); + + const auto msgLen = (*bufferPtr).length; + vector encodedMsg(msgLen); + memcpy(&encodedMsg[0], (*bufferPtr).data, msgLen); + BUF_MEM_free(bufferPtr); + return string(encodedMsg.begin(), encodedMsg.end()); + } + return {}; } -std::vector base64Dec(const std::string& input) { - std::vector dec; - CryptoPP::StringSource ss(input, true, new CryptoPP::Base64Decoder(new CryptoPP::VectorSink(dec))); +vector base64Dec(const string& b64message) { + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + vector dec; + CryptoPP::StringSource ss(b64message, true, new CryptoPP::Base64Decoder(new CryptoPP::VectorSink(dec))); + return dec; + } else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + const string b64msg(stripPemHeaderFooter(b64message, "-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----")); + + if (b64msg.empty()) { + return {}; + } + vector decodedOutput(calcDecodeLength(b64msg.data())); + + BIO* bio = BIO_new_mem_buf(b64msg.data(), -1); + BIO* b64 = BIO_new(BIO_f_base64()); + bio = BIO_push(b64, bio); + + const int outputLen = BIO_read(bio, decodedOutput.data(), b64msg.size()); + vector dec(outputLen); + memcpy(&dec[0], decodedOutput.data(), outputLen); + BIO_free_all(bio); + return dec; + } + return {}; +} + +size_t calcDecodeLength(const char* b64message) { + const size_t len{strlen(b64message)}; + size_t padding{0}; + + if ((b64message[len - 1] == '=') && (b64message[len - 2] == '=')) { // Check if the last 2 characters are '==' + padding = 2; + } else if (b64message[len - 1] == '=') { // Check if the last characters is '=' + padding = 1; + } + return (((len * 3) / 4) - padding); +} + +string stripPemHeaderFooter(const string_view b64message, const string_view header, const string_view footer) { + string strippedPemMsg(b64message); + auto pos1 = b64message.find(header); + + if (pos1 != string::npos) { + auto pos2 = b64message.find(footer, pos1 + 1); - return dec; + // Start position and header's length. + pos1 = pos1 + header.length(); + pos2 = pos2 - pos1 - 1; + strippedPemMsg = b64message.substr(pos1 + 1, pos2 - 1); + } + return strippedPemMsg; } -} // namespace concord::secretsmanager \ No newline at end of file +} // namespace concord::secretsmanager diff --git a/secretsmanager/src/base64.h b/secretsmanager/src/base64.h index d7d8a04f21..e8cd2b9287 100644 --- a/secretsmanager/src/base64.h +++ b/secretsmanager/src/base64.h @@ -18,9 +18,37 @@ #include #include +#include +#include +#include + namespace concord::secretsmanager { -std::string base64Enc(const std::vector& cipher_text); -std::vector base64Dec(const std::string& input); +/* + * Encode message to Base64 string. + * @param msgBytes (input) Message to be encoded. + * @return Base64 encoded message. + */ +std::string base64Enc(const std::vector& msgBytes); + +/* + * Decode Base64 string. + * @param b64message (input) Base64 encoded message. + * @return Decoded, but encrypted message. + */ +std::vector base64Dec(const std::string& b64message); + +size_t calcDecodeLength(const char* b64message); -} // namespace concord::secretsmanager \ No newline at end of file +/** + * @brief Extracts the message part of PEM file by deleting the HEADER and FOOTER parts, if exist. + * + * @param b64message Base64 encoded message. + * @param header Header to be removed. + * @param footer Footer to be removed. + * @return std::string Extracted message. + */ +std::string stripPemHeaderFooter(const std::string_view b64message, + const std::string_view header, + const std::string_view footer); +} // namespace concord::secretsmanager diff --git a/secretsmanager/src/key_params.cpp b/secretsmanager/src/key_params.cpp index 2af6594226..c7a410e6d3 100644 --- a/secretsmanager/src/key_params.cpp +++ b/secretsmanager/src/key_params.cpp @@ -1,12 +1,25 @@ #include "key_params.h" +#include "hex_tools.h" +#include "ReplicaConfig.hpp" +#include + +// CryptoPP headers. #include #include #include namespace concord::secretsmanager { +using bftEngine::ReplicaConfig; +using concord::crypto::SIGN_VERIFY_ALGO; + KeyParams::KeyParams(const std::string& pkey, const std::string& piv) { - CryptoPP::StringSource sskey(pkey, true, new CryptoPP::HexDecoder(new CryptoPP::VectorSink(key))); - CryptoPP::StringSource ssiv(piv, true, new CryptoPP::HexDecoder(new CryptoPP::VectorSink(iv))); + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + CryptoPP::StringSource sskey(pkey, true, new CryptoPP::HexDecoder(new CryptoPP::VectorSink(key))); + CryptoPP::StringSource ssiv(piv, true, new CryptoPP::HexDecoder(new CryptoPP::VectorSink(iv))); + } else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + key = concordUtils::unhex(pkey); + iv = concordUtils::unhex(piv); + } } -} // namespace concord::secretsmanager \ No newline at end of file +} // namespace concord::secretsmanager diff --git a/secretsmanager/src/key_params.h b/secretsmanager/src/key_params.h index 5025d0d36e..5ee08dbee2 100644 --- a/secretsmanager/src/key_params.h +++ b/secretsmanager/src/key_params.h @@ -28,4 +28,4 @@ struct KeyParams { std::vector iv; }; -} // namespace concord::secretsmanager \ No newline at end of file +} // namespace concord::secretsmanager diff --git a/secretsmanager/src/secrets_manager_enc.cpp b/secretsmanager/src/secrets_manager_enc.cpp index 0b0369f75c..b31754800b 100644 --- a/secretsmanager/src/secrets_manager_enc.cpp +++ b/secretsmanager/src/secrets_manager_enc.cpp @@ -17,6 +17,7 @@ #include "aes.h" #include "base64.h" +#include "assertUtils.hpp" namespace concord::secretsmanager { @@ -32,6 +33,9 @@ SecretsManagerEnc::SecretsManagerEnc(const SecretData& secrets) } bool SecretsManagerEnc::encryptFile(std::string_view file_path, const std::string& input) { + if (file_path.empty()) { + return false; + } auto ct_encoded = encrypt(input); if (!ct_encoded.has_value()) { return false; @@ -50,6 +54,9 @@ bool SecretsManagerEnc::encryptFile(std::string_view file_path, const std::strin std::optional SecretsManagerEnc::encryptString(const std::string& input) { return encrypt(input); } std::optional SecretsManagerEnc::decryptFile(std::string_view path) { + if (path.empty()) { + return std::nullopt; + } std::string data; try { data = readFile(path); @@ -76,21 +83,25 @@ std::optional SecretsManagerEnc::decryptFile(const std::ifstream& f std::optional SecretsManagerEnc::decryptString(const std::string& input) { return decrypt(input); } std::optional SecretsManagerEnc::decrypt(const std::string& data) { + if (data.empty()) { + return std::nullopt; + } try { - // AES_CBC is created on each call fir thread safety + // AES_CBC is created on each call for thread safety auto aes = AES_CBC(*key_params_); auto cipher_text = base64Dec(data); auto pt = aes.decrypt(cipher_text); - return std::optional{pt}; } catch (std::exception& e) { LOG_ERROR(logger_, "Decryption error: " << e.what()); } - return std::nullopt; } std::optional SecretsManagerEnc::encrypt(const std::string& data) { + if (data.empty()) { + return std::nullopt; + } try { // AES_CBC is created on each call fir thread safety auto aes = AES_CBC(*key_params_); @@ -99,10 +110,9 @@ std::optional SecretsManagerEnc::encrypt(const std::string& data) { } catch (std::exception& e) { LOG_ERROR(logger_, "Encryption error: " << e.what()); } - return std::nullopt; } SecretsManagerEnc::~SecretsManagerEnc() {} -} // namespace concord::secretsmanager \ No newline at end of file +} // namespace concord::secretsmanager diff --git a/secretsmanager/test/secrets_manager_test.cpp b/secretsmanager/test/secrets_manager_test.cpp index 1cfb1e7164..1cf6cad0a5 100644 --- a/secretsmanager/test/secrets_manager_test.cpp +++ b/secretsmanager/test/secrets_manager_test.cpp @@ -4,6 +4,8 @@ #include "aes.h" #include "secrets_manager_enc.h" #include "secrets_manager_plain.h" +#include "Logger.hpp" +#include "kvstream.h" using namespace concord::secretsmanager; @@ -60,6 +62,9 @@ TEST(SecretsManager, StringToHex) { EXPECT_THAT(key_params.iv, testing::ContainerEq(expected_iv)); } +// The encrypted strings are generated using URLs: +// 1. https://cryptii.com/pipes/aes-encryption and +// 2. https://onlinehextools.com/convert-hex-to-ascii TEST(SecretsManager, Internals) { const std::string input{"This is a sample text"}; const std::string encrypted{"eIetIYAvY5EHsb2F7bDcHH8labEq5jrmyvW7DC2N904=\n"}; @@ -93,6 +98,14 @@ TEST(SecretsManager, Base64) { ASSERT_EQ(r, cipher_text); } +TEST(SecretsManager, EmptyFileTest) { + std::string filename; + auto sm = getSecretsManager(); + + ASSERT_FALSE(sm.encryptFile(filename, long_input)); + ASSERT_TRUE(std::optional{} == sm.decryptFile(filename)); +} + TEST(SecretsManager, FileTest) { std::string filename{"/tmp/secrets_manager_unit_test"}; auto sm = getSecretsManager(); @@ -103,7 +116,13 @@ TEST(SecretsManager, FileTest) { ASSERT_EQ(long_input, output); } -TEST(SecretsManager, EmptyInput) { +TEST(SecretsManager, EncryptEmptyInput) { + auto sm = getSecretsManager(); + auto res = sm.encryptString(""); + ASSERT_FALSE(res.has_value()); +} + +TEST(SecretsManager, DecryptEmptyInput) { auto sm = getSecretsManager(); auto res = sm.decryptString(""); ASSERT_FALSE(res.has_value()); diff --git a/tests/apollo/test_skvbc_multi_sig.py b/tests/apollo/test_skvbc_multi_sig.py index 808b3a6220..e4856c90b4 100644 --- a/tests/apollo/test_skvbc_multi_sig.py +++ b/tests/apollo/test_skvbc_multi_sig.py @@ -47,7 +47,7 @@ class SkvbcMultiSig(ApolloTest): @with_bft_network(start_replica_cmd, selected_configs=lambda n, f, c: n == 7, rotate_keys=True ) async def test_happy_initial_key_exchange(self, bft_network): """ - Validates that if all replicas are up and all key-exchnage msgs reached consensus via the fast path + Validates that if all replicas are up and all key-exchange msgs reached consensus via the fast path then the counter of the exchanged keys is equal to the cluster size in all replicas. """ bft_network.start_all_replicas() @@ -177,7 +177,7 @@ async def test_reload_fast_path_after_key_exchange(self, bft_network): @with_trio @with_bft_network(start_replica_cmd, selected_configs=lambda n, f, c: n == 7, rotate_keys=True) - async def test_reload_slows_path_after_key_exchange(self, bft_network): + async def test_reload_slow_path_after_key_exchange(self, bft_network): bft_network.start_all_replicas() skvbc = kvbc.SimpleKVBCProtocol(bft_network) diff --git a/tests/apollo/util/bft.py b/tests/apollo/util/bft.py index 50934538fa..924d8129ef 100644 --- a/tests/apollo/util/bft.py +++ b/tests/apollo/util/bft.py @@ -504,16 +504,30 @@ def _generate_operator_keys(self): if self.builddir is None: return with open(self.builddir + "/operator_pub.pem", 'w') as f: + # EdDSA public key. + f.write("-----BEGIN PUBLIC KEY-----\n" + "MCowBQYDK2VwAyEAq6x6mTckhvzscZmDtRAwgneYpIE3sqkdLdaZ4B5JBbw=\n" + "-----END PUBLIC KEY-----") + """ + # ECDSA public key. f.write("-----BEGIN PUBLIC KEY-----\n" "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENEMHcbJgnnYxfa1zDlIF7lzp/Ioa" "NfwGuJpAg84an5FdPALwZwBp/m/X3d8kwmfZEytqt2PGMNhHMkovIaRI1A==\n" "-----END PUBLIC KEY-----") + """ with open(self.builddir + "/operator_priv.pem", 'w') as f: + # EdDSA private key. + f.write("-----BEGIN PRIVATE KEY-----\n" + "MC4CAQAwBQYDK2VwBCIEIIIyaCtHzqPqMdvvcTIp+ZtOGccurc7e8qMPs8+jt0xo\n" + "-----END PRIVATE KEY-----") + """ + # ECDSA private key. f.write("-----BEGIN EC PRIVATE KEY-----\n" "MHcCAQEEIEWf8ZTkCWbdA9WrMSNGCC7GQxvSXiDlU6dlZAi6JaCboAoGCCqGSM49" "AwEHoUQDQgAENEMHcbJgnnYxfa1zDlIF7lzp/IoaNfwGuJpAg84an5FdPALwZwBp" "/m/X3d8kwmfZEytqt2PGMNhHMkovIaRI1A==\n" "-----END EC PRIVATE KEY-----") + """ def generate_tls_certs(self, num_to_generate, start_index=0): """ diff --git a/tests/apollo/util/operator.py b/tests/apollo/util/operator.py index 3e7542db2f..721654b36c 100644 --- a/tests/apollo/util/operator.py +++ b/tests/apollo/util/operator.py @@ -20,25 +20,37 @@ sys.path.append(os.path.abspath("../../util/pyclient")) +from cryptography.hazmat.primitives import serialization + import bft_client -from ecdsa import SigningKey -from ecdsa import SECP256k1 -import hashlib -from Crypto.PublicKey import RSA +#from ecdsa import SigningKey +#from ecdsa import SECP256k1 +#import hashlib import util.eliot_logging as log - class Operator: def __init__(self, config, client, priv_key_dir): self.config = config self.client = client - with open(priv_key_dir + "/operator_priv.pem") as f: - self.private_key = SigningKey.from_pem(f.read(), hashlib.sha256) - def _sign_reconf_msg(self, msg): - return self.private_key.sign_deterministic(msg.serialize()) + # Read ECDSA signing key. + # with open(priv_key_dir + "/operator_priv.pem") as f: + # self.private_key = SigningKey.from_pem(f.read(), hashlib.sha256) + # Read EdDSA signing key. + txn_signing_key_path = priv_key_dir + "/operator_priv.pem" + if txn_signing_key_path: + with open(txn_signing_key_path, 'rb') as f: + self.private_key = serialization.load_pem_private_key(f.read(), password=None) + + def _sign_reconf_msg(self, msg): + signature = b'' + if self.private_key: + signature = self.private_key.sign(bytes(msg.serialize())) + return signature + # Return ECDSA signature. + # return self.private_key.sign_deterministic(msg.serialize()) def _construct_basic_reconfiguration_request(self, command): reconf_msg = cmf_msgs.ReconfigurationRequest() @@ -50,10 +62,10 @@ def _construct_basic_reconfiguration_request(self, command): return reconf_msg def _construct_reconfiguration_wedge_command(self): - wedge_cmd = cmf_msgs.WedgeCommand() - wedge_cmd.sender = 1000 - wedge_cmd.noop = False - return self._construct_basic_reconfiguration_request(wedge_cmd) + wedge_cmd = cmf_msgs.WedgeCommand() + wedge_cmd.sender = 1000 + wedge_cmd.noop = False + return self._construct_basic_reconfiguration_request(wedge_cmd) def _construct_reconfiguration_latest_prunebale_block_command(self): lpab_cmd = cmf_msgs.LatestPrunableBlockRequest() diff --git a/tests/simpleKVBC/TesterCRE/main.cpp b/tests/simpleKVBC/TesterCRE/main.cpp index 4e50169654..4bf1fbfd06 100644 --- a/tests/simpleKVBC/TesterCRE/main.cpp +++ b/tests/simpleKVBC/TesterCRE/main.cpp @@ -21,7 +21,6 @@ #include "client/reconfiguration/config.hpp" #include "client/reconfiguration/poll_based_state_client.hpp" #include "client/reconfiguration/client_reconfiguration_engine.hpp" -#include "crypto_utils.hpp" #include "secrets_manager_plain.h" #include "secrets_manager_enc.h" #include "client/reconfiguration/default_handlers.hpp" diff --git a/thirdparty/include/picobench.h b/thirdparty/include/picobench.hpp similarity index 100% rename from thirdparty/include/picobench.h rename to thirdparty/include/picobench.hpp diff --git a/threshsign/bench/BenchmarkThreshsign.cpp b/threshsign/bench/BenchmarkThreshsign.cpp index e2405263ed..5d8584125b 100644 --- a/threshsign/bench/BenchmarkThreshsign.cpp +++ b/threshsign/bench/BenchmarkThreshsign.cpp @@ -28,7 +28,7 @@ #pragma GCC diagnostic ignored "-Wsign-compare" #pragma GCC diagnostic ignored "-Wunused-variable" #pragma GCC diagnostic ignored "-Wc99-extensions" -#include "picobench.h" +#include "picobench.hpp" #include "macros.h" #include "include/threshsign/eddsa/EdDSAMultisigFactory.h" #include "include/threshsign/eddsa/SingleEdDSASignature.h" @@ -276,4 +276,4 @@ int main(int argc, char* argv[]) { return runner.run(picobenchSeed); } -#pragma GCC diagnostic pop \ No newline at end of file +#pragma GCC diagnostic pop diff --git a/threshsign/include/threshsign/ThresholdSignaturesTypes.h b/threshsign/include/threshsign/ThresholdSignaturesTypes.h index e4d7d4ebb2..de5ac36fd8 100644 --- a/threshsign/include/threshsign/ThresholdSignaturesTypes.h +++ b/threshsign/include/threshsign/ThresholdSignaturesTypes.h @@ -63,7 +63,6 @@ class Cryptosystem { // Internally used helper functions. IThresholdFactory* createThresholdFactory(); - void validateKey(const std::string& key, size_t expectedSize) const; void validatePublicKey(const std::string& key) const; void validateVerificationKey(const std::string& key) const; void validatePrivateKey(const std::string& key) const; diff --git a/threshsign/include/threshsign/eddsa/EdDSAMultisigSigner.h b/threshsign/include/threshsign/eddsa/EdDSAMultisigSigner.h index 21322e46f1..fcc5b8dbe7 100644 --- a/threshsign/include/threshsign/eddsa/EdDSAMultisigSigner.h +++ b/threshsign/include/threshsign/eddsa/EdDSAMultisigSigner.h @@ -13,9 +13,10 @@ #include "threshsign/IThresholdSigner.h" #include "EdDSAThreshsignKeys.h" -#include "crypto/eddsa/EdDSASigner.hpp" +#include "crypto/openssl/EdDSASigner.hpp" -class EdDSAMultisigSigner : public IThresholdSigner, public EdDSASigner { +class EdDSAMultisigSigner : public IThresholdSigner, + public concord::crypto::openssl::EdDSASigner { public: EdDSAMultisigSigner(const EdDSAThreshsignPrivateKey &privateKey, const uint32_t id); int requiredLengthForSignedData() const override; diff --git a/threshsign/include/threshsign/eddsa/EdDSAMultisigVerifier.h b/threshsign/include/threshsign/eddsa/EdDSAMultisigVerifier.h index faf47f5d72..21af0a6bc2 100644 --- a/threshsign/include/threshsign/eddsa/EdDSAMultisigVerifier.h +++ b/threshsign/include/threshsign/eddsa/EdDSAMultisigVerifier.h @@ -12,7 +12,7 @@ #pragma once #include "threshsign/IThresholdVerifier.h" #include "SingleEdDSASignature.h" -#include "crypto/eddsa/EdDSAVerifier.hpp" +#include "crypto/openssl/EdDSAVerifier.hpp" #include "EdDSAThreshsignKeys.h" class EdDSAMultisigVerifier; @@ -45,7 +45,7 @@ class EdDSASignatureAccumulator : public IThresholdAccumulator { class EdDSAMultisigVerifier : public IThresholdVerifier { public: - using SingleVerifier = EdDSAVerifier; + using SingleVerifier = concord::crypto::openssl::EdDSAVerifier; EdDSAMultisigVerifier(const std::vector &verifiers, const size_t signersCount, const size_t threshold); diff --git a/threshsign/include/threshsign/eddsa/EdDSAThreshsignKeys.h b/threshsign/include/threshsign/eddsa/EdDSAThreshsignKeys.h index f8599768f5..7c01b1867c 100644 --- a/threshsign/include/threshsign/eddsa/EdDSAThreshsignKeys.h +++ b/threshsign/include/threshsign/eddsa/EdDSAThreshsignKeys.h @@ -12,16 +12,18 @@ #pragma once #include "threshsign/IPublicKey.h" #include "threshsign/ISecretKey.h" -#include "crypto/eddsa/EdDSA.h" +#include "crypto/openssl/EdDSA.hpp" -class EdDSAThreshsignPrivateKey : public IShareSecretKey, public EdDSAPrivateKey { +class EdDSAThreshsignPrivateKey : public IShareSecretKey, public concord::util::crypto::openssl::EdDSAPrivateKey { public: - EdDSAThreshsignPrivateKey(const EdDSAThreshsignPrivateKey::ByteArray& arr) : EdDSAPrivateKey(arr) {} + EdDSAThreshsignPrivateKey(const EdDSAThreshsignPrivateKey::ByteArray& arr) + : concord::util::crypto::openssl::EdDSAPrivateKey(arr) {} std::string toString() const override { return toHexString(); } }; -class EdDSAThreshsignPublicKey : public IShareVerificationKey, public EdDSAPublicKey { +class EdDSAThreshsignPublicKey : public IShareVerificationKey, public concord::util::crypto::openssl::EdDSAPublicKey { public: - EdDSAThreshsignPublicKey(const EdDSAThreshsignPublicKey::ByteArray& arr) : EdDSAPublicKey(arr) {} + EdDSAThreshsignPublicKey(const EdDSAThreshsignPublicKey::ByteArray& arr) + : concord::util::crypto::openssl::EdDSAPublicKey(arr) {} std::string toString() const override { return toHexString(); } }; \ No newline at end of file diff --git a/threshsign/src/ThresholdSignaturesTypes.cpp b/threshsign/src/ThresholdSignaturesTypes.cpp index a30836f1cd..3b7a8d3d1e 100644 --- a/threshsign/src/ThresholdSignaturesTypes.cpp +++ b/threshsign/src/ThresholdSignaturesTypes.cpp @@ -18,8 +18,9 @@ #include "yaml_utils.hpp" #include "Logger.hpp" #include "string.hpp" +#include "crypto.hpp" -using concord::util::isValidHexString; +using concord::crypto::isValidKey; Cryptosystem::Cryptosystem(const std::string& sysType, const std::string& sysSubtype, @@ -223,45 +224,37 @@ IThresholdSigner* Cryptosystem::createThresholdSigner() { return factory->newSigner(signerID_, privateKeys_.front().c_str()); } -void Cryptosystem::validateKey(const std::string& key, size_t expectedSize) const { - auto isValidHex = isValidHexString(key); - if ((expectedSize == 0 || (key.length() == expectedSize)) && isValidHex) { - return; - } - - throw std::runtime_error("Invalid key for this cryptosystem (type " + type_ + " and subtype " + subtype_ + - "): " + key + " expected key size: " + std::to_string(expectedSize) + ", Actual key size: " + - std::to_string(key.length()) + ", IsValidHex: " + std::to_string(isValidHex)); -} - void Cryptosystem::validatePublicKey(const std::string& key) const { #ifdef USE_EDDSA_OPENSSL UNUSED(key); return; #else constexpr const size_t expectedKeyLength = 130u; - validateKey(key, expectedKeyLength); + auto keyType = type_ + " " + subtype_ + " public"; + isValidKey(keyType, key, expectedKeyLength); #endif } void Cryptosystem::validateVerificationKey(const std::string& key) const { #ifdef USE_EDDSA_OPENSSL - constexpr const size_t expectedKeyLength = EdDSAPublicKeyByteSize * 2; + constexpr const size_t expectedKeyLength = concord::util::crypto::openssl::EdDSAPublicKeyByteSize * 2; #else constexpr const size_t expectedKeyLength = 130u; #endif - validateKey(key, expectedKeyLength); + auto keyType = type_ + " " + subtype_ + " verification"; + isValidKey(keyType, key, expectedKeyLength); } void Cryptosystem::validatePrivateKey(const std::string& key) const { #ifdef USE_EDDSA_OPENSSL - constexpr const size_t expectedKeyLength = EdDSAPrivateKeyByteSize * 2; + constexpr const size_t expectedKeyLength = concord::util::crypto::openssl::EdDSAPrivateKeyByteSize * 2; #else // We currently do not validate the length of the private key's string // representation because the length of its serialization varies slightly. constexpr const size_t expectedKeyLength = 0; #endif - validateKey(key, expectedKeyLength); + auto keyType = type_ + " " + subtype_ + " private"; + isValidKey(keyType, key, expectedKeyLength); } bool Cryptosystem::isValidCryptosystemSelection(const std::string& type, const std::string& subtype) { @@ -350,7 +343,6 @@ Cryptosystem* Cryptosystem::fromConfiguration(std::istream& input, type = yaml::readValue(input, prefix + "_cryptosystem_type"); subtype = yaml::readValue(input, prefix + "_cryptosystem_subtype_parameter"); std::uint16_t numSigners = yaml::readValue(input, prefix + "_cryptosystem_num_signers"); - std::string publicKey = "uninitialized"; uint16_t threshold = 1; if (type == THRESHOLD_BLS_SCHEME || type == MULTISIG_EDDSA_SCHEME) threshold = yaml::readValue(input, prefix + "_cryptosystem_threshold"); diff --git a/threshsign/src/eddsa/EdDSAMultisigSigner.cpp b/threshsign/src/eddsa/EdDSAMultisigSigner.cpp index 08938e171b..a97c974e74 100644 --- a/threshsign/src/eddsa/EdDSAMultisigSigner.cpp +++ b/threshsign/src/eddsa/EdDSAMultisigSigner.cpp @@ -13,6 +13,8 @@ #include "threshsign/eddsa/EdDSAMultisigSigner.h" #include "threshsign/eddsa/SingleEdDSASignature.h" +using concord::crypto::openssl::EdDSASigner; + EdDSAMultisigSigner::EdDSAMultisigSigner(const EdDSAThreshsignPrivateKey &privateKey, const uint32_t id) : EdDSASigner{privateKey}, publicKey_{}, id_{id} {} @@ -31,5 +33,5 @@ void EdDSAMultisigSigner::signData(const char *hash, int hashLen, char *outSig, result.id = id_; std::memcpy(outSig, &result, sizeof(SingleEdDSASignature)); } -const IShareSecretKey &EdDSAMultisigSigner::getShareSecretKey() const { return getPrivKey(); } +const IShareSecretKey &EdDSAMultisigSigner::getShareSecretKey() const { return privateKey_; } const IShareVerificationKey &EdDSAMultisigSigner::getShareVerificationKey() const { return publicKey_; } \ No newline at end of file diff --git a/threshsign/src/eddsa/EdDSAMultisigVerifier.cpp b/threshsign/src/eddsa/EdDSAMultisigVerifier.cpp index 908ef4d839..5879174b8b 100644 --- a/threshsign/src/eddsa/EdDSAMultisigVerifier.cpp +++ b/threshsign/src/eddsa/EdDSAMultisigVerifier.cpp @@ -119,8 +119,8 @@ bool EdDSAMultisigVerifier::verify(const char *msg, int msgLen, const char *sig, int EdDSAMultisigVerifier::requiredLengthForSignedData() const { return static_cast(static_cast(signersCount_) * sizeof(SingleEdDSASignature)); } -const IPublicKey &EdDSAMultisigVerifier::getPublicKey() const { return verifiers_[0].getPubKey(); } +const IPublicKey &EdDSAMultisigVerifier::getPublicKey() const { return verifiers_[0].publicKey_; } const IShareVerificationKey &EdDSAMultisigVerifier::getShareVerificationKey(ShareID signer) const { - return verifiers_[static_cast(signer)].getPubKey(); + return verifiers_[static_cast(signer)].publicKey_; } size_t EdDSAMultisigVerifier::maxShareID() const { return signersCount_ + 1; } diff --git a/tools/GenerateConcordKeys.cpp b/tools/GenerateConcordKeys.cpp index 7366503cb0..501faa723e 100644 --- a/tools/GenerateConcordKeys.cpp +++ b/tools/GenerateConcordKeys.cpp @@ -23,6 +23,14 @@ #include "threshsign/ThresholdSignaturesTypes.h" #include "KeyfileIOUtils.hpp" #include "util/filesystem.hpp" +#include "crypto.hpp" + +using bftEngine::ReplicaConfig; +using concord::crypto::SIGN_VERIFY_ALGO; +using concord::crypto::cryptopp::RSA_SIGNATURE_LENGTH; +using concord::crypto::generateEdDSAKeyPair; +using concord::crypto::generateRsaKeyPair; + // Helper functions and static state to this executable's main function. static bool containsHelpOption(int argc, char** argv) { @@ -34,27 +42,6 @@ static bool containsHelpOption(int argc, char** argv) { return false; } -static CryptoPP::RandomPool sGlobalRandGen; -const unsigned int rsaKeyLength = 2048; - -static std::pair generateRsaKey() { - // Uses CryptoPP implementation of RSA key generation. - - std::pair keyPair; - - CryptoPP::RSAES>::Decryptor priv(sGlobalRandGen, rsaKeyLength); - CryptoPP::HexEncoder privEncoder(new CryptoPP::StringSink(keyPair.first)); - priv.AccessMaterial().Save(privEncoder); - privEncoder.MessageEnd(); - - CryptoPP::RSAES>::Encryptor pub(priv); - CryptoPP::HexEncoder pubEncoder(new CryptoPP::StringSink(keyPair.second)); - pub.AccessMaterial().Save(pubEncoder); - pubEncoder.MessageEnd(); - - return keyPair; -} - /** * Main function for the GenerateConcordKeys executable. Pseudorandomly * generates a new set of keys for a Concord deployment with given F and C @@ -114,7 +101,7 @@ int main(int argc, char** argv) { std::cout << usageMessage; return 0; } - bftEngine::ReplicaConfig& config = bftEngine::ReplicaConfig::instance(); + ReplicaConfig& config = ReplicaConfig::instance(); uint16_t n = 0; uint16_t ro = 0; std::string outputPrefix; @@ -201,10 +188,15 @@ int main(int argc, char** argv) { config.cVal = (n - (3 * config.fVal) - 1) / 2; - std::vector> rsaKeys; + std::vector> replicaKeyPairs; + for (uint16_t i = 0; i < n + ro; ++i) { - rsaKeys.push_back(generateRsaKey()); - config.publicKeysOfReplicas.insert(std::pair(i, rsaKeys[i].second)); + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + replicaKeyPairs.push_back(generateRsaKeyPair(RSA_SIGNATURE_LENGTH)); + } else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + replicaKeyPairs.push_back(generateEdDSAKeyPair()); + } + config.publicKeysOfReplicas.insert(std::pair(i, replicaKeyPairs[i].second)); } // We want to generate public key for n-out-of-n case @@ -216,14 +208,14 @@ int main(int argc, char** argv) { // Output the generated keys. for (uint16_t i = 0; i < n; ++i) { config.replicaId = i; - config.replicaPrivateKey = rsaKeys[i].first; + config.replicaPrivateKey = replicaKeyPairs[i].first; outputReplicaKeyfile(n, ro, config, outputPrefix + std::to_string(i), &cryptoSys); } for (uint16_t i = n; i < n + ro; ++i) { config.isReadOnly = true; config.replicaId = i; - config.replicaPrivateKey = rsaKeys[i].first; + config.replicaPrivateKey = replicaKeyPairs[i].first; outputReplicaKeyfile(n, ro, config, outputPrefix + std::to_string(i)); } } catch (std::exception& e) { diff --git a/tools/KeyfileIOUtils.cpp b/tools/KeyfileIOUtils.cpp index 824d8b1cfa..b70cfb4b63 100644 --- a/tools/KeyfileIOUtils.cpp +++ b/tools/KeyfileIOUtils.cpp @@ -20,10 +20,18 @@ #include #include "KeyfileIOUtils.hpp" #include "yaml_utils.hpp" +#include "crypto/openssl/EdDSA.hpp" +#include "crypto.hpp" + +using concord::crypto::isValidKey; +using bftEngine::ReplicaConfig; +using concord::crypto::SIGN_VERIFY_ALGO; +using concord::util::crypto::openssl::EdDSAPrivateKeyByteSize; +using concord::util::crypto::openssl::EdDSAPublicKeyByteSize; void outputReplicaKeyfile(uint16_t numReplicas, uint16_t numRoReplicas, - bftEngine::ReplicaConfig& config, + ReplicaConfig& config, const std::string& outputFilename, Cryptosystem* commonSys) { std::ofstream output(outputFilename); @@ -39,13 +47,21 @@ void outputReplicaKeyfile(uint16_t numReplicas, << "c_val: " << config.cVal << "\n" << "replica_id: " << config.replicaId << "\n" << "read-only: " << config.isReadOnly << "\n\n" - << "# RSA non-threshold replica public keys\n" - << "rsa_public_keys:\n"; + << "# Non-threshold replica public keys\n" + << "replica_public_keys:\n"; - for (auto& v : config.publicKeysOfReplicas) output << " - " << v.second << "\n"; + for (auto& v : config.publicKeysOfReplicas) { + output << " - " << v.second << "\n"; + } output << "\n"; - output << "rsa_private_key: " << config.replicaPrivateKey << "\n"; + output << "main_key_algorithm: "; + if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) { + output << "rsa\n"; + } else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) { + output << "eddsa\n"; + } + output << "replica_private_key: " << config.replicaPrivateKey << "\n"; if (commonSys) commonSys->writeConfiguration(output, "common", config.replicaId); } @@ -64,7 +80,7 @@ static void validateRSAPrivateKey(const std::string& key) { if (!std::regex_match(key, std::regex("[0-9A-Fa-f]+"))) throw std::runtime_error("Invalid RSA private key: " + key); } -Cryptosystem* inputReplicaKeyfileMultisig(const std::string& filename, bftEngine::ReplicaConfig& config) { +Cryptosystem* inputReplicaKeyfileMultisig(const std::string& filename, ReplicaConfig& config) { using namespace concord::util; std::ifstream input(filename); @@ -86,19 +102,34 @@ Cryptosystem* inputReplicaKeyfileMultisig(const std::string& filename, bftEngine if (config.replicaId >= config.numReplicas + config.numRoReplicas) throw std::runtime_error("replica IDs must be in the range [0, num_replicas + num_ro_replicas]"); - std::vector rsaPublicKeys = yaml::readCollection(input, "rsa_public_keys"); + const std::vector replicaPublicKeys(yaml::readCollection(input, "replica_public_keys")); - if (rsaPublicKeys.size() != config.numReplicas + config.numRoReplicas) - throw std::runtime_error("number of public RSA keys must match num_replicas"); + if (replicaPublicKeys.size() != config.numReplicas + config.numRoReplicas) + throw std::runtime_error("number of replica public keys must match num_replicas"); + + const auto mainKeyAlgo = yaml::readValue(input, "main_key_algorithm"); + if (mainKeyAlgo.empty()) { + throw std::runtime_error("main_key_algorithm value is empty."); + } + std::cout << "main_key_algorithm=" << mainKeyAlgo << std::endl; config.publicKeysOfReplicas.clear(); for (size_t i = 0; i < config.numReplicas + config.numRoReplicas; ++i) { - validateRSAPublicKey(rsaPublicKeys[i]); - config.publicKeysOfReplicas.insert(std::pair(i, rsaPublicKeys[i])); + if ("rsa" == mainKeyAlgo) { + validateRSAPublicKey(replicaPublicKeys[i]); + } else if ("eddsa" == mainKeyAlgo) { + constexpr const size_t expectedKeyLength = EdDSAPublicKeyByteSize * 2; + isValidKey("EdDSA public", replicaPublicKeys[i], expectedKeyLength); + } + config.publicKeysOfReplicas.insert(std::pair(i, replicaPublicKeys[i])); + } + config.replicaPrivateKey = yaml::readValue(input, "replica_private_key"); + if ("rsa" == mainKeyAlgo) { + validateRSAPrivateKey(config.replicaPrivateKey); + } else if ("eddsa" == mainKeyAlgo) { + constexpr const size_t expectedKeyLength = EdDSAPrivateKeyByteSize * 2; + isValidKey("EdDSA private", config.replicaPrivateKey, expectedKeyLength); } - - config.replicaPrivateKey = yaml::readValue(input, "rsa_private_key"); - validateRSAPrivateKey(config.replicaPrivateKey); if (config.isReadOnly) return nullptr; diff --git a/tools/README.md b/tools/README.md index b988e78937..901be75cd1 100644 --- a/tools/README.md +++ b/tools/README.md @@ -75,13 +75,13 @@ Parameter | Expected Value | Description `c_val` | non-negative integer | C parameter to the SBFT algorithm, that is, the maximum number of slow, crashed, or otherwise unresponsive replicas that can be tolerated before Concord must fall back to the slow path for committing transactions. `replica_id` | non-negative integer | Replica ID for the replica to which this keyfile belongs; replica IDs must be in the range [0, `num_replicas` - 1], inclusive, and no two replicas should have the same ID. -##### List of Public RSA Keys ##### +##### List of Replica Public Keys ##### -A list of public RSA keys is expected under the identifier `rsa_public_keys`: +A list of replica public keys is expected under the identifier `replica_public_keys`: Parameter | Expected Value | Description --- | --- | --- -`rsa_public_keys` | list of RSA keys in hexadecimal | A public RSA key for each replica for non-threshold cryptographic purposes. The keys should be in hexadecimal, and there should be as many keys as there are replicas. The keys should be given in ascending order of ID of the replica they belong to. +`replica_public_keys` | list of public keys in hexadecimal | A public key for each replica for non-threshold cryptographic purposes. The keys should be in hexadecimal, and there should be as many keys as there are replicas. The keys should be given in ascending order of ID of the replica they belong to. ##### Threshold Cryptosystem Public Configuration ##### diff --git a/tools/TestGeneratedKeys.cpp b/tools/TestGeneratedKeys.cpp index 4110bd7401..907ae9f333 100644 --- a/tools/TestGeneratedKeys.cpp +++ b/tools/TestGeneratedKeys.cpp @@ -21,7 +21,13 @@ #include "threshsign/IThresholdSigner.h" #include "threshsign/IThresholdVerifier.h" #include "KeyfileIOUtils.hpp" -#include "crypto_utils.hpp" +#include "crypto/factory.hpp" + +using concord::crypto::ISigner; +using concord::crypto::IVerifier; +using concord::crypto::Factory; +using concord::crypto::KeyFormat; +using bftEngine::ReplicaConfig; // How often to output status when testing cryptosystems, measured as an // interval measured in tested signaturs. @@ -122,31 +128,28 @@ static bool validateFundamentalFields(const std::vector& conf return true; } -// Helper function to test RSA keys to test the compatibility of a single key -// pair. -static bool testRSAKeyPair(const std::string& privateKey, const std::string& publicKey, uint16_t replicaID) { +// Helper function to test replica keys to test the compatibility of a single key pair. +static bool testReplicaKeyPair(const std::string& privateKey, const std::string& publicKey, uint16_t replicaID) { // The signer and verifier are stored with unique pointers rather than by // value so that they can be constructed in try/catch statements without // limiting their scope to those statements; declaring them by value is not // possible in this case becuause they lack paramter-less default // constructors. - std::unique_ptr signer; - std::unique_ptr verifier; + std::unique_ptr signer; + std::unique_ptr verifier; - std::string invalidPrivateKey = "FAILURE: Invalid RSA private key for replica " + std::to_string(replicaID) + ".\n"; - std::string invalidPublicKey = "FAILURE: Invalid RSA public key for replica " + std::to_string(replicaID) + ".\n"; + const std::string invalidPrivateKey = "FAILURE: Invalid private key for replica " + std::to_string(replicaID) + ".\n"; + const std::string invalidPublicKey = "FAILURE: Invalid public key for replica " + std::to_string(replicaID) + ".\n"; try { - signer.reset( - new concord::util::crypto::RSASigner(privateKey, concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat)); - } catch (std::exception& e) { + signer = Factory::getSigner(privateKey, ReplicaConfig::instance().replicaMsgSigningAlgo); + } catch (const std::exception& e) { std::cout << invalidPrivateKey; return false; } try { - verifier.reset( - new concord::util::crypto::RSAVerifier(publicKey, concord::util::crypto::KeyFormat::HexaDecimalStrippedFormat)); - } catch (std::exception& e) { + verifier = Factory::getVerifier(publicKey, ReplicaConfig::instance().replicaMsgSigningAlgo); + } catch (const std::exception& e) { std::cout << invalidPublicKey; return false; } @@ -158,9 +161,7 @@ static bool testRSAKeyPair(const std::string& privateKey, const std::string& pub try { sig = signer->sign(hash); if (sig.empty()) { - std::cout << "FAILURE: Failed to sign data with" - " replica " - << replicaID << "'s RSA private key.\n"; + std::cout << "FAILURE: Failed to sign data with replica " << replicaID << "'s private key.\n"; return false; } } catch (std::exception& e) { @@ -171,9 +172,7 @@ static bool testRSAKeyPair(const std::string& privateKey, const std::string& pub try { if (!verifier->verify(hash, sig)) { std::cout << "FAILURE: A signature with replica " << replicaID - << "'s RSA private key could not be verified with" - " replica " - << replicaID << "'s RSA public key.\n"; + << "'s private key could not be verified with replica " << replicaID << "'s public key.\n"; return false; } } catch (std::exception& e) { @@ -181,18 +180,17 @@ static bool testRSAKeyPair(const std::string& privateKey, const std::string& pub return false; } } - return true; } -// Test that the RSA key pairs given in the keyfiles work, that the keyfiles +// Test that the replica key pairs (could be RSA, or EdDSA key pair) given in the keyfiles work, that the keyfiles // agree on what the public keys are, and that there are no duplicates. -static bool testRSAKeys(const std::vector& configs) { +static bool testReplicaKeys(const std::vector& configs) { uint16_t numReplicas = configs.size(); - std::cout << "Testing " << numReplicas << " RSA key pairs...\n"; + std::cout << "Testing " << numReplicas << " replicas key pairs...\n"; std::unordered_map expectedPublicKeys; - std::unordered_set rsaPublicKeysSeen; + std::unordered_set replicaPublicKeysSeen; // Test that a signature produced with each replica's private key can be // verified with that replica's public key. @@ -206,44 +204,41 @@ static bool testRSAKeys(const std::vector& configs) { } } - if (!testRSAKeyPair(privateKey, publicKey, i)) { + if (!testReplicaKeyPair(privateKey, publicKey, i)) { return false; } - if (rsaPublicKeysSeen.count(publicKey) > 0) { + if (replicaPublicKeysSeen.count(publicKey) > 0) { uint16_t existingKeyholder; for (const auto& publicKeyEntry : expectedPublicKeys) { if (publicKeyEntry.second == publicKey) { existingKeyholder = publicKeyEntry.first; } } - std::cout << "FAILURE: Replicas " << existingKeyholder << " and " << i << " share the same RSA public key.\n"; + std::cout << "FAILURE: Replicas " << existingKeyholder << " and " << i << " share the same replica public key.\n"; return false; } expectedPublicKeys[i] = publicKey; if (((i + 1) % kTestProgressReportingInterval) == 0) { - std::cout << "Tested " << (i + 1) << " out of " << numReplicas << " RSA key pairs...\n"; + std::cout << "Tested " << (i + 1) << " out of " << numReplicas << " replica key pairs...\n"; } } - std::cout << "Verifying that all replicas agree on RSA public keys...\n"; + std::cout << "Verifying that all replicas agree on replica public keys...\n"; - // Verify that all replicas' keyfiles agree on the RSA public keys. + // Verify that all replicas' keyfiles agree on the replica public keys. for (uint16_t i = 0; i < numReplicas; ++i) { for (const auto& publicKeyEntry : configs[i].publicKeysOfReplicas) { if (publicKeyEntry.second != expectedPublicKeys[publicKeyEntry.first]) { - std::cout << "FAILURE: Replica " << i - << " has an" - " incorrect RSA public key for replica " + std::cout << "FAILURE: Replica " << i << " has an incorrect replica public key for replica " << publicKeyEntry.first << ".\n"; return false; } } } - std::cout << "All RSA key tests were successful.\n"; - + std::cout << "All replica key tests were successful.\n"; return true; } @@ -726,7 +721,8 @@ int main(int argc, char** argv) { } std::cout << "Cryptographic configurations read appear to be sane.\n"; std::cout << "Testing key functionality and agreement...\n"; - if (!testRSAKeys(configs)) { + + if (!testReplicaKeys(configs)) { return -1; } if (!testThresholdKeys(configs, cryptoSystems)) { diff --git a/util/CMakeLists.txt b/util/CMakeLists.txt index eb91e1ff7a..61e72ba6c6 100644 --- a/util/CMakeLists.txt +++ b/util/CMakeLists.txt @@ -11,18 +11,22 @@ set(util_source_files src/hex_tools.cpp src/OpenTracing.cpp src/throughput.cpp - src/crypto_utils.cpp + src/crypto.cpp + src/openssl/utils.cpp + src/crypto/cryptopp/signers.cpp + src/crypto/cryptopp/verifiers.cpp src/RawMemoryPool.cpp src/config_file_parser.cpp - src/cryptopp_digest_creator.cpp) + src/cryptopp/digest_creator.cpp + src/io.cpp) add_library(util STATIC ${util_source_files}) add_library(util_shared SHARED ${util_source_files}) # Use below macros to use CryptoPP's SHA_256 or OpenSSL's SHA_256 hashing. # USE_CRYPTOPP_SHA_256 -# USE_OPENSSL_SHA_256 -target_compile_definitions(util PUBLIC USE_OPENSSL_SHA3_256) -target_compile_definitions(util_shared PUBLIC USE_OPENSSL_SHA3_256) +# USE_OPENSSL_SHA3_256 +target_compile_definitions(util PUBLIC USE_OPENSSL_SHA_256) +target_compile_definitions(util_shared PUBLIC USE_OPENSSL_SHA_256) if(USE_OPENSSL) if(NOT BUILD_THIRDPARTY) @@ -43,11 +47,17 @@ else() find_package(cryptopp REQUIRED) endif() -target_link_libraries(util PUBLIC Threads::Threads ${CRYPTOPP_LIBRARIES}) -target_include_directories(util PUBLIC include ${CRYPTOPP_INCLUDE_DIRS}) +target_link_libraries(util PUBLIC + Threads::Threads ${CRYPTOPP_LIBRARIES} + stdc++fs) +# corebft +target_include_directories(util PUBLIC include ${CRYPTOPP_INCLUDE_DIRS} include/openssl) -target_link_libraries(util_shared PUBLIC Threads::Threads ${CRYPTOPP_LIBRARIES}) -target_include_directories(util_shared PUBLIC include ${CRYPTOPP_INCLUDE_DIRS}) +target_link_libraries(util_shared PUBLIC + Threads::Threads ${CRYPTOPP_LIBRARIES} + stdc++fs) +# corebft +target_include_directories(util_shared PUBLIC include ${CRYPTOPP_INCLUDE_DIRS} include/openssl) if(USE_OPENTRACING) if(NOT DEFINED OPENTRACING_INCLUDE_DIR) @@ -76,10 +86,7 @@ set(util_header_files include/SimpleThreadPool.hpp include/sliver.hpp include/status.hpp - include/string.hpp - include/openssl_crypto.hpp - include/digest.hpp - include/digest_type.hpp) + include/string.hpp) install(FILES ${util_header_files} DESTINATION include/util) set_property(DIRECTORY .. APPEND PROPERTY INCLUDE_DIRECTORIES @@ -101,3 +108,5 @@ if(USE_PROMETHEUS) util ) endif() + +add_subdirectory(bench) diff --git a/util/bench/CMakeLists.txt b/util/bench/CMakeLists.txt new file mode 100644 index 0000000000..a0c4458a9f --- /dev/null +++ b/util/bench/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.2) + +find_package(Boost ${MIN_BOOST_VERSION} COMPONENTS program_options REQUIRED) +add_executable(sign_verify_bench benchmarkSignVerify.cpp) + +target_link_libraries(sign_verify_bench + util + Boost::program_options + stdc++fs) + +target_include_directories(sign_verify_bench PUBLIC ../../thirdparty/include) diff --git a/util/bench/benchmarkSignVerify.cpp b/util/bench/benchmarkSignVerify.cpp new file mode 100644 index 0000000000..5498766f85 --- /dev/null +++ b/util/bench/benchmarkSignVerify.cpp @@ -0,0 +1,228 @@ +// Concord +// +// Copyright (c) 2018-2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the subcomponent's license, as noted in the +// LICENSE file. +// + +// #define PICOBENCH_DEBUG +// #define PICOBENCH_IMPLEMENT_WITH_MAIN +#define PICOBENCH_IMPLEMENT +#define PICOBENCH_STD_FUNCTION_BENCHMARKS + +#include +#include +#include +#include + +#include "thread_pool.hpp" +#include "picobench.hpp" +#include "crypto.hpp" +#include "crypto/openssl/EdDSASigner.hpp" +#include "crypto/openssl/EdDSAVerifier.hpp" +#include "util/filesystem.hpp" +#include "crypto/cryptopp/signers.hpp" +#include "crypto/cryptopp/verifiers.hpp" + +namespace concord::benchmark { +using std::string; +using std::unique_ptr; +using concord::crypto::KeyFormat; +using concord::crypto::cryptopp::RSASigner; +using concord::crypto::cryptopp::RSAVerifier; +using concord::crypto::cryptopp::RSA_SIGNATURE_LENGTH; +using concord::crypto::generateEdDSAKeyPair; +using concord::crypto::generateRsaKeyPair; +using concord::util::crypto::openssl::EdDSAPrivateKey; +using concord::util::crypto::openssl::EdDSAPublicKey; +using concord::util::crypto::openssl::deserializeKey; + +using TestSigner = concord::crypto::openssl::EdDSASigner; +using TestVerifier = concord::crypto::openssl::EdDSAVerifier; + +std::default_random_engine generator; + +constexpr size_t RANDOM_DATA_SIZE = 1000U; +constexpr uint8_t RANDOM_DATA_ARRAY_SIZE = 100U; +static string randomData[RANDOM_DATA_ARRAY_SIZE]; + +const auto rsaKeysPair = generateRsaKeyPair(RSA_SIGNATURE_LENGTH); +const auto eddsaKeysPair = generateEdDSAKeyPair(); + +/** + * Initializes 'randomData' with random bytes of size 'len'. + * @param len Length of the random data to be generated. + */ +void generateRandomData(size_t len) { + for (uint8_t i{0}; i < RANDOM_DATA_ARRAY_SIZE; ++i) { + randomData[i].reserve(RANDOM_DATA_SIZE); + } + + std::uniform_int_distribution distribution(0, 0xFF); + + for (uint8_t i{0}; i < RANDOM_DATA_ARRAY_SIZE; ++i) { + for (size_t j{0}; j < len; ++j) { + randomData[i][j] = static_cast(distribution(generator)); + } + } +} + +/** + * A benchmark which measures the time it takes for EdDSA signer to sign a message. + * @param s + */ +void edDSASignerBenchmark(picobench::state& s) { + string sig; + const auto signingKey = deserializeKey(eddsaKeysPair.first); + auto signer_ = unique_ptr(new TestSigner(signingKey.getBytes())); + + // Sign with EdDSASigner. + size_t expectedSignerSigLen = signer_->signatureLength(); + sig.reserve(expectedSignerSigLen); + size_t lenRetData; + + uint64_t signaturesPerformed = 0; + { + picobench::scope scope(s); + + for (int msgIdx = 0; msgIdx < s.iterations(); msgIdx++) { + sig = signer_->sign(randomData[msgIdx % RANDOM_DATA_ARRAY_SIZE]); + lenRetData = sig.size(); + ++signaturesPerformed; + ConcordAssertEQ(lenRetData, expectedSignerSigLen); + } + } + s.set_result(signaturesPerformed); +} + +/** + * @brief A benchmark which measures the time it takes for EdDSA verifier to verify a signature. + * + * @param s + */ +void edDSAVerifierBenchmark(picobench::state& s) { + string sig; + const auto signingKey = deserializeKey(eddsaKeysPair.first); + const auto verificationKey = deserializeKey(eddsaKeysPair.second); + + auto signer_ = unique_ptr(new TestSigner(signingKey.getBytes())); + auto verifier_ = unique_ptr(new TestVerifier(verificationKey.getBytes())); + + // Sign with EdDSASigner. + size_t expectedSignerSigLen = signer_->signatureLength(); + sig.reserve(expectedSignerSigLen); + size_t lenRetData; + + const auto offset = (uint8_t)rand() % RANDOM_DATA_ARRAY_SIZE; + sig = signer_->sign(randomData[offset]); + lenRetData = sig.size(); + ConcordAssertEQ(lenRetData, expectedSignerSigLen); + + uint64_t signaturesVerified = 0; + { + picobench::scope scope(s); + + for (int msgIdx = 0; msgIdx < s.iterations(); msgIdx++) { + ++signaturesVerified; + + // validate with EdDSAVerifier. + ConcordAssert(verifier_->verify(randomData[offset], sig)); + } + } + s.set_result(signaturesVerified); +} + +/** + * @brief A benchmark which measures the time it takes for RSA signer to sign a message. + * + * @param s + */ +void rsaSignerBenchmark(picobench::state& s) { + string sig; + auto signer_ = unique_ptr(new RSASigner(rsaKeysPair.first, KeyFormat::HexaDecimalStrippedFormat)); + + // Sign with RSA_Signer. + size_t expectedSignerSigLen = signer_->signatureLength(); + sig.reserve(expectedSignerSigLen); + size_t lenRetData; + + uint64_t signaturesPerformed = 0; + { + picobench::scope scope(s); + + for (int msgIdx = 0; msgIdx < s.iterations(); msgIdx++) { + sig = signer_->sign(randomData[msgIdx % RANDOM_DATA_ARRAY_SIZE]); + lenRetData = sig.size(); + ++signaturesPerformed; + ConcordAssertEQ(lenRetData, expectedSignerSigLen); + } + } + s.set_result(signaturesPerformed); +} + +/** + * @brief A benchmark which measures the time it takes for RSA verifier to verify a signature. + * + * @param s + */ +void rsaVerifierBenchmark(picobench::state& s) { + string sig; + auto signer_ = unique_ptr(new RSASigner(rsaKeysPair.first, KeyFormat::HexaDecimalStrippedFormat)); + auto verifier_ = unique_ptr(new RSAVerifier(rsaKeysPair.second, KeyFormat::HexaDecimalStrippedFormat)); + + // Sign with RSASigner. + size_t expectedSignerSigLen = signer_->signatureLength(); + sig.reserve(expectedSignerSigLen); + size_t lenRetData; + + const auto offset = (uint8_t)rand() % RANDOM_DATA_ARRAY_SIZE; + sig = signer_->sign(randomData[offset]); + lenRetData = sig.size(); + ConcordAssertEQ(lenRetData, expectedSignerSigLen); + + uint64_t signaturesVerified = 0; + { + picobench::scope scope(s); + + for (int msgIdx = 0; msgIdx < s.iterations(); msgIdx++) { + ++signaturesVerified; + + // validate with RSAVerifier. + ConcordAssert(verifier_->verify(randomData[offset], sig)); + } + } + s.set_result(signaturesVerified); +} + +/** + * @brief Construct a new PICOBENCH object. + * Take one of the fastest samples out of 2 samples. + */ +PICOBENCH(edDSASignerBenchmark).label("EdDSA-Signer").samples(2).iterations({1, 10, 100, 1000, 10000}); +PICOBENCH(rsaSignerBenchmark).label("RSA-Signer").samples(2).iterations({1, 10, 100, 1000, 10000}); +PICOBENCH(edDSAVerifierBenchmark).label("EdDSA-Verifier").samples(2).iterations({1, 10, 100, 1000, 10000}); +PICOBENCH(rsaVerifierBenchmark).label("RSA-Verifier").samples(2).iterations({1, 10, 100, 1000, 10000}); +} // namespace concord::benchmark + +/** + * @brief Entry function. + * + * @param argc + * @param argv + * @return int + */ +int main(int argc, char* argv[]) { + concord::benchmark::generateRandomData(concord::benchmark::RANDOM_DATA_SIZE); + + constexpr const uint64_t picobenchSeed = 20222022; + picobench::runner runner; + runner.set_default_samples(1); + + return runner.run(picobenchSeed); +} diff --git a/util/include/crypto.hpp b/util/include/crypto.hpp new file mode 100644 index 0000000000..9dc71abbf9 --- /dev/null +++ b/util/include/crypto.hpp @@ -0,0 +1,93 @@ +// Concord +// +// Copyright (c) 2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 +// License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the sub-component's license, as noted in the LICENSE +// file. + +#pragma once + +#include +#include + +namespace concord::crypto { + +enum class KeyFormat : uint16_t { HexaDecimalStrippedFormat, PemFormat }; +enum class CurveType : uint16_t { secp256k1, secp384r1 }; + +/** + * @brief Generates an EdDSA asymmetric key pair (private-public key pair). + * + * @param fmt Output key format. + * @return pair Private-Public key pair. + */ +std::pair generateEdDSAKeyPair(const KeyFormat fmt = KeyFormat::HexaDecimalStrippedFormat); + +/** + * @brief Generates an EdDSA PEM file from hexadecimal key pair (private-public key pair). + * + * @param key_pair Key pair in hexa-decimal format. + * @return pair + */ +std::pair EdDSAHexToPem(const std::pair& hex_key_pair); + +/** + * @brief Generates an RSA asymmetric key pair (private-public key pair). + * + * @param fmt Output key format. + * @return pair Private-Public key pair. + */ +std::pair generateRsaKeyPair(const uint32_t sig_length, + const KeyFormat fmt = KeyFormat::HexaDecimalStrippedFormat); + +/** + * @brief Generates an ECDSA asymmetric key pair (private-public key pair). + * + * @param fmt Output key format. + * @return pair Private-Public key pair. + */ +std::pair generateECDSAKeyPair( + const KeyFormat fmt, concord::crypto::CurveType curve_type = concord::crypto::CurveType::secp256k1); + +/** + * @brief Generates an RSA PEM file from hexadecimal key pair (private-public key pair). + * + * @param key_pair Key pair in hexa-decimal format. + * @return pair + */ +std::pair RsaHexToPem(const std::pair& key_pair); + +/** + * @brief Generates an ECDSA PEM file from hexadecimal key pair (private-public key pair). + * + * @param key_pair Key pair in hexa-decimal format. + * @return pair + */ +std::pair ECDSAHexToPem(const std::pair& key_pair); + +/** + * @brief If the key string contains 'BEGIN' token, then it is PEM format, else HEX format. + * + * @param key + * @return KeyFormat Returns the key's format. + * @todo The check to identify the format is not generic. Need to implement some generic way + * identifying the input format. + */ +KeyFormat getFormat(const std::string& key_str); + +/** + * @brief Validates the key. + * + * @param keyType Key type to be validated. + * @param key Key to be validate. + * @param expectedSize Size of the key to be validated. + * @return Validation result. + */ +bool isValidKey(const std::string& keyType, const std::string& key, size_t expectedSize); +} // namespace concord::crypto diff --git a/util/include/crypto/cryptopp/signers.hpp b/util/include/crypto/cryptopp/signers.hpp new file mode 100644 index 0000000000..5b4e6b4031 --- /dev/null +++ b/util/include/crypto/cryptopp/signers.hpp @@ -0,0 +1,55 @@ +// Concord +// +// Copyright (c) 2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 +// License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the sub-component's license, as noted in the LICENSE +// file. + +#pragma once + +#include + +#include "crypto.hpp" +#include "crypto/signer.hpp" + +namespace concord::crypto::cryptopp { + +constexpr static uint32_t RSA_SIGNATURE_LENGTH = 2048U; + +class ECDSASigner : public ISigner { + public: + ECDSASigner(const std::string& str_priv_key, + concord::crypto::KeyFormat fmt = concord::crypto::KeyFormat::HexaDecimalStrippedFormat); + std::string sign(const std::string& data) override; + uint32_t signatureLength() const override; + std::string getPrivKey() const override { return key_str_; } + ~ECDSASigner(); + + private: + class Impl; + std::unique_ptr impl_; + std::string key_str_; +}; + +class RSASigner : public ISigner { + public: + RSASigner(const std::string& str_priv_key, + concord::crypto::KeyFormat fmt = concord::crypto::KeyFormat::HexaDecimalStrippedFormat); + std::string sign(const std::string& data) override; + uint32_t signatureLength() const override; + std::string getPrivKey() const override { return key_str_; } + ~RSASigner(); + + private: + class Impl; + std::unique_ptr impl_; + std::string key_str_; +}; + +} // namespace concord::crypto::cryptopp diff --git a/util/include/crypto/cryptopp/verifiers.hpp b/util/include/crypto/cryptopp/verifiers.hpp new file mode 100644 index 0000000000..8b57476c6b --- /dev/null +++ b/util/include/crypto/cryptopp/verifiers.hpp @@ -0,0 +1,53 @@ +// Concord +// +// Copyright (c) 2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 +// License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the sub-component's license, as noted in the LICENSE +// file. + +#pragma once + +#include + +#include "crypto.hpp" +#include "crypto/verifier.hpp" + +namespace concord::crypto::cryptopp { + +class ECDSAVerifier : public IVerifier { + public: + ECDSAVerifier(const std::string& str_pub_key, + concord::crypto::KeyFormat fmt = concord::crypto::KeyFormat::HexaDecimalStrippedFormat); + bool verify(const std::string& data, const std::string& sig) const override; + uint32_t signatureLength() const override; + std::string getPubKey() const override { return key_str_; } + ~ECDSAVerifier(); + + private: + class Impl; + std::unique_ptr impl_; + std::string key_str_; +}; + +class RSAVerifier : public IVerifier { + public: + RSAVerifier(const std::string& str_pub_key, + concord::crypto::KeyFormat fmt = concord::crypto::KeyFormat::HexaDecimalStrippedFormat); + bool verify(const std::string& data, const std::string& sig) const override; + uint32_t signatureLength() const override; + std::string getPubKey() const override { return key_str_; } + ~RSAVerifier(); + + private: + class Impl; + std::unique_ptr impl_; + std::string key_str_; +}; + +} // namespace concord::crypto::cryptopp diff --git a/util/include/crypto/eddsa/EdDSA.h b/util/include/crypto/eddsa/EdDSA.h deleted file mode 100644 index 974af3b96b..0000000000 --- a/util/include/crypto/eddsa/EdDSA.h +++ /dev/null @@ -1,28 +0,0 @@ -// Concord -// -// Copyright (c) 2018-2022 VMware, Inc. All Rights Reserved. -// -// This product is licensed to you under the Apache 2.0 license (the "License"). -// You may not use this product except in compliance with the Apache 2.0 License. -// -// This product may include a number of subcomponents with separate copyright -// notices and license terms. Your use of these subcomponents is subject to the -// terms and conditions of the subcomponent's license, as noted in the -// LICENSE file. -// -#pragma once -#include "SerializableByteArray.hpp" - -static constexpr const size_t EdDSAPrivateKeyByteSize = 32; -static constexpr const size_t EdDSAPublicKeyByteSize = 32; -static constexpr const size_t EdDSASignatureByteSize = 64; - -class EdDSAPrivateKey : public SerializableByteArray { - public: - EdDSAPrivateKey(const EdDSAPrivateKey::ByteArray& arr) : SerializableByteArray(arr) {} -}; - -class EdDSAPublicKey : public SerializableByteArray { - public: - EdDSAPublicKey(const EdDSAPublicKey::ByteArray& arr) : SerializableByteArray(arr) {} -}; \ No newline at end of file diff --git a/util/include/crypto/eddsa/EdDSAVerifier.hpp b/util/include/crypto/eddsa/EdDSAVerifier.hpp deleted file mode 100644 index 57e0a7cd41..0000000000 --- a/util/include/crypto/eddsa/EdDSAVerifier.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// Concord -// -// Copyright (c) 2018-2022 VMware, Inc. All Rights Reserved. -// -// This product is licensed to you under the Apache 2.0 license (the "License"). -// You may not use this product except in compliance with the Apache 2.0 License. -// -// This product may include a number of subcomponents with separate copyright -// notices and license terms. Your use of these subcomponents is subject to the -// terms and conditions of the subcomponent's license, as noted in the -// LICENSE file. -// -#pragma once -#include "EdDSA.h" -#include "openssl_crypto.hpp" - -/** - * @tparam PublicKeyType The type of the public key - expected to be a SerializableByteArray - * - */ -template -class EdDSAVerifier { - public: - using VerifierKeyType = PublicKeyType; - EdDSAVerifier(const PublicKeyType &publicKey) : publicKey_(publicKey) {} - - bool verify(const std::string &message, const std::string &signature) const { - return verify(message.data(), message.size(), signature.data(), signature.size()); - } - - bool verify(const char *msg, int msgLen, const char *sig, int sigLen) const { - return verify(reinterpret_cast(msg), - static_cast(msgLen), - reinterpret_cast(sig), - static_cast(sigLen)); - } - - bool verify(const uint8_t *msg, size_t msgLen, const uint8_t *sig, size_t sigLen) const { - ConcordAssertEQ(sigLen, EdDSASignatureByteSize); - concord::util::openssl_utils::UniquePKEY pkey{ - EVP_PKEY_new_raw_public_key(NID_ED25519, nullptr, publicKey_.getBytes().data(), publicKey_.getBytes().size())}; - concord::util::openssl_utils::UniqueOpenSSLContext ctx{EVP_MD_CTX_new()}; - ConcordAssertEQ(EVP_DigestVerifyInit(ctx.get(), nullptr, nullptr, nullptr, pkey.get()), - concord::util::openssl_utils::OPENSSL_SUCCESS); - return concord::util::openssl_utils::OPENSSL_SUCCESS == EVP_DigestVerify(ctx.get(), sig, sigLen, msg, msgLen); - } - const PublicKeyType &getPubKey() const { return publicKey_; } - virtual ~EdDSAVerifier() = default; - - private: - PublicKeyType publicKey_; -}; \ No newline at end of file diff --git a/util/include/crypto/factory.hpp b/util/include/crypto/factory.hpp new file mode 100644 index 0000000000..864984b2ec --- /dev/null +++ b/util/include/crypto/factory.hpp @@ -0,0 +1,79 @@ +// Concord +// +// Copyright (c) 2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 +// License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the sub-component's license, as noted in the LICENSE +// file. + +#pragma once + +#include "crypto/cryptopp/signers.hpp" +#include "crypto/cryptopp/verifiers.hpp" +#include "crypto/openssl/EdDSASigner.hpp" +#include "crypto/openssl/EdDSAVerifier.hpp" +#include "Logger.hpp" + +namespace concord::crypto { +enum class SIGN_VERIFY_ALGO : uint8_t { ECDSA, RSA, EDDSA }; + +class Factory { + public: + static std::unique_ptr getSigner( + const std::string& signingKey, + SIGN_VERIFY_ALGO signingAlgo, + concord::crypto::KeyFormat fmt = concord::crypto::KeyFormat::HexaDecimalStrippedFormat) { + switch (signingAlgo) { + case SIGN_VERIFY_ALGO::ECDSA: { + return std::unique_ptr(new concord::crypto::cryptopp::ECDSASigner(signingKey, fmt)); + } + case SIGN_VERIFY_ALGO::RSA: { + return std::unique_ptr(new concord::crypto::cryptopp::RSASigner(signingKey, fmt)); + } + case SIGN_VERIFY_ALGO::EDDSA: { + using MainReplicaSigner = + concord::crypto::openssl::EdDSASigner; + const auto signingKeyObject = + concord::util::crypto::openssl::deserializeKey(signingKey, + fmt); + return std::unique_ptr(new MainReplicaSigner(signingKeyObject.getBytes())); + } + default: + LOG_ERROR(EDDSA_SIG_LOG, "Invalid signing algorithm."); + return {}; + } + } + + static std::unique_ptr getVerifier( + const std::string& verificationKey, + SIGN_VERIFY_ALGO verifierAlgo, + concord::crypto::KeyFormat fmt = concord::crypto::KeyFormat::HexaDecimalStrippedFormat) { + switch (verifierAlgo) { + case SIGN_VERIFY_ALGO::ECDSA: { + return std::unique_ptr( + new concord::crypto::cryptopp::ECDSAVerifier(verificationKey, fmt)); + } + case SIGN_VERIFY_ALGO::RSA: { + return std::unique_ptr( + new concord::crypto::cryptopp::RSAVerifier(verificationKey, fmt)); + } + case SIGN_VERIFY_ALGO::EDDSA: { + using MainReplicaVerifier = + concord::crypto::openssl::EdDSAVerifier; + const auto verifyingKeyObject = + concord::util::crypto::openssl::deserializeKey( + verificationKey, fmt); + return std::unique_ptr(new MainReplicaVerifier(verifyingKeyObject.getBytes())); + } + default: + LOG_ERROR(EDDSA_SIG_LOG, "Invalid verifying algorithm."); + return {}; + } + } +}; +} // namespace concord::crypto diff --git a/util/include/crypto/openssl/EdDSA.hpp b/util/include/crypto/openssl/EdDSA.hpp new file mode 100644 index 0000000000..6514501ce1 --- /dev/null +++ b/util/include/crypto/openssl/EdDSA.hpp @@ -0,0 +1,89 @@ +// Concord +// +// Copyright (c) 2018-2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the subcomponent's license, as noted in the +// LICENSE file. +// +#pragma once + +#include "crypto.hpp" +#include "SerializableByteArray.hpp" +#include "openssl_crypto.hpp" + +namespace concord::util::crypto::openssl { + +static constexpr const size_t EdDSAPrivateKeyByteSize = 32UL; +static constexpr const size_t EdDSAPublicKeyByteSize = 32UL; +static constexpr const size_t EdDSASignatureByteSize = 64UL; + +class EdDSAPrivateKey : public SerializableByteArray { + public: + EdDSAPrivateKey(const EdDSAPrivateKey::ByteArray& arr) : SerializableByteArray(arr) {} +}; + +class EdDSAPublicKey : public SerializableByteArray { + public: + EdDSAPublicKey(const EdDSAPublicKey::ByteArray& arr) : SerializableByteArray(arr) {} +}; + +/** + * @brief Generate hex format key from pem file. + * + * @tparam ByteArrayKeyClass + * @param pemKey + * @param KeyLength + * @return std::vector Generated key. + */ +template +static std::vector extractHexKeyFromPem(const std::string_view pemKey, size_t KeyLength) { + using concord::util::openssl_utils::UniquePKEY; + using concord::util::openssl_utils::UniqueOpenSSLBIO; + using concord::util::openssl_utils::OPENSSL_SUCCESS; + + UniquePKEY pkey; + UniqueOpenSSLBIO bio(BIO_new(BIO_s_mem())); + + ConcordAssertGT(BIO_write(bio.get(), pemKey.data(), static_cast(pemKey.size())), 0); + + size_t keyLen{KeyLength}; + std::vector key(KeyLength); + + if constexpr (std::is_same_v) { + pkey.reset(PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr)); + ConcordAssertEQ(EVP_PKEY_get_raw_private_key(pkey.get(), &key[0], &keyLen), OPENSSL_SUCCESS); + } else if constexpr (std::is_same_v) { + pkey.reset(PEM_read_bio_PUBKEY(bio.get(), nullptr, nullptr, nullptr)); + ConcordAssertEQ(EVP_PKEY_get_raw_public_key(pkey.get(), &key[0], &keyLen), OPENSSL_SUCCESS); + } + return key; +} + +/** + * @brief Get the ByteArray Key Class object. It deserializes the key passed in the first parameter. + * + * @tparam ByteArrayKeyClass + * @param key + * @param format + * @return ByteArrayKeyClass + */ +template +static ByteArrayKeyClass deserializeKey( + const std::string& key, concord::crypto::KeyFormat format = concord::crypto::KeyFormat::HexaDecimalStrippedFormat) { + using concord::crypto::KeyFormat; + + constexpr size_t keyLength = ByteArrayKeyClass::ByteSize; + + if (KeyFormat::PemFormat == format) { + typename ByteArrayKeyClass::ByteArray resultBytes; + std::memcpy(resultBytes.data(), extractHexKeyFromPem(key, keyLength).data(), keyLength); + return ByteArrayKeyClass{resultBytes}; + } + return fromHexString(key); +} +} // namespace concord::util::crypto::openssl diff --git a/util/include/crypto/eddsa/EdDSASigner.hpp b/util/include/crypto/openssl/EdDSASigner.hpp similarity index 52% rename from util/include/crypto/eddsa/EdDSASigner.hpp rename to util/include/crypto/openssl/EdDSASigner.hpp index b3104c9b16..cfcd7dc60d 100644 --- a/util/include/crypto/eddsa/EdDSASigner.hpp +++ b/util/include/crypto/openssl/EdDSASigner.hpp @@ -11,45 +11,63 @@ // LICENSE file. // #pragma once -#include "EdDSA.h" + +#include "EdDSA.hpp" #include "openssl_crypto.hpp" +#include "crypto/signer.hpp" +#include "crypto.hpp" + +namespace concord::crypto::openssl { /** - * - * @tparam PrivateKeyType The type of the private key, expected to be a SerializableByteArray + * @tparam PrivateKeyType The type of the private key, expected to be a SerializableByteArray. * */ template -class EdDSASigner { +class EdDSASigner : public ISigner { public: using SignerKeyType = PrivateKeyType; - EdDSASigner(const PrivateKeyType &privateKey) : privateKey_(privateKey) {} + + /** + * @brief Construct a new EdDSA Signer object. + * + * @param privateKey + */ + explicit EdDSASigner(const PrivateKeyType &privateKey) : privateKey_(privateKey) { + pkey_.reset(EVP_PKEY_new_raw_private_key( + NID_ED25519, nullptr, privateKey_.getBytes().data(), privateKey_.getBytes().size())); + ConcordAssertNE(pkey_, nullptr); + } std::string sign(const uint8_t *msg, size_t len) const { - std::string signature(EdDSASignatureByteSize, 0); - size_t sigLen_ = EdDSASignatureByteSize; + std::string signature(concord::util::crypto::openssl::EdDSASignatureByteSize, 0); + size_t sigLen_ = concord::util::crypto::openssl::EdDSASignatureByteSize; sign(msg, len, reinterpret_cast(signature.data()), sigLen_); - ConcordAssertEQ(sigLen_, EdDSASignatureByteSize); + ConcordAssertEQ(sigLen_, concord::util::crypto::openssl::EdDSASignatureByteSize); return signature; } void sign(const uint8_t *msg, size_t len, uint8_t *signature, size_t &signatureLength) const { - concord::util::openssl_utils::UniquePKEY pkey{EVP_PKEY_new_raw_private_key( - NID_ED25519, nullptr, privateKey_.getBytes().data(), privateKey_.getBytes().size())}; + using concord::util::openssl_utils::OPENSSL_SUCCESS; concord::util::openssl_utils::UniqueOpenSSLContext ctx{EVP_MD_CTX_new()}; - ConcordAssertEQ(EVP_DigestSignInit(ctx.get(), nullptr, nullptr, nullptr, pkey.get()), - concord::util::openssl_utils::OPENSSL_SUCCESS); - ConcordAssertEQ(EVP_DigestSign(ctx.get(), signature, &signatureLength, msg, len), - concord::util::openssl_utils::OPENSSL_SUCCESS); + ConcordAssertEQ(EVP_DigestSignInit(ctx.get(), nullptr, nullptr, nullptr, pkey_.get()), OPENSSL_SUCCESS); + ConcordAssertEQ(EVP_DigestSign(ctx.get(), signature, &signatureLength, msg, len), OPENSSL_SUCCESS); } - std::string sign(const std::string &message) const { + std::string sign(const std::string &message) override { return sign(reinterpret_cast(message.data()), message.size()); } - const PrivateKeyType &getPrivKey() const { return privateKey_; } + uint32_t signatureLength() const override { return concord::util::crypto::openssl::EdDSASignatureByteSize; } + + std::string getPrivKey() const override { return privateKey_.toString(); } + virtual ~EdDSASigner() = default; private: - PrivateKeyType privateKey_; -}; \ No newline at end of file + concord::util::openssl_utils::UniquePKEY pkey_; + + protected: + const PrivateKeyType privateKey_; +}; +} // namespace concord::crypto::openssl diff --git a/util/include/crypto/openssl/EdDSAVerifier.hpp b/util/include/crypto/openssl/EdDSAVerifier.hpp new file mode 100644 index 0000000000..113c71d533 --- /dev/null +++ b/util/include/crypto/openssl/EdDSAVerifier.hpp @@ -0,0 +1,67 @@ +// Concord +// +// Copyright (c) 2018-2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the subcomponent's license, as noted in the +// LICENSE file. +// +#pragma once + +#include "EdDSA.hpp" +#include "openssl_crypto.hpp" +#include "crypto/verifier.hpp" + +// OpenSSL includes. +#include + +namespace concord::crypto::openssl { + +/** + * @tparam PublicKeyType The type of the public key, expected to be a SerializableByteArray. + */ +template +class EdDSAVerifier : public IVerifier { + public: + using VerifierKeyType = PublicKeyType; + + /** + * @brief Construct a new EdDSA Verifier object + * + * @param publicKey + */ + explicit EdDSAVerifier(const PublicKeyType &publicKey) : publicKey_(publicKey) {} + + bool verify(const std::string &message, const std::string &signature) const override { + return verify(message.data(), message.size(), signature.data(), signature.size()); + } + + bool verify(const char *msg, std::size_t msgLen, const char *sig, std::size_t sigLen) const { + return verify(reinterpret_cast(msg), msgLen, reinterpret_cast(sig), sigLen); + } + + bool verify(const uint8_t *msg, size_t msgLen, const uint8_t *sig, size_t sigLen) const { + using concord::util::openssl_utils::UniquePKEY; + using concord::util::openssl_utils::OPENSSL_SUCCESS; + ConcordAssertEQ(sigLen, concord::util::crypto::openssl::EdDSASignatureByteSize); + UniquePKEY pkey{ + EVP_PKEY_new_raw_public_key(NID_ED25519, nullptr, publicKey_.getBytes().data(), publicKey_.getBytes().size())}; + concord::util::openssl_utils::UniqueOpenSSLContext ctx{EVP_MD_CTX_new()}; + ConcordAssertEQ(EVP_DigestVerifyInit(ctx.get(), nullptr, nullptr, nullptr, pkey.get()), OPENSSL_SUCCESS); + return (OPENSSL_SUCCESS == EVP_DigestVerify(ctx.get(), sig, sigLen, msg, msgLen)); + } + + uint32_t signatureLength() const override { return concord::util::crypto::openssl::EdDSASignatureByteSize; } + + std::string getPubKey() const override { return publicKey_.toString(); } + + virtual ~EdDSAVerifier() = default; + + public: + const PublicKeyType publicKey_; +}; +} // namespace concord::crypto::openssl diff --git a/util/include/crypto/signer.hpp b/util/include/crypto/signer.hpp new file mode 100644 index 0000000000..49646408c8 --- /dev/null +++ b/util/include/crypto/signer.hpp @@ -0,0 +1,27 @@ +// Concord +// +// Copyright (c) 2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 +// License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the sub-component's license, as noted in the LICENSE +// file. +#pragma once + +#include + +namespace concord::crypto { + +// Interface for signer. +class ISigner { + public: + virtual std::string sign(const std::string& data) = 0; + virtual uint32_t signatureLength() const = 0; + virtual ~ISigner() = default; + virtual std::string getPrivKey() const = 0; +}; +} // namespace concord::crypto diff --git a/util/include/crypto/verifier.hpp b/util/include/crypto/verifier.hpp new file mode 100644 index 0000000000..c4d9589d69 --- /dev/null +++ b/util/include/crypto/verifier.hpp @@ -0,0 +1,27 @@ +// Concord +// +// Copyright (c) 2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 +// License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the sub-component's license, as noted in the LICENSE +// file. +#pragma once + +#include + +namespace concord::crypto { + +// Interface for verifier. +class IVerifier { + public: + virtual bool verify(const std::string& data, const std::string& sig) const = 0; + virtual uint32_t signatureLength() const = 0; + virtual ~IVerifier() = default; + virtual std::string getPubKey() const = 0; +}; +} // namespace concord::crypto diff --git a/util/include/crypto_utils.hpp b/util/include/crypto_utils.hpp deleted file mode 100644 index fc324d324f..0000000000 --- a/util/include/crypto_utils.hpp +++ /dev/null @@ -1,132 +0,0 @@ -// Concord -// -// Copyright (c) 2020 VMware, Inc. All Rights Reserved. -// -// This product is licensed to you under the Apache 2.0 license (the "License"). -// You may not use this product except in compliance with the Apache 2.0 -// License. -// -// This product may include a number of subcomponents with separate copyright -// notices and license terms. Your use of these subcomponents is subject to the -// terms and conditions of the sub-component's license, as noted in the LICENSE -// file. -#pragma once - -#include -#include -#include - -#include -#include -#include -#include -#include - -namespace concord::util::crypto { -enum class KeyFormat : std::uint16_t { HexaDecimalStrippedFormat, PemFormat }; -enum class CurveType : std::uint16_t { secp256k1, secp384r1 }; - -class CertificateUtils { - public: - static std::string generateSelfSignedCert(const std::string& origin_cert_path, - const std::string& pub_key, - const std::string& signing_key); - static bool verifyCertificate(X509* cert, const std::string& pub_key); - static bool verifyCertificate(X509* cert_to_verify, - const std::string& cert_root_directory, - uint32_t& remote_peer_id, - std::string& conn_type, - bool use_unified_certs); -}; -class IVerifier { - public: - virtual bool verify(const std::string& data, const std::string& sig) const = 0; - virtual uint32_t signatureLength() const = 0; - virtual ~IVerifier() = default; - virtual std::string getPubKey() const = 0; -}; - -class ISigner { - public: - virtual std::string sign(const std::string& data) = 0; - virtual uint32_t signatureLength() const = 0; - virtual ~ISigner() = default; - virtual std::string getPrivKey() const = 0; -}; - -class ECDSAVerifier : public IVerifier { - public: - ECDSAVerifier(const std::string& str_pub_key, KeyFormat fmt); - bool verify(const std::string& data, const std::string& sig) const override; - uint32_t signatureLength() const override; - std::string getPubKey() const override { return key_str_; } - ~ECDSAVerifier(); - - private: - class Impl; - std::unique_ptr impl_; - std::string key_str_; -}; - -class ECDSASigner : public ISigner { - public: - ECDSASigner(const std::string& str_priv_key, KeyFormat fmt); - std::string sign(const std::string& data) override; - uint32_t signatureLength() const override; - std::string getPrivKey() const override { return key_str_; } - ~ECDSASigner(); - - private: - class Impl; - std::unique_ptr impl_; - std::string key_str_; -}; -class RSAVerifier : public IVerifier { - public: - RSAVerifier(const std::string& str_pub_key, KeyFormat fmt); - bool verify(const std::string& data, const std::string& sig) const override; - uint32_t signatureLength() const override; - std::string getPubKey() const override { return key_str_; } - ~RSAVerifier(); - - private: - class Impl; - std::unique_ptr impl_; - std::string key_str_; -}; - -class RSASigner : public ISigner { - public: - RSASigner(const std::string& str_priv_key, KeyFormat fmt); - std::string sign(const std::string& data) override; - uint32_t signatureLength() const override; - std::string getPrivKey() const override { return key_str_; } - ~RSASigner(); - - private: - class Impl; - std::unique_ptr impl_; - std::string key_str_; -}; - -class Crypto { - public: - static Crypto& instance() { - static Crypto crypto; - return crypto; - } - - Crypto(); - ~Crypto(); - std::pair generateRsaKeyPair(const uint32_t sig_length, const KeyFormat fmt) const; - std::pair generateECDSAKeyPair(const KeyFormat fmt, - CurveType curve_type = CurveType::secp256k1) const; - std::pair RsaHexToPem(const std::pair& key_pair) const; - std::pair ECDSAHexToPem(const std::pair& key_pair) const; - KeyFormat getFormat(const std::string& key_str) const; - - private: - class Impl; - std::unique_ptr impl_; -}; -} // namespace concord::util::crypto \ No newline at end of file diff --git a/util/include/cryptopp_digest_creator.hpp b/util/include/cryptopp/digest_creator.hpp similarity index 87% rename from util/include/cryptopp_digest_creator.hpp rename to util/include/cryptopp/digest_creator.hpp index c4b78e85be..f90b80c5cc 100644 --- a/util/include/cryptopp_digest_creator.hpp +++ b/util/include/cryptopp/digest_creator.hpp @@ -11,7 +11,7 @@ #pragma once -#include "digest_creator.hpp" +#include "digestCreator.hpp" #include "digest_type.hpp" #if defined MD5_DIGEST @@ -23,10 +23,10 @@ #define DigestType CryptoPP::SHA512 #endif -namespace concord::util::digest { +namespace concord::util::crypto::cryptopp { // Implements digest creator using Crypto++ library. -class CryptoppDigestCreator : public DigestCreator { +class CryptoppDigestCreator : public concord::util::digest::DigestCreator { public: CryptoppDigestCreator(); virtual ~CryptoppDigestCreator(); @@ -46,4 +46,4 @@ class CryptoppDigestCreator : public DigestCreator { private: void* internalState_; }; -} // namespace concord::util::digest +} // namespace concord::util::crypto::cryptopp diff --git a/util/include/digest.hpp b/util/include/digest.hpp index 6819fd5758..37978fc574 100644 --- a/util/include/digest.hpp +++ b/util/include/digest.hpp @@ -13,22 +13,26 @@ #include "digest_type.hpp" #include "digest_holder.hpp" -#include "cryptopp_digest_creator.hpp" -#include "openssl_digest_creator.ipp" + +#if defined USE_CRYPTOPP_SHA_256 +#include "cryptopp/digest_creator.hpp" +#elif defined USE_OPENSSL_SHA_256 || defined USE_OPENSSL_SHA3_256 +#include "openssl/digest_creator.hpp" +#endif namespace concord::util::digest { using BlockDigest = std::array; -#if defined USE_CRYPTOPP_HASH -using Digest = DigestHolder; -using DigestGenerator = CryptoppDigestCreator; +#if defined USE_CRYPTOPP_SHA_256 +using Digest = DigestHolder; +using DigestGenerator = concord::util::crypto::cryptopp::CryptoppDigestCreator; #elif defined USE_OPENSSL_SHA_256 -using Digest = DigestHolder >; -using DigestGenerator = OpenSSLDigestCreator; +using Digest = DigestHolder >; +using DigestGenerator = concord::util::crypto::openssl::OpenSSLDigestCreator; #elif defined USE_OPENSSL_SHA3_256 -using Digest = DigestHolder >; -using DigestGenerator = OpenSSLDigestCreator; +using Digest = DigestHolder >; +using DigestGenerator = concord::util::crypto::openssl::OpenSSLDigestCreator; #endif static_assert(DIGEST_SIZE >= sizeof(uint64_t), "Digest size should be >= sizeof(uint64_t)"); diff --git a/util/include/digest_creator.hpp b/util/include/digestCreator.hpp similarity index 87% rename from util/include/digest_creator.hpp rename to util/include/digestCreator.hpp index bfff275e21..b4bb280670 100644 --- a/util/include/digest_creator.hpp +++ b/util/include/digestCreator.hpp @@ -8,9 +8,6 @@ // This product may include a number of subcomponents with separate copyright notices and license terms. Your use of // these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE // file. -// -// Design doc: -// https://confluence.eng.vmware.com/pages/viewpage.action?spaceKey=BLOC&title=Align+cryptographic+algorithms+across+Concord #pragma once diff --git a/util/include/hex_tools.h b/util/include/hex_tools.h index 08874a5b0b..8d10e18847 100644 --- a/util/include/hex_tools.h +++ b/util/include/hex_tools.h @@ -37,4 +37,9 @@ std::string sliverToHex(const Sliver &sliver); // Converts a byte vector into a hex string std::string vectorToHex(const std::vector &data); +// Converts a hex string into a char vector. Handles leading 0x characters (if present). +// Input hex: "616263" or "0x616263" +// Returns: abc +std::vector unhex(const std::string &hex); + } // namespace concordUtils diff --git a/util/include/io.hpp b/util/include/io.hpp new file mode 100644 index 0000000000..cda92a5527 --- /dev/null +++ b/util/include/io.hpp @@ -0,0 +1,27 @@ +// Concord +// +// Copyright (c) 2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 +// License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the sub-component's license, as noted in the LICENSE +// file. + +#pragma once + +#include + +namespace concord::io { +/** + * @brief Reads a file. + * + * @param file File stream to be read from. + * @param maxBytes Maximum bytes of data to be read from the file. + * @return std::string Contents of the file. + */ +std::string readFile(FILE* file, uint64_t maxBytes); +} // namespace concord::io diff --git a/util/include/openssl_digest_creator.ipp b/util/include/openssl/digest_creator.hpp similarity index 89% rename from util/include/openssl_digest_creator.ipp rename to util/include/openssl/digest_creator.hpp index bc1ff35e7d..0f1b98a6ac 100644 --- a/util/include/openssl_digest_creator.ipp +++ b/util/include/openssl/digest_creator.hpp @@ -11,20 +11,15 @@ #pragma once -#include -#include -#include -#include - -#include "digest_creator.hpp" #include "sha_hash.hpp" +#include "digestCreator.hpp" -namespace concord::util::digest { +namespace concord::util::crypto::openssl { template || std::is_same_v>> -class OpenSSLDigestCreator : public DigestCreator { +class OpenSSLDigestCreator : public concord::util::digest::DigestCreator { public: OpenSSLDigestCreator() = default; @@ -73,4 +68,4 @@ class OpenSSLDigestCreator : public DigestCreator { bool initialized_{false}; SHACTX hash_ctx_; }; -} // namespace concord::util::digest +} // namespace concord::util::crypto::openssl diff --git a/util/include/openssl/utils.hpp b/util/include/openssl/utils.hpp new file mode 100644 index 0000000000..4a793d658f --- /dev/null +++ b/util/include/openssl/utils.hpp @@ -0,0 +1,53 @@ +// Concord +// +// Copyright (c) 2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 +// License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the sub-component's license, as noted in the LICENSE +// file. + +#pragma once + +#include +#include +#include +#include +#include +#include "crypto/factory.hpp" + +namespace concord::crypto { + +std::string generateSelfSignedCert(const std::string& origin_cert_path, + const std::string& pub_key, + const std::string& signing_key, + const SIGN_VERIFY_ALGO signingAlgo); +/** + * @brief Verifies the signature of certificate 'cert' using public key 'pub_key'. + * + * @param cert [input] Certificate to be validated. + * @param pub_key [input] Public key to be used to validate the certificate. + * @return bool Verification result. + */ +bool verifyCertificate(X509& cert, const std::string& pub_key); + +/** + * @brief Verifies the certificate 'cert_to_verify' with another certificate present in 'cert_root_directory'. + * + * @param cert_to_verify [input] Certificate to be validated. + * @param cert_root_directory [input] Location of the other certificate to be verified. + * @param remote_peer_id [output] + * @param conn_type [output] Certificate type (server or client). + * @param use_unified_certs [input] + * @return Verification result. + */ +bool verifyCertificate(const X509& cert_to_verify, + const std::string& cert_root_directory, + uint32_t& remote_peer_id, + std::string& conn_type, + bool use_unified_certs); +} // namespace concord::crypto diff --git a/util/include/openssl_crypto.hpp b/util/include/openssl_crypto.hpp index 39caac841e..4b41078aab 100644 --- a/util/include/openssl_crypto.hpp +++ b/util/include/openssl_crypto.hpp @@ -18,23 +18,25 @@ // and more convenient interface to the OpenSSL crypto library to fit better // with the rest of the Concord codebase, as the OpenSSL crypto library itself // has a C interface. - -#ifndef UTILS_OPENSSL_CRYPTO_HPP -#define UTILS_OPENSSL_CRYPTO_HPP +#pragma once #include #include #include #include #include -#include -#include + #include "memory.hpp" #include "assertUtils.hpp" -namespace concord { -namespace util { -namespace openssl_utils { +// OpenSSL includes. +#include +#include +#include +#include +#include + +namespace concord::util::openssl_utils { // Note these utilities may use std::strings to pass arond byte strings; note // this should work since C++ should guarantee std::string is a string of chars @@ -200,11 +202,16 @@ class UnexpectedOpenSSLCryptoFailureException : public std::exception { using UniqueOpenSSLContext = custom_deleter_unique_ptr; using UniqueOpenSSLPKEYContext = custom_deleter_unique_ptr; using UniquePKEY = custom_deleter_unique_ptr; +using UniqueOpenSSLX509 = custom_deleter_unique_ptr; +using UniqueOpenSSLBIO = custom_deleter_unique_ptr; +using UniqueOpenSSLCipherContext = custom_deleter_unique_ptr; +using UniqueOpenSSLBIGNUM = custom_deleter_unique_ptr; +using UniqueOpenSSLBNCTX = custom_deleter_unique_ptr; +using UniqueOpenSSLECKEY = custom_deleter_unique_ptr; +using UniqueOpenSSLECPOINT = custom_deleter_unique_ptr; constexpr int OPENSSL_SUCCESS = 1; +constexpr int OPENSSL_FAILURE = 0; +constexpr int OPENSSL_ERROR = -1; -} // namespace openssl_utils -} // namespace util -} // namespace concord - -#endif // UTILS_OPENSSL_CRYPTO_HPP +} // namespace concord::util::openssl_utils diff --git a/util/pyclient/bft_client.py b/util/pyclient/bft_client.py index 9809f28ba5..6e1157353a 100644 --- a/util/pyclient/bft_client.py +++ b/util/pyclient/bft_client.py @@ -17,9 +17,7 @@ import ssl import os import random -from Crypto.PublicKey import RSA -from Crypto.Hash import SHA256 -from Crypto.Signature import pkcs1_15 +from cryptography.hazmat.primitives import serialization import bft_msgs import replica_specific_info as RSI @@ -96,7 +94,7 @@ def __init__(self, config, replicas, ro_replicas=[]): self.signing_key = None if txn_signing_key_path: with open(txn_signing_key_path, 'rb') as f: - self.signing_key = RSA.import_key(f.read()) + self.signing_key = serialization.load_pem_private_key(f.read(), password=None) @abstractmethod def __enter__(self): @@ -187,8 +185,7 @@ async def sendSync(self, msg, read_only, seq_num=None, cid=None, pre_process=Fal signature = b'' client_id = self.client_id if self.signing_key: - h = SHA256.new(msg) - signature = pkcs1_15.new(self.signing_key).sign(h) + signature = self.signing_key.sign(bytes(msg)) if corrupt_params: msg, signature, client_id = self._corrupt_signing_params(msg, signature, client_id, corrupt_params) @@ -232,8 +229,7 @@ async def write_batch(self, msg_batch, batch_seq_nums=None, m_of_n_quorum=None, signature = b'' client_id = self.client_id if self.signing_key: - h = SHA256.new(msg) - signature = pkcs1_15.new(self.signing_key).sign(h) + signature = self.signing_key.sign(bytes(msg)) if corrupt_params and (req_index_to_corrupt == n): msg, signature, client_id = self._corrupt_signing_params(msg, signature, client_id, corrupt_params) diff --git a/util/src/crypto.cpp b/util/src/crypto.cpp new file mode 100644 index 0000000000..cc9884e4d0 --- /dev/null +++ b/util/src/crypto.cpp @@ -0,0 +1,208 @@ +// Concord +// +// Copyright (c) 2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 +// License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the sub-component's license, as noted in the LICENSE +// file. + +#include "crypto.hpp" +#include "Logger.hpp" +#include "assertUtils.hpp" +#include "hex_tools.h" +#include "string.hpp" +#include "crypto/openssl/EdDSA.hpp" +#include "util/filesystem.hpp" + +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#include +#include +#include +#include +#include +#pragma GCC diagnostic pop + +namespace concord::crypto { +using std::array; +using std::pair; +using std::string; +using concord::crypto::KeyFormat; +using concord::crypto::CurveType; +using concord::util::openssl_utils::UniquePKEY; +using concord::util::openssl_utils::UniqueOpenSSLPKEYContext; +using concord::util::openssl_utils::UniqueOpenSSLBIO; +using concord::util::openssl_utils::OPENSSL_SUCCESS; +using concord::util::crypto::openssl::EdDSASignatureByteSize; +using namespace CryptoPP; + +pair generateEdDSAKeyPair(const KeyFormat fmt) { + UniquePKEY edPkey; + UniqueOpenSSLPKEYContext edPkeyCtx(EVP_PKEY_CTX_new_id(NID_ED25519, nullptr)); + + ConcordAssertNE(edPkeyCtx, nullptr); + + ConcordAssertEQ(OPENSSL_SUCCESS, EVP_PKEY_keygen_init(edPkeyCtx.get())); + ConcordAssertEQ( + OPENSSL_SUCCESS, + EVP_PKEY_keygen(edPkeyCtx.get(), reinterpret_cast(&edPkey))); // Generate EdDSA key 'edPkey'. + + array privKey; + array pubKey; + size_t privlen{EdDSASignatureByteSize}; + size_t publen{EdDSASignatureByteSize}; + + ConcordAssertEQ(OPENSSL_SUCCESS, EVP_PKEY_get_raw_private_key(edPkey.get(), privKey.data(), &privlen)); + ConcordAssertEQ(OPENSSL_SUCCESS, EVP_PKEY_get_raw_public_key(edPkey.get(), pubKey.data(), &publen)); + + pair keyPair(boost::algorithm::hex(string(reinterpret_cast(privKey.data()), privlen)), + boost::algorithm::hex(string(reinterpret_cast(pubKey.data()), publen))); + + if (KeyFormat::PemFormat == fmt) { + keyPair = EdDSAHexToPem(keyPair); + } + return keyPair; +} + +pair EdDSAHexToPem(const std::pair& hex_key_pair) { + string privPemString; + string pubPemString; + + if (!hex_key_pair.first.empty()) { // Proceed with private key pem file generation. + const auto privKey = boost::algorithm::unhex(hex_key_pair.first); + + UniquePKEY ed_privKey(EVP_PKEY_new_raw_private_key( + NID_ED25519, nullptr, reinterpret_cast(privKey.data()), privKey.size())); + ConcordAssertNE(nullptr, ed_privKey); + + UniqueOpenSSLBIO bio(BIO_new(BIO_s_mem())); + ConcordAssertNE(nullptr, bio); + + ConcordAssertEQ(OPENSSL_SUCCESS, + PEM_write_bio_PrivateKey(bio.get(), ed_privKey.get(), nullptr, nullptr, 0, nullptr, nullptr)); + + const auto lenToRead = BIO_pending(bio.get()); + std::vector output(lenToRead); + ConcordAssertGT(BIO_read(bio.get(), output.data(), lenToRead), 0); + privPemString = string(output.begin(), output.end()); + } + + if (!hex_key_pair.second.empty()) { // Proceed with public key pem file generation. + const auto pubKey = boost::algorithm::unhex(hex_key_pair.second); + + UniquePKEY ed_pubKey(EVP_PKEY_new_raw_public_key( + NID_ED25519, nullptr, reinterpret_cast(pubKey.data()), pubKey.size())); + ConcordAssertNE(nullptr, ed_pubKey); + + UniqueOpenSSLBIO bio(BIO_new(BIO_s_mem())); + ConcordAssertNE(nullptr, bio); + + ConcordAssertEQ(OPENSSL_SUCCESS, PEM_write_bio_PUBKEY(bio.get(), ed_pubKey.get())); + + const auto lenToRead = BIO_pending(bio.get()); + std::vector output(lenToRead); + ConcordAssertGT(BIO_read(bio.get(), output.data(), lenToRead), 0); + pubPemString = string(output.begin(), output.end()); + } + return make_pair(privPemString, pubPemString); +} + +pair RsaHexToPem(const pair& key_pair) { + pair out; + if (!key_pair.first.empty()) { + StringSource priv_str(key_pair.first, true, new HexDecoder()); + CryptoPP::RSA::PrivateKey priv; + priv.Load(priv_str); + StringSink priv_string_sink(out.first); + PEM_Save(priv_string_sink, priv); + priv_string_sink.MessageEnd(); + } + + if (!key_pair.second.empty()) { + StringSource pub_str(key_pair.second, true, new HexDecoder()); + CryptoPP::RSA::PublicKey pub; + pub.Load(pub_str); + StringSink pub_string_sink(out.second); + PEM_Save(pub_string_sink, pub); + pub_string_sink.MessageEnd(); + } + return out; +} + +pair ECDSAHexToPem(const pair& key_pair) { + pair out; + if (!key_pair.first.empty()) { + StringSource priv_str(key_pair.first, true, new HexDecoder()); + ECDSA::PrivateKey priv; + priv.Load(priv_str); + StringSink priv_string_sink(out.first); + PEM_Save(priv_string_sink, priv); + } + if (!key_pair.second.empty()) { + StringSource pub_str(key_pair.second, true, new HexDecoder()); + ECDSA::PublicKey pub; + pub.Load(pub_str); + StringSink pub_string_sink(out.second); + PEM_Save(pub_string_sink, pub); + } + return out; +} + +pair generateRsaKeyPair(const uint32_t sig_length, const KeyFormat fmt) { + AutoSeededRandomPool rng; + pair keyPair; + + RSAES>::Decryptor priv(rng, sig_length); + RSAES>::Encryptor pub(priv); + HexEncoder privEncoder(new StringSink(keyPair.first)); + priv.AccessMaterial().Save(privEncoder); + privEncoder.MessageEnd(); + + HexEncoder pubEncoder(new StringSink(keyPair.second)); + pub.AccessMaterial().Save(pubEncoder); + pubEncoder.MessageEnd(); + if (fmt == KeyFormat::PemFormat) { + keyPair = RsaHexToPem(keyPair); + } + return keyPair; +} + +pair generateECDSAKeyPair(const KeyFormat fmt, CurveType curve_types) { + AutoSeededRandomPool prng; + ECDSA::PrivateKey privateKey; + ECDSA::PublicKey publicKey; + + privateKey.Initialize(prng, curve_types == CurveType::secp256k1 ? ASN1::secp256k1() : ASN1::secp384r1()); + privateKey.MakePublicKey(publicKey); + pair keyPair; + HexEncoder privEncoder(new StringSink(keyPair.first)); + privateKey.Save(privEncoder); + HexEncoder pubEncoder(new StringSink(keyPair.second)); + publicKey.Save(pubEncoder); + if (fmt == KeyFormat::PemFormat) { + keyPair = ECDSAHexToPem(keyPair); + } + return keyPair; +} + +KeyFormat getFormat(const std::string& key) { + return (key.find("BEGIN") != std::string::npos) ? KeyFormat::PemFormat : KeyFormat::HexaDecimalStrippedFormat; +} + +bool isValidKey(const std::string& keyName, const std::string& key, size_t expectedSize) { + auto isValidHex = util::isValidHexString(key); + if ((expectedSize == 0 or (key.length() == expectedSize)) and isValidHex) { + return true; + } + throw std::runtime_error("Invalid " + keyName + " key (" + key + ") of size " + std::to_string(expectedSize) + + " bytes."); +} +} // namespace concord::crypto diff --git a/util/src/crypto/cryptopp/signers.cpp b/util/src/crypto/cryptopp/signers.cpp new file mode 100644 index 0000000000..9a444003c1 --- /dev/null +++ b/util/src/crypto/cryptopp/signers.cpp @@ -0,0 +1,106 @@ +// Concord +// +// Copyright (c) 2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 +// License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the sub-component's license, as noted in the LICENSE +// file. + +#include "crypto/cryptopp/signers.hpp" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#include +#include +#include +#include +#include +#pragma GCC diagnostic pop + +namespace concord::crypto::cryptopp { + +using namespace CryptoPP; +using concord::crypto::KeyFormat; + +class ECDSASigner::Impl { + std::unique_ptr::Signer> signer_; + AutoSeededRandomPool prng_; + + public: + Impl(ECDSA::PrivateKey& privateKey) { + signer_ = std::make_unique::Signer>(std::move(privateKey)); + } + + std::string sign(const std::string& data_to_sign) { + size_t siglen = signer_->MaxSignatureLength(); + std::string signature(siglen, 0x00); + siglen = signer_->SignMessage( + prng_, (const CryptoPP::byte*)&data_to_sign[0], data_to_sign.size(), (CryptoPP::byte*)&signature[0]); + signature.resize(siglen); + return signature; + } + uint32_t signatureLength() const { return signer_->SignatureLength(); } +}; + +std::string ECDSASigner::sign(const std::string& data) { return impl_->sign(data); } + +ECDSASigner::ECDSASigner(const std::string& str_priv_key, KeyFormat fmt) : key_str_{str_priv_key} { + ECDSA::PrivateKey privateKey; + if (fmt == KeyFormat::PemFormat) { + StringSource s(str_priv_key, true); + PEM_Load(s, privateKey); + } else { + StringSource s(str_priv_key, true, new HexDecoder()); + privateKey.Load(s); + } + impl_.reset(new Impl(privateKey)); +} + +uint32_t ECDSASigner::signatureLength() const { return impl_->signatureLength(); } + +ECDSASigner::~ECDSASigner() = default; + +class RSASigner::Impl { + public: + Impl(CryptoPP::RSA::PrivateKey& private_key) { + signer_ = std::make_unique::Signer>(std::move(private_key)); + } + std::string sign(const std::string& data_to_sign) { + size_t siglen = signer_->MaxSignatureLength(); + std::string signature(siglen, 0x00); + siglen = signer_->SignMessage( + prng_, (const CryptoPP::byte*)&data_to_sign[0], data_to_sign.size(), (CryptoPP::byte*)&signature[0]); + signature.resize(siglen); + return signature; + } + uint32_t signatureLength() const { return signer_->SignatureLength(); } + + private: + std::unique_ptr::Signer> signer_; + AutoSeededRandomPool prng_; +}; + +RSASigner::RSASigner(const std::string& str_priv_key, KeyFormat fmt) : key_str_{str_priv_key} { + CryptoPP::RSA::PrivateKey private_key; + if (fmt == KeyFormat::PemFormat) { + StringSource s(str_priv_key, true); + PEM_Load(s, private_key); + } else { + StringSource s(str_priv_key, true, new HexDecoder()); + private_key.Load(s); + } + impl_.reset(new RSASigner::Impl(private_key)); +} + +std::string RSASigner::sign(const std::string& data) { return impl_->sign(data); } + +uint32_t RSASigner::signatureLength() const { return impl_->signatureLength(); } + +RSASigner::~RSASigner() = default; + +} // namespace concord::crypto::cryptopp diff --git a/util/src/crypto/cryptopp/verifiers.cpp b/util/src/crypto/cryptopp/verifiers.cpp new file mode 100644 index 0000000000..069d14fce8 --- /dev/null +++ b/util/src/crypto/cryptopp/verifiers.cpp @@ -0,0 +1,102 @@ +// Concord +// +// Copyright (c) 2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 +// License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the sub-component's license, as noted in the LICENSE +// file. + +#include "crypto/cryptopp/verifiers.hpp" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#include +#include +#include +#include +#include +#pragma GCC diagnostic pop + +namespace concord::crypto::cryptopp { + +using namespace CryptoPP; +using concord::crypto::KeyFormat; + +class ECDSAVerifier::Impl { + std::unique_ptr::Verifier> verifier_; + + public: + Impl(ECDSA::PublicKey& publicKey) { + verifier_ = std::make_unique::Verifier>(std::move(publicKey)); + } + + bool verify(const std::string& data_to_verify, const std::string& signature) const { + return verifier_->VerifyMessage((const CryptoPP::byte*)&data_to_verify[0], + data_to_verify.size(), + (const CryptoPP::byte*)&signature[0], + signature.size()); + } + + uint32_t signatureLength() const { return verifier_->SignatureLength(); } +}; + +bool ECDSAVerifier::verify(const std::string& data, const std::string& sig) const { return impl_->verify(data, sig); } + +ECDSAVerifier::ECDSAVerifier(const std::string& str_pub_key, KeyFormat fmt) : key_str_{str_pub_key} { + ECDSA::PublicKey publicKey; + if (fmt == KeyFormat::PemFormat) { + StringSource s(str_pub_key, true); + PEM_Load(s, publicKey); + } else { + StringSource s(str_pub_key, true, new HexDecoder()); + publicKey.Load(s); + } + impl_.reset(new Impl(publicKey)); +} + +uint32_t ECDSAVerifier::signatureLength() const { return impl_->signatureLength(); } + +ECDSAVerifier::~ECDSAVerifier() = default; + +class RSAVerifier::Impl { + public: + Impl(CryptoPP::RSA::PublicKey& public_key) { + verifier_ = std::make_unique::Verifier>(std::move(public_key)); + } + bool verify(const std::string& data_to_verify, const std::string& signature) const { + return verifier_->VerifyMessage((const CryptoPP::byte*)&data_to_verify[0], + data_to_verify.size(), + (const CryptoPP::byte*)&signature[0], + signature.size()); + } + + uint32_t signatureLength() const { return verifier_->SignatureLength(); } + + private: + std::unique_ptr::Verifier> verifier_; +}; + +RSAVerifier::RSAVerifier(const std::string& str_pub_key, KeyFormat fmt) : key_str_{str_pub_key} { + CryptoPP::RSA::PublicKey public_key; + if (fmt == KeyFormat::PemFormat) { + StringSource s(str_pub_key, true); + PEM_Load(s, public_key); + } else { + StringSource s(str_pub_key, true, new HexDecoder()); + public_key.Load(s); + } + impl_.reset(new RSAVerifier::Impl(public_key)); +} + +bool RSAVerifier::verify(const std::string& data, const std::string& sig) const { return impl_->verify(data, sig); } + +uint32_t RSAVerifier::signatureLength() const { return impl_->signatureLength(); } + +RSAVerifier::~RSAVerifier() = default; + +} // namespace concord::crypto::cryptopp diff --git a/util/src/crypto_utils.cpp b/util/src/crypto_utils.cpp deleted file mode 100644 index 1c9f38fd95..0000000000 --- a/util/src/crypto_utils.cpp +++ /dev/null @@ -1,452 +0,0 @@ -// Concord -// -// Copyright (c) 2020 VMware, Inc. All Rights Reserved. -// -// This product is licensed to you under the Apache 2.0 license (the "License"). -// You may not use this product except in compliance with the Apache 2.0 -// License. -// -// This product may include a number of subcomponents with separate copyright -// notices and license terms. Your use of these subcomponents is subject to the -// terms and conditions of the sub-component's license, as noted in the LICENSE -// file. -#include "crypto_utils.hpp" - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#include -#include -#include -#include -#include -#pragma GCC diagnostic pop - -#include -#include -#include -#include -#include -#include -#include "Logger.hpp" - -using namespace CryptoPP; -namespace concord::util::crypto { -class ECDSAVerifier::Impl { - std::unique_ptr::Verifier> verifier_; - - public: - Impl(ECDSA::PublicKey& publicKey) { - verifier_ = std::make_unique::Verifier>(std::move(publicKey)); - } - - bool verify(const std::string& data_to_verify, const std::string& signature) const { - return verifier_->VerifyMessage((const CryptoPP::byte*)&data_to_verify[0], - data_to_verify.size(), - (const CryptoPP::byte*)&signature[0], - signature.size()); - } - - uint32_t signatureLength() const { return verifier_->SignatureLength(); } -}; -bool ECDSAVerifier::verify(const std::string& data, const std::string& sig) const { return impl_->verify(data, sig); } -ECDSAVerifier::ECDSAVerifier(const std::string& str_pub_key, KeyFormat fmt) : key_str_{str_pub_key} { - ECDSA::PublicKey publicKey; - if (fmt == KeyFormat::PemFormat) { - StringSource s(str_pub_key, true); - PEM_Load(s, publicKey); - } else { - StringSource s(str_pub_key, true, new HexDecoder()); - publicKey.Load(s); - } - impl_.reset(new Impl(publicKey)); -} -uint32_t ECDSAVerifier::signatureLength() const { return impl_->signatureLength(); } -ECDSAVerifier::~ECDSAVerifier() = default; - -class ECDSASigner::Impl { - std::unique_ptr::Signer> signer_; - AutoSeededRandomPool prng_; - - public: - Impl(ECDSA::PrivateKey& privateKey) { - signer_ = std::make_unique::Signer>(std::move(privateKey)); - } - - std::string sign(const std::string& data_to_sign) { - size_t siglen = signer_->MaxSignatureLength(); - std::string signature(siglen, 0x00); - siglen = signer_->SignMessage( - prng_, (const CryptoPP::byte*)&data_to_sign[0], data_to_sign.size(), (CryptoPP::byte*)&signature[0]); - signature.resize(siglen); - return signature; - } - uint32_t signatureLength() const { return signer_->SignatureLength(); } -}; - -std::string ECDSASigner::sign(const std::string& data) { return impl_->sign(data); } -ECDSASigner::ECDSASigner(const std::string& str_priv_key, KeyFormat fmt) : key_str_{str_priv_key} { - ECDSA::PrivateKey privateKey; - if (fmt == KeyFormat::PemFormat) { - StringSource s(str_priv_key, true); - PEM_Load(s, privateKey); - } else { - StringSource s(str_priv_key, true, new HexDecoder()); - privateKey.Load(s); - } - impl_.reset(new Impl(privateKey)); -} -uint32_t ECDSASigner::signatureLength() const { return impl_->signatureLength(); } -ECDSASigner::~ECDSASigner() = default; - -class RSAVerifier::Impl { - public: - Impl(CryptoPP::RSA::PublicKey& public_key) { - verifier_ = std::make_unique::Verifier>(std::move(public_key)); - } - bool verify(const std::string& data_to_verify, const std::string& signature) const { - return verifier_->VerifyMessage((const CryptoPP::byte*)&data_to_verify[0], - data_to_verify.size(), - (const CryptoPP::byte*)&signature[0], - signature.size()); - } - - uint32_t signatureLength() const { return verifier_->SignatureLength(); } - - private: - std::unique_ptr::Verifier> verifier_; -}; - -class RSASigner::Impl { - public: - Impl(CryptoPP::RSA::PrivateKey& private_key) { - signer_ = std::make_unique::Signer>(std::move(private_key)); - } - std::string sign(const std::string& data_to_sign) { - size_t siglen = signer_->MaxSignatureLength(); - std::string signature(siglen, 0x00); - siglen = signer_->SignMessage( - prng_, (const CryptoPP::byte*)&data_to_sign[0], data_to_sign.size(), (CryptoPP::byte*)&signature[0]); - signature.resize(siglen); - return signature; - } - uint32_t signatureLength() const { return signer_->SignatureLength(); } - - private: - std::unique_ptr::Signer> signer_; - AutoSeededRandomPool prng_; -}; - -RSASigner::RSASigner(const std::string& str_priv_key, KeyFormat fmt) : key_str_{str_priv_key} { - CryptoPP::RSA::PrivateKey private_key; - if (fmt == KeyFormat::PemFormat) { - StringSource s(str_priv_key, true); - PEM_Load(s, private_key); - } else { - StringSource s(str_priv_key, true, new HexDecoder()); - private_key.Load(s); - } - impl_.reset(new RSASigner::Impl(private_key)); -} - -std::string RSASigner::sign(const std::string& data) { return impl_->sign(data); } -uint32_t RSASigner::signatureLength() const { return impl_->signatureLength(); } -RSASigner::~RSASigner() = default; - -RSAVerifier::RSAVerifier(const std::string& str_pub_key, KeyFormat fmt) : key_str_{str_pub_key} { - CryptoPP::RSA::PublicKey public_key; - if (fmt == KeyFormat::PemFormat) { - StringSource s(str_pub_key, true); - PEM_Load(s, public_key); - } else { - StringSource s(str_pub_key, true, new HexDecoder()); - public_key.Load(s); - } - impl_.reset(new RSAVerifier::Impl(public_key)); -} -bool RSAVerifier::verify(const std::string& data, const std::string& sig) const { return impl_->verify(data, sig); } -uint32_t RSAVerifier::signatureLength() const { return impl_->signatureLength(); } -RSAVerifier::~RSAVerifier() = default; - -class Crypto::Impl { - public: - std::pair RsaHexToPem(const std::pair& key_pair) { - std::pair out; - if (!key_pair.first.empty()) { - StringSource priv_str(key_pair.first, true, new HexDecoder()); - CryptoPP::RSA::PrivateKey priv; - priv.Load(priv_str); - StringSink priv_string_sink(out.first); - PEM_Save(priv_string_sink, priv); - priv_string_sink.MessageEnd(); - } - - if (!key_pair.second.empty()) { - StringSource pub_str(key_pair.second, true, new HexDecoder()); - CryptoPP::RSA::PublicKey pub; - pub.Load(pub_str); - StringSink pub_string_sink(out.second); - PEM_Save(pub_string_sink, pub); - pub_string_sink.MessageEnd(); - } - return out; - } - - std::pair ECDSAHexToPem(const std::pair& key_pair) { - std::pair out; - if (!key_pair.first.empty()) { - StringSource priv_str(key_pair.first, true, new HexDecoder()); - ECDSA::PrivateKey priv; - priv.Load(priv_str); - StringSink priv_string_sink(out.first); - PEM_Save(priv_string_sink, priv); - } - if (!key_pair.second.empty()) { - StringSource pub_str(key_pair.second, true, new HexDecoder()); - ECDSA::PublicKey pub; - pub.Load(pub_str); - StringSink pub_string_sink(out.second); - PEM_Save(pub_string_sink, pub); - } - return out; - } - - std::pair generateRsaKeyPairs(uint32_t sig_length, KeyFormat fmt) { - AutoSeededRandomPool rng; - std::pair keyPair; - - RSAES>::Decryptor priv(rng, sig_length); - RSAES>::Encryptor pub(priv); - HexEncoder privEncoder(new StringSink(keyPair.first)); - priv.AccessMaterial().Save(privEncoder); - privEncoder.MessageEnd(); - - HexEncoder pubEncoder(new StringSink(keyPair.second)); - pub.AccessMaterial().Save(pubEncoder); - pubEncoder.MessageEnd(); - if (fmt == KeyFormat::PemFormat) { - keyPair = RsaHexToPem(keyPair); - } - return keyPair; - } - std::pair generateECDSAKeyPair(const KeyFormat fmt, CurveType curve_types) { - AutoSeededRandomPool prng; - ECDSA::PrivateKey privateKey; - ECDSA::PublicKey publicKey; - - privateKey.Initialize(prng, curve_types == CurveType::secp256k1 ? ASN1::secp256k1() : ASN1::secp384r1()); - privateKey.MakePublicKey(publicKey); - std::pair keyPair; - HexEncoder privEncoder(new StringSink(keyPair.first)); - privateKey.Save(privEncoder); - HexEncoder pubEncoder(new StringSink(keyPair.second)); - publicKey.Save(pubEncoder); - if (fmt == KeyFormat::PemFormat) { - keyPair = ECDSAHexToPem(keyPair); - } - return keyPair; - } - - ~Impl() = default; -}; - -std::pair Crypto::generateRsaKeyPair(const uint32_t sig_length, const KeyFormat fmt) const { - return impl_->generateRsaKeyPairs(sig_length, fmt); -} - -std::pair Crypto::RsaHexToPem(const std::pair& key_pair) const { - return impl_->RsaHexToPem(key_pair); -} - -std::pair Crypto::generateECDSAKeyPair(KeyFormat fmt, CurveType curve_types) const { - return impl_->generateECDSAKeyPair(fmt, curve_types); -} - -std::pair Crypto::ECDSAHexToPem(const std::pair& key_pair) const { - return impl_->ECDSAHexToPem(key_pair); -} - -KeyFormat Crypto::getFormat(const std::string& key) const { - return key.find("BEGIN") != std::string::npos ? KeyFormat::PemFormat : KeyFormat::HexaDecimalStrippedFormat; -} - -Crypto::Crypto() : impl_{new Impl()} {} - -Crypto::~Crypto() = default; - -bool CertificateUtils::verifyCertificate(X509* cert_to_verify, - const std::string& cert_root_directory, - uint32_t& remote_peer_id, - std::string& conn_type, - bool use_unified_certs) { - // First get the source ID - static constexpr size_t SIZE = 512; - std::string subject(SIZE, 0); - X509_NAME_oneline(X509_get_subject_name(cert_to_verify), subject.data(), SIZE); - - int peerIdPrefixLength = 3; - std::regex r("OU=\\d*", std::regex_constants::icase); - std::smatch sm; - regex_search(subject, sm, r); - - LOG_DEBUG(GL, "Subject from certificate " << subject.data()); - if (sm.length() <= peerIdPrefixLength) { - LOG_ERROR(GL, "OU not found or empty: " << subject); - return false; - } - - auto remPeer = sm.str().substr(peerIdPrefixLength, sm.str().length() - peerIdPrefixLength); - if (0 == remPeer.length()) { - LOG_ERROR(GL, "OU empty " << subject); - return false; - } - - uint32_t remotePeerId; - try { - remotePeerId = stoul(remPeer, nullptr); - } catch (const std::invalid_argument& ia) { - LOG_ERROR(GL, "cannot convert OU, " << subject << ", " << ia.what()); - return false; - } catch (const std::out_of_range& e) { - LOG_ERROR(GL, "cannot convert OU, " << subject << ", " << e.what()); - return false; - } - remote_peer_id = remotePeerId; - LOG_INFO(GL, "Peer: " << remote_peer_id); - std::string CN; - CN.resize(SIZE); - X509_NAME_get_text_by_NID(X509_get_subject_name(cert_to_verify), NID_commonName, CN.data(), SIZE); - - LOG_INFO(GL, "Field CN: " << CN.data()); - std::string cert_type = "server"; - if (CN.find("cli") != std::string::npos) cert_type = "client"; - conn_type = cert_type; - - // Get the local stored certificate for this peer - std::string local_cert_path = - (use_unified_certs) - ? cert_root_directory + "/" + std::to_string(remotePeerId) + "/" + "node.cert" - : cert_root_directory + "/" + std::to_string(remotePeerId) + "/" + cert_type + "/" + cert_type + ".cert"; - auto deleter = [](FILE* fp) { - if (fp) fclose(fp); - }; - std::unique_ptr fp(fopen(local_cert_path.c_str(), "r"), deleter); - if (!fp) { - LOG_ERROR(GL, "Certificate file not found, path: " << local_cert_path); - return false; - } - - X509* localCert = PEM_read_X509(fp.get(), NULL, NULL, NULL); - if (!localCert) { - LOG_ERROR(GL, "Cannot parse certificate, path: " << local_cert_path); - return false; - } - - // this is actual comparison, compares hash of 2 certs - bool res = (X509_cmp(cert_to_verify, localCert) == 0); - X509_free(localCert); - return res; -} -std::string CertificateUtils::generateSelfSignedCert(const std::string& origin_cert_path, - const std::string& public_key, - const std::string& signing_key) { - auto deleter = [](FILE* fp) { - if (fp) fclose(fp); - }; - std::unique_ptr fp(fopen(origin_cert_path.c_str(), "r"), deleter); - if (!fp) { - LOG_ERROR(GL, "Certificate file not found, path: " << origin_cert_path); - return std::string(); - } - - X509* cert = PEM_read_X509(fp.get(), NULL, NULL, NULL); - if (!cert) { - LOG_ERROR(GL, "Cannot parse certificate, path: " << origin_cert_path); - return std::string(); - } - - EVP_PKEY* priv_key = EVP_PKEY_new(); - BIO* priv_bio = BIO_new(BIO_s_mem()); - int priv_bio_write_ret = BIO_write(priv_bio, static_cast(signing_key.c_str()), signing_key.size()); - if (priv_bio_write_ret <= 0) { - EVP_PKEY_free(priv_key); - BIO_free(priv_bio); - X509_free(cert); - LOG_ERROR(GL, "Unable to create private key object"); - return std::string(); - } - if (!PEM_read_bio_PrivateKey(priv_bio, &priv_key, NULL, NULL)) { - EVP_PKEY_free(priv_key); - BIO_free(priv_bio); - X509_free(cert); - LOG_ERROR(GL, "Unable to create private key object"); - return std::string(); - } - EVP_PKEY* pub_key = EVP_PKEY_new(); - BIO* pub_bio = BIO_new(BIO_s_mem()); - int pub_bio_write_ret = BIO_write(pub_bio, static_cast(public_key.c_str()), public_key.size()); - if (pub_bio_write_ret <= 0) { - EVP_PKEY_free(priv_key); - EVP_PKEY_free(pub_key); - BIO_free(priv_bio); - BIO_free(pub_bio); - X509_free(cert); - LOG_ERROR(GL, "Unable to create public key object"); - return std::string(); - } - if (!PEM_read_bio_PUBKEY(pub_bio, &pub_key, NULL, NULL)) { - EVP_PKEY_free(priv_key); - EVP_PKEY_free(pub_key); - BIO_free(priv_bio); - BIO_free(pub_bio); - X509_free(cert); - LOG_ERROR(GL, "Unable to create public key object"); - return std::string(); - } - - X509_set_pubkey(cert, pub_key); - X509_sign(cert, priv_key, EVP_sha256()); - - BIO* outbio = BIO_new(BIO_s_mem()); - if (!PEM_write_bio_X509(outbio, cert)) { - BIO_free(outbio); - EVP_PKEY_free(priv_key); - EVP_PKEY_free(pub_key); - BIO_free(priv_bio); - BIO_free(pub_bio); - X509_free(cert); - LOG_ERROR(GL, "Unable to create certificate object"); - return std::string(); - } - std::string certStr; - int certLen = BIO_pending(outbio); - certStr.resize(certLen); - BIO_read(outbio, (void*)&(certStr.front()), certLen); - // free all pointers - BIO_free(outbio); - EVP_PKEY_free(priv_key); - BIO_free(priv_bio); - EVP_PKEY_free(pub_key); - BIO_free(pub_bio); - X509_free(cert); - return certStr; -} -bool CertificateUtils::verifyCertificate(X509* cert, const std::string& public_key) { - EVP_PKEY* pub_key = EVP_PKEY_new(); - BIO* pub_bio = BIO_new(BIO_s_mem()); - int pub_bio_write_ret = BIO_write(pub_bio, static_cast(public_key.c_str()), public_key.size()); - if (pub_bio_write_ret <= 0) { - EVP_PKEY_free(pub_key); - BIO_free(pub_bio); - return false; - } - if (!PEM_read_bio_PUBKEY(pub_bio, &pub_key, NULL, NULL)) { - EVP_PKEY_free(pub_key); - BIO_free(pub_bio); - return false; - } - int r = X509_verify(cert, pub_key); - EVP_PKEY_free(pub_key); - BIO_free(pub_bio); - return (bool)r; -} -} // namespace concord::util::crypto diff --git a/util/src/cryptopp_digest_creator.cpp b/util/src/cryptopp/digest_creator.cpp similarity index 93% rename from util/src/cryptopp_digest_creator.cpp rename to util/src/cryptopp/digest_creator.cpp index 7d9dc88b00..c1d27efa55 100644 --- a/util/src/cryptopp_digest_creator.cpp +++ b/util/src/cryptopp/digest_creator.cpp @@ -21,12 +21,13 @@ #include #include -#include "cryptopp_digest_creator.hpp" +#include "cryptopp/digest_creator.hpp" #include "digest.hpp" -namespace concord::util::digest { +namespace concord::util::crypto::cryptopp { using CryptoPP::SecByteBlock; +using concord::util::digest::DigestGenerator; CryptoppDigestCreator::CryptoppDigestCreator() { DigestType* p = new DigestType(); @@ -46,6 +47,7 @@ bool CryptoppDigestCreator::compute(const char* input, if (lengthOfBufferForDigest < size) { return false; } + SecByteBlock digest(size); dig.Update((CryptoPP::byte*)input, inputLength); @@ -86,4 +88,4 @@ CryptoppDigestCreator::~CryptoppDigestCreator() { internalState_ = nullptr; } } -} // namespace concord::util::digest +} // namespace concord::util::crypto::cryptopp diff --git a/util/src/hex_tools.cpp b/util/src/hex_tools.cpp index 170b3f60e9..a0c61d800a 100644 --- a/util/src/hex_tools.cpp +++ b/util/src/hex_tools.cpp @@ -65,4 +65,30 @@ std::string sliverToHex(const Sliver &sliver) { return bufferToHex(sliver.data() std::string vectorToHex(const std::vector &data) { return bufferToHex(data.data(), data.size()); } +std::vector unhex(const std::string &hex) { + const auto inputLen = hex.size(); + if (0 == inputLen) { + return {}; + } else if (inputLen % 2) { + throw std::invalid_argument{"Invalid hex string: " + hex}; + } + + const auto valid_chars = "0123456789abcdefABCDEF"; + auto start = std::string::size_type{0}; + if (hex.find("0x") == 0 || hex.find("0X") == 0) { + start += 2; + if (inputLen > 2 && hex.find_first_not_of(valid_chars, 2) != std::string::npos) { + throw std::invalid_argument{"Invalid hex string: " + hex}; + } + } else if (hex.find_first_not_of(valid_chars) != std::string::npos) { + throw std::invalid_argument{"Invalid hex string: " + hex}; + } + + auto index{0}; + std::vector output(inputLen / 2); + for (size_t i = start; i < inputLen; i += 2) { + output[index++] = static_cast(stoul(hex.substr(i, 2), nullptr, 16)); + } + return output; +} } // namespace concordUtils diff --git a/util/src/io.cpp b/util/src/io.cpp new file mode 100644 index 0000000000..1b195083c1 --- /dev/null +++ b/util/src/io.cpp @@ -0,0 +1,33 @@ +// Concord +// +// Copyright (c) 2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 +// License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the sub-component's license, as noted in the LICENSE +// file. + +#include "io.hpp" + +namespace concord::io { + +using std::string; + +string readFile(FILE* file, uint64_t maxBytes) { + string result; + + while (true) { + auto ch = std::fgetc(file); + + if ((ch == EOF) || (result.size() == maxBytes)) { + break; + } + result += static_cast(ch); + } + return result; +} +} // namespace concord::io diff --git a/util/src/openssl/utils.cpp b/util/src/openssl/utils.cpp new file mode 100644 index 0000000000..81385435c9 --- /dev/null +++ b/util/src/openssl/utils.cpp @@ -0,0 +1,182 @@ +// Concord +// +// Copyright (c) 2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 +// License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the sub-component's license, as noted in the LICENSE +// file. + +#include "utils.hpp" +#include "Logger.hpp" +#include "util/filesystem.hpp" + +#include + +namespace concord::crypto { +using std::unique_ptr; +using std::string; +using concord::crypto::SIGN_VERIFY_ALGO; +using concord::util::openssl_utils::UniquePKEY; +using concord::util::openssl_utils::UniqueOpenSSLX509; +using concord::util::openssl_utils::UniqueOpenSSLBIO; +using concord::util::openssl_utils::OPENSSL_SUCCESS; +using concord::util::openssl_utils::OPENSSL_FAILURE; +using concord::util::openssl_utils::OPENSSL_ERROR; + +string generateSelfSignedCert(const string& origin_cert_path, + const string& public_key, + const string& signing_key, + const SIGN_VERIFY_ALGO signingAlgo) { + unique_ptr fp(fopen(origin_cert_path.c_str(), "r"), fclose); + if (nullptr == fp) { + LOG_ERROR(OPENSSL_LOG, "Certificate file not found, path: " << origin_cert_path); + return string(); + } + + UniqueOpenSSLX509 cert(PEM_read_X509(fp.get(), nullptr, nullptr, nullptr)); + if (nullptr == cert) { + LOG_ERROR(OPENSSL_LOG, "Cannot parse certificate, path: " << origin_cert_path); + return string(); + } + + UniquePKEY priv_key(EVP_PKEY_new()); + UniqueOpenSSLBIO priv_bio(BIO_new(BIO_s_mem())); + + if (BIO_write(priv_bio.get(), static_cast(signing_key.c_str()), signing_key.size()) <= 0) { + LOG_ERROR(OPENSSL_LOG, "Unable to create private key object"); + return string(); + } + + if (nullptr == PEM_read_bio_PrivateKey(priv_bio.get(), reinterpret_cast(&priv_key), nullptr, nullptr)) { + LOG_ERROR(OPENSSL_LOG, "Unable to create private key object"); + return string(); + } + UniquePKEY pub_key(EVP_PKEY_new()); + UniqueOpenSSLBIO pub_bio(BIO_new(BIO_s_mem())); + + if (BIO_write(pub_bio.get(), static_cast(public_key.c_str()), public_key.size()) <= 0) { + LOG_ERROR(OPENSSL_LOG, "Unable to write public key object"); + return string(); + } + if (nullptr == PEM_read_bio_PUBKEY(pub_bio.get(), reinterpret_cast(&pub_key), nullptr, nullptr)) { + LOG_ERROR(OPENSSL_LOG, "Unable to create public key object"); + return string(); + } + + if (OPENSSL_FAILURE == X509_set_pubkey(cert.get(), pub_key.get())) { + LOG_ERROR(OPENSSL_LOG, "Failed to set public key for certificate."); + return {}; + } + + if (SIGN_VERIFY_ALGO::RSA == signingAlgo) { + if (OPENSSL_FAILURE == X509_sign(cert.get(), priv_key.get(), EVP_sha256())) { + LOG_ERROR(OPENSSL_LOG, "Failed to sign certificate using RSA private key."); + return {}; + } + } else if (SIGN_VERIFY_ALGO::EDDSA == signingAlgo) { + if (OPENSSL_FAILURE == X509_sign(cert.get(), priv_key.get(), nullptr)) { + LOG_ERROR(OPENSSL_LOG, "Failed to sign certificate using EdDSA private key."); + return {}; + } + } + + UniqueOpenSSLBIO outbio(BIO_new(BIO_s_mem())); + if (OPENSSL_FAILURE == PEM_write_bio_X509(outbio.get(), cert.get())) { + LOG_ERROR(OPENSSL_LOG, "Unable to create certificate object"); + return string(); + } + string certStr; + int certLen = BIO_pending(outbio.get()); + certStr.resize(certLen); + const auto res = BIO_read(outbio.get(), (void*)&(certStr.front()), certLen); + if (OPENSSL_FAILURE == res || OPENSSL_ERROR == res) { + LOG_ERROR(OPENSSL_LOG, "Failed to read data from the BIO certifiate object."); + return {}; + } + return certStr; +} + +bool verifyCertificate(X509& cert, const string& public_key) { + UniquePKEY pub_key(EVP_PKEY_new()); + UniqueOpenSSLBIO pub_bio(BIO_new(BIO_s_mem())); + + if (BIO_write(pub_bio.get(), static_cast(public_key.c_str()), public_key.size()) <= 0) { + return false; + } + if (nullptr == PEM_read_bio_PUBKEY(pub_bio.get(), reinterpret_cast(&pub_key), nullptr, nullptr)) { + return false; + } + return (OPENSSL_SUCCESS == X509_verify(&cert, pub_key.get())); +} + +bool verifyCertificate(const X509& cert_to_verify, + const string& cert_root_directory, + uint32_t& remote_peer_id, + string& conn_type, + bool use_unified_certs) { + // First get the source ID + static constexpr size_t SIZE = 512; + string subject(SIZE, 0); + X509_NAME_oneline(X509_get_subject_name(&cert_to_verify), subject.data(), SIZE); + + int peerIdPrefixLength = 3; + std::regex r("OU=\\d*", std::regex_constants::icase); + std::smatch sm; + regex_search(subject, sm, r); + if (sm.length() <= peerIdPrefixLength) { + LOG_ERROR(OPENSSL_LOG, "OU not found or empty: " << subject); + return false; + } + + auto remPeer = sm.str().substr(peerIdPrefixLength, sm.str().length() - peerIdPrefixLength); + if (0 == remPeer.length()) { + LOG_ERROR(OPENSSL_LOG, "OU empty " << subject); + return false; + } + + uint32_t remotePeerId; + try { + remotePeerId = stoul(remPeer, nullptr); + } catch (const std::invalid_argument& ia) { + LOG_ERROR(OPENSSL_LOG, "cannot convert OU, " << subject << ", " << ia.what()); + return false; + } catch (const std::out_of_range& e) { + LOG_ERROR(OPENSSL_LOG, "cannot convert OU, " << subject << ", " << e.what()); + return false; + } + remote_peer_id = remotePeerId; + string CN; + CN.resize(SIZE); + X509_NAME_get_text_by_NID(X509_get_subject_name(&cert_to_verify), NID_commonName, CN.data(), SIZE); + string cert_type = "server"; + if (CN.find("cli") != string::npos) { + cert_type = "client"; + } + conn_type = cert_type; + + // Get the local stored certificate for this peer + const fs::path local_cert_path = (use_unified_certs) + ? (fs::path(cert_root_directory) / std::to_string(remotePeerId) / "node.cert") + : (fs::path(cert_root_directory) / std::to_string(remotePeerId) / + fs::path(cert_type) / fs::path(cert_type + ".cert")); + std::unique_ptr fp(fopen(local_cert_path.c_str(), "r"), fclose); + if (nullptr == fp) { + LOG_ERROR(OPENSSL_LOG, "Certificate file not found, path: " << local_cert_path.string()); + return false; + } + + UniqueOpenSSLX509 localCert(PEM_read_X509(fp.get(), nullptr, nullptr, nullptr)); + if (nullptr == localCert) { + LOG_ERROR(OPENSSL_LOG, "Cannot parse certificate, path: " << local_cert_path.string()); + return false; + } + + // this is actual comparison, compares hash of 2 certs + return (X509_cmp(&cert_to_verify, localCert.get()) == 0); +} +} // namespace concord::crypto diff --git a/util/src/openssl_crypto.cpp b/util/src/openssl_crypto.cpp index 86658050ab..291b0771d1 100644 --- a/util/src/openssl_crypto.cpp +++ b/util/src/openssl_crypto.cpp @@ -14,7 +14,6 @@ #include "openssl_crypto.hpp" #include -#include #include #include #include @@ -23,6 +22,12 @@ using concord::util::openssl_utils::AsymmetricPrivateKey; using concord::util::openssl_utils::AsymmetricPublicKey; using concord::util::openssl_utils::kExpectedSHA256HashLengthInBytes; using concord::util::openssl_utils::UnexpectedOpenSSLCryptoFailureException; +using concord::util::openssl_utils::UniquePKEY; +using concord::util::openssl_utils::UniqueOpenSSLContext; +using concord::util::openssl_utils::UniqueOpenSSLBIGNUM; +using concord::util::openssl_utils::UniqueOpenSSLBNCTX; +using concord::util::openssl_utils::UniqueOpenSSLECKEY; +using concord::util::openssl_utils::UniqueOpenSSLECPOINT; using std::invalid_argument; using std::pair; using std::string; @@ -31,30 +36,6 @@ using std::unique_ptr; // Deleter classes for using smart pointers that correctly manage objects from // the OpenSSL Crypto library, given OpenSSL Crypto objects use free functions // provided by the library rather than normal destructors. -class BIGNUMDeleter { - public: - void operator()(BIGNUM* num) const { BN_clear_free(num); } -}; -class BNCTXDeleter { - public: - void operator()(BN_CTX* obj) const { BN_CTX_free(obj); } -}; -class ECKEYDeleter { - public: - void operator()(EC_KEY* obj) const { EC_KEY_free(obj); } -}; -class ECPOINTDeleter { - public: - void operator()(EC_POINT* obj) const { EC_POINT_clear_free(obj); } -}; -class EVPMDCTXDeleter { - public: - void operator()(EVP_MD_CTX* obj) const { EVP_MD_CTX_free(obj); } -}; -class EVPPKEYDeleter { - public: - void operator()(EVP_PKEY* obj) const { EVP_PKEY_free(obj); } -}; class OPENSSLStringDeleter { public: void operator()(char* string) const { OPENSSL_free(string); } @@ -64,7 +45,7 @@ class OPENSSLStringDeleter { // concord::util::openssl_crypto::AsymmetricPrivateKey. class EVPPKEYPrivateKey : public AsymmetricPrivateKey { private: - unique_ptr pkey; + UniquePKEY pkey; string scheme_name; public: @@ -83,8 +64,7 @@ class EVPPKEYPrivateKey : public AsymmetricPrivateKey { // EVP_PKEY object must have both its private and public keys initialized; // future behavior of this EVPPKEYPrivateKey object is undefined if this // precondition is not met. - EVPPKEYPrivateKey(unique_ptr&& pkey_ptr, const string& scheme) - : pkey(move(pkey_ptr)), scheme_name(scheme) {} + EVPPKEYPrivateKey(UniquePKEY&& pkey_ptr, const string& scheme) : pkey(move(pkey_ptr)), scheme_name(scheme) {} virtual ~EVPPKEYPrivateKey() override {} virtual string serialize() const override { @@ -115,7 +95,7 @@ class EVPPKEYPrivateKey : public AsymmetricPrivateKey { } virtual std::string sign(const std::string& message) const override { - unique_ptr digest_context(EVP_MD_CTX_new(), EVPMDCTXDeleter()); + UniqueOpenSSLContext digest_context(EVP_MD_CTX_new()); if (!digest_context) { throw UnexpectedOpenSSLCryptoFailureException( "OpenSSL Crypto unexpectedly failed to allocate a message digest " @@ -162,7 +142,7 @@ class EVPPKEYPrivateKey : public AsymmetricPrivateKey { // concord::util::openssl_crypto::AsymmetricPublicKey. class EVPPKEYPublicKey : public AsymmetricPublicKey { private: - unique_ptr pkey; + UniquePKEY pkey; string scheme_name; public: @@ -180,8 +160,7 @@ class EVPPKEYPublicKey : public AsymmetricPublicKey { // constructed with. A precondition of this constructor is that the provided // EVP_PKEY object must its public key initialized; future behavior of this // EVPPKEYPublicKey object is undefined if this precondition is not met. - EVPPKEYPublicKey(unique_ptr&& pkey_ptr, const string& scheme) - : pkey(move(pkey_ptr)), scheme_name(scheme) {} + EVPPKEYPublicKey(UniquePKEY&& pkey_ptr, const string& scheme) : pkey(move(pkey_ptr)), scheme_name(scheme) {} virtual ~EVPPKEYPublicKey() override {} virtual string serialize() const override { @@ -199,7 +178,7 @@ class EVPPKEYPublicKey : public AsymmetricPublicKey { "OpenSSL Crypto unexpectedly failed to fetch the elliptic curve " "group from an elliptic curve key object."); } - unique_ptr big_num_context(BN_CTX_new(), BNCTXDeleter()); + UniqueOpenSSLBNCTX big_num_context(BN_CTX_new()); if (!big_num_context) { throw UnexpectedOpenSSLCryptoFailureException( "OpenSSL Crypto unexpectedly failed to allocate a big number " @@ -227,7 +206,7 @@ class EVPPKEYPublicKey : public AsymmetricPublicKey { } virtual bool verify(const std::string& message, const std::string& signature) const override { - unique_ptr digest_context(EVP_MD_CTX_new(), EVPMDCTXDeleter()); + UniqueOpenSSLContext digest_context(EVP_MD_CTX_new()); if (!digest_context) { throw UnexpectedOpenSSLCryptoFailureException( "OpenSSL Crypto unexpectedly failed to allocate a message digest " @@ -260,8 +239,8 @@ concord::util::openssl_utils::generateAsymmetricCryptoKeyPair(const string& sche // prime256v1 is an alternative name for the same curve parameters as // secp256r1; prime256v1 happens to be the name OpenSSL's Crypto library // uses for a possible parameter to EC_KEY_new_by_curve_name. - unique_ptr key_pair(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1), ECKEYDeleter()); - unique_ptr public_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1), ECKEYDeleter()); + UniqueOpenSSLECKEY key_pair(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + UniqueOpenSSLECKEY public_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); if (!key_pair || !public_key) { throw UnexpectedOpenSSLCryptoFailureException( "OpenSSL Crypto unexpectedly failed to allocate and prepare an " @@ -283,8 +262,8 @@ concord::util::openssl_utils::generateAsymmetricCryptoKeyPair(const string& sche "OpenSSL Crypto unexpectedly failed to set the public key for an " "empty allocated elliptic curve key object."); } - unique_ptr private_pkey(EVP_PKEY_new(), EVPPKEYDeleter()); - unique_ptr public_pkey(EVP_PKEY_new(), EVPPKEYDeleter()); + UniquePKEY private_pkey(EVP_PKEY_new()); + UniquePKEY public_pkey(EVP_PKEY_new()); if (!private_pkey || !public_pkey) { throw UnexpectedOpenSSLCryptoFailureException( "OpenSSL Crypto unexpectedly failed to allocate and prepare a " @@ -340,13 +319,13 @@ unique_ptr concord::util::openssl_utils::deserializePrivat // prime256v1 is an alternative name for the same curve parameters as // secp256r1; prime256v1 happens to be the name OpenSSL's Crypto library // uses for a possible parameter to EC_KEY_new_by_curve_name. - unique_ptr ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1), ECKEYDeleter()); - if (!ec_key) { + UniqueOpenSSLECKEY ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + if (nullptr == ec_key.get()) { throw UnexpectedOpenSSLCryptoFailureException( "OpenSSL Crypto unexpectedly failed to allocate and prepare an " "elliptic curve key object."); } - unique_ptr private_key(nullptr, BIGNUMDeleter()); + UniqueOpenSSLBIGNUM private_key(nullptr); BIGNUM* allocated_private_key = nullptr; int hex_parse_return_code = BN_hex2bn(&allocated_private_key, private_key_data.c_str()); private_key.reset(allocated_private_key); @@ -375,13 +354,13 @@ unique_ptr concord::util::openssl_utils::deserializePrivat "OpenSSL Crypto unexpectedly failed to fetch the elliptic curve " "group for an elliptic curve key object."); } - unique_ptr public_key(EC_POINT_new(ec_group), ECPOINTDeleter()); + UniqueOpenSSLECPOINT public_key(EC_POINT_new(ec_group)); if (!public_key) { throw UnexpectedOpenSSLCryptoFailureException( "OpenSSL Crypto unexpectedly failed to allocate an elliptic curve " "point object."); } - unique_ptr public_key_derivation_context(BN_CTX_new(), BNCTXDeleter()); + UniqueOpenSSLBNCTX public_key_derivation_context(BN_CTX_new()); if (!public_key_derivation_context) { throw UnexpectedOpenSSLCryptoFailureException( "OpenSSL Crypto unexpectedly failed to allocate a big number context " @@ -400,7 +379,7 @@ unique_ptr concord::util::openssl_utils::deserializePrivat "curve key object."); } - unique_ptr private_pkey(EVP_PKEY_new(), EVPPKEYDeleter()); + UniquePKEY private_pkey(EVP_PKEY_new()); if (!private_pkey) { throw UnexpectedOpenSSLCryptoFailureException( "OpenSSL Crypto unexpectedly failed to allocate and prepare a " @@ -431,30 +410,25 @@ std::unique_ptr concord::util::openssl_utils::deserializeP "(which could be because it does not meet them, or could simply be " "because we have not assessed this particular scheme)."); } - FILE* fp = fopen(path_to_file.c_str(), "r"); - if (!fp) { + unique_ptr fp(fopen(path_to_file.c_str(), "r"), fclose); + if (nullptr == fp) { return nullptr; } - EC_KEY* pkey = EC_KEY_new(); + UniqueOpenSSLECKEY pkey(EC_KEY_new()); - if (!PEM_read_ECPrivateKey(fp, &pkey, nullptr, nullptr)) { - fclose(fp); - EC_KEY_free(pkey); + if (!PEM_read_ECPrivateKey(fp.get(), reinterpret_cast(pkey.get()), nullptr, nullptr)) { throw UnexpectedOpenSSLCryptoFailureException( "OpenSSL Crypto unexpectedly failed to parse the private key file " "for " + path_to_file); } - fclose(fp); - unique_ptr private_pkey(EVP_PKEY_new(), EVPPKEYDeleter()); - if (!EVP_PKEY_set1_EC_KEY(private_pkey.get(), pkey)) { - EC_KEY_free(pkey); + UniquePKEY private_pkey(EVP_PKEY_new()); + if (!EVP_PKEY_set1_EC_KEY(private_pkey.get(), pkey.get())) { throw UnexpectedOpenSSLCryptoFailureException( "OpenSSL Crypto unexpectedly failed to initialize a high-level key " "object given an elliptic curve key object."); } - EC_KEY_free(pkey); return std::make_unique(std::move(private_pkey), "secp256r1"); } @@ -500,7 +474,7 @@ std::unique_ptr concord::util::openssl_utils::deserializeP EVP_PKEY_free(pkey); BIO_free(bio); - unique_ptr private_pkey(EVP_PKEY_new(), EVPPKEYDeleter()); + UniquePKEY private_pkey(EVP_PKEY_new()); if (!EVP_PKEY_set1_EC_KEY(private_pkey.get(), eckey)) { EC_KEY_free(eckey); throw UnexpectedOpenSSLCryptoFailureException( @@ -520,27 +494,24 @@ std::unique_ptr concord::util::openssl_utils::deserializePu "(which could be because it does not meet them, or could simply be " "because we have not assessed this particular scheme)."); } - FILE* fp = fopen(path_to_file.c_str(), "r"); - if (!fp) { - return nullptr; + unique_ptr fp(fopen(path_to_file.c_str(), "r"), fclose); + if (nullptr == fp) { + throw UnexpectedOpenSSLCryptoFailureException( + "OpenSSL Crypto unexpectedly failed to open the public key file for " + path_to_file); } - EC_KEY* pkey = EC_KEY_new(); + UniqueOpenSSLECKEY pkey(EC_KEY_new()); - if (!PEM_read_EC_PUBKEY(fp, &pkey, nullptr, nullptr)) { - fclose(fp); - EC_KEY_free(pkey); + if (!PEM_read_EC_PUBKEY(fp.get(), reinterpret_cast(pkey.get()), nullptr, nullptr)) { throw UnexpectedOpenSSLCryptoFailureException( "OpenSSL Crypto unexpectedly failed to parse the public key file for " + path_to_file); } - fclose(fp); - unique_ptr public_pkey(EVP_PKEY_new(), EVPPKEYDeleter()); - if (!EVP_PKEY_set1_EC_KEY(public_pkey.get(), pkey)) { - EC_KEY_free(pkey); + + UniquePKEY public_pkey(EVP_PKEY_new()); + if (!EVP_PKEY_set1_EC_KEY(public_pkey.get(), pkey.get())) { throw UnexpectedOpenSSLCryptoFailureException( "OpenSSL Crypto unexpectedly failed to initialize a high-level key " "object given an elliptic curve key object."); } - EC_KEY_free(pkey); return std::make_unique(std::move(public_pkey), "secp256r1"); } @@ -571,8 +542,8 @@ unique_ptr concord::util::openssl_utils::deserializePublicK // prime256v1 is an alternative name for the same curve parameters as // secp256r1; prime256v1 happens to be the name OpenSSL's Crypto library // uses for a possible parameter to EC_KEY_new_by_curve_name. - unique_ptr ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1), ECKEYDeleter()); - if (!ec_key) { + UniqueOpenSSLECKEY ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + if (nullptr == ec_key.get()) { throw UnexpectedOpenSSLCryptoFailureException( "OpenSSL Crypto unexpectedly failed to allocate and prepare an " "elliptic curve key object."); @@ -583,13 +554,13 @@ unique_ptr concord::util::openssl_utils::deserializePublicK "OpenSSL Crypto unexpectedly failed to fetch the elliptic curve " "group from an elliptic curve key object."); } - unique_ptr public_key(EC_POINT_new(ec_group), ECPOINTDeleter()); + UniqueOpenSSLECPOINT public_key(EC_POINT_new(ec_group)); if (!public_key) { throw UnexpectedOpenSSLCryptoFailureException( "OpenSSL Crypto unexpectedly failed to allocate an elliptic curve " "point object."); } - unique_ptr big_num_context(BN_CTX_new(), BNCTXDeleter()); + UniqueOpenSSLBNCTX big_num_context(BN_CTX_new()); if (!big_num_context) { throw UnexpectedOpenSSLCryptoFailureException( "OpenSSL Crypto unexpectedly failed to allocate a big number context " @@ -608,7 +579,7 @@ unique_ptr concord::util::openssl_utils::deserializePublicK "elliptic curve key object."); } - unique_ptr public_pkey(EVP_PKEY_new(), EVPPKEYDeleter()); + UniquePKEY public_pkey(EVP_PKEY_new()); if (!public_pkey) { throw UnexpectedOpenSSLCryptoFailureException( "OpenSSL Crypto unexpectedly failed to allocate and prepare a " @@ -635,7 +606,7 @@ string concord::util::openssl_utils::computeSHA256Hash(const string& data) { } string concord::util::openssl_utils::computeSHA256Hash(const char* data, size_t length) { - unique_ptr digest_context(EVP_MD_CTX_new(), EVPMDCTXDeleter()); + UniqueOpenSSLContext digest_context(EVP_MD_CTX_new()); if (!digest_context) { throw UnexpectedOpenSSLCryptoFailureException( "OpenSSL Crypto unexpectedly failed to allocate a message digest " @@ -668,4 +639,4 @@ string concord::util::openssl_utils::computeSHA256Hash(const char* data, size_t } return hash; -} +} \ No newline at end of file diff --git a/util/test/CMakeLists.txt b/util/test/CMakeLists.txt index 36f6c7ab0e..671faeac59 100644 --- a/util/test/CMakeLists.txt +++ b/util/test/CMakeLists.txt @@ -75,9 +75,13 @@ add_executable(RawMemoryPool_test RawMemoryPool_test.cpp) add_test(RawMemoryPool_test RawMemoryPool_test) target_link_libraries(RawMemoryPool_test GTest::Main util) -add_executable(crypto_utils_test crypto_utils_test.cpp ) -add_test(crypto_utils_test crypto_utils_test) -target_link_libraries(crypto_utils_test GTest::Main util) +add_executable(cryptopp_utils_test cryptopp_utils_test.cpp ) +add_test(cryptopp_utils_test cryptopp_utils_test) +target_link_libraries(cryptopp_utils_test GTest::Main util) + +add_executable(openssl_utils_test openssl_utils_test.cpp ) +add_test(openssl_utils_test openssl_utils_test) +target_link_libraries(openssl_utils_test GTest::Main util) add_executable(synchronized_value_test synchronized_value_test.cpp) add_test(synchronized_value_test synchronized_value_test) @@ -95,6 +99,10 @@ add_executable(openssl_digest_creator_test openssl_digest_creator_test.cpp) add_test(openssl_digest_creator_test openssl_digest_creator_test) target_link_libraries(openssl_digest_creator_test GTest::Main util) -add_executable(digest_holder_test digest_holder_test.cpp) -add_test(digest_holder_test digest_holder_test) -target_link_libraries(digest_holder_test GTest::Main util) +add_executable(cryptopp_digest_holder_test cryptopp_digest_holder_test.cpp) +add_test(cryptopp_digest_holder_test cryptopp_digest_holder_test) +target_link_libraries(cryptopp_digest_holder_test GTest::Main util) + +add_executable(openssl_digest_holder_test openssl_digest_holder_test.cpp) +add_test(openssl_digest_holder_test openssl_digest_holder_test) +target_link_libraries(openssl_digest_holder_test GTest::Main util) diff --git a/util/test/crypto_utils_test.cpp b/util/test/crypto_utils_test.cpp index 38ec7f4057..bcd088af67 100644 --- a/util/test/crypto_utils_test.cpp +++ b/util/test/crypto_utils_test.cpp @@ -13,36 +13,42 @@ // #include "gtest/gtest.h" -#include "crypto_utils.hpp" +#include "crypto.hpp" #include "Logger.hpp" -using namespace concord::util::crypto; + namespace { + +using concord::crypto::generateRsaKeyPair; +using concord::crypto::RsaHexToPem; +using concord::crypto::generateECDSAKeyPair; +using concord::crypto::ECDSAHexToPem; + TEST(crypto_utils, generate_rsa_keys_hex_format) { - ASSERT_NO_THROW(Crypto::instance().generateRsaKeyPair(2048, KeyFormat::HexaDecimalStrippedFormat)); - auto keys = Crypto::instance().generateRsaKeyPair(2048, KeyFormat::HexaDecimalStrippedFormat); + ASSERT_NO_THROW(generateRsaKeyPair(RSA_SIGNATURE_LENGTH)); + auto keys = generateRsaKeyPair(RSA_SIGNATURE_LENGTH); LOG_INFO(GL, keys.first << " | " << keys.second); } TEST(crypto_utils, generate_rsa_keys_pem_format) { - ASSERT_NO_THROW(Crypto::instance().generateRsaKeyPair(2048, KeyFormat::PemFormat)); - auto keys = Crypto::instance().generateRsaKeyPair(2048, KeyFormat::PemFormat); + ASSERT_NO_THROW(generateRsaKeyPair(RSA_SIGNATURE_LENGTH, KeyFormat::PemFormat)); + auto keys = generateRsaKeyPair(RSA_SIGNATURE_LENGTH, KeyFormat::PemFormat); LOG_INFO(GL, keys.first << " | " << keys.second); } TEST(crypto_utils, generate_ECDSA_keys_pem_format) { - ASSERT_NO_THROW(Crypto::instance().generateECDSAKeyPair(KeyFormat::PemFormat)); - auto keys = Crypto::instance().generateECDSAKeyPair(KeyFormat::PemFormat); + ASSERT_NO_THROW(generateECDSAKeyPair(KeyFormat::PemFormat)); + auto keys = generateECDSAKeyPair(KeyFormat::PemFormat); LOG_INFO(GL, keys.first << " | " << keys.second); } TEST(crypto_utils, generate_ECDSA_keys_hex_format) { - ASSERT_NO_THROW(Crypto::instance().generateECDSAKeyPair(KeyFormat::HexaDecimalStrippedFormat)); - auto keys = Crypto::instance().generateECDSAKeyPair(KeyFormat::HexaDecimalStrippedFormat); + ASSERT_NO_THROW(generateECDSAKeyPair(KeyFormat::HexaDecimalStrippedFormat)); + auto keys = generateECDSAKeyPair(KeyFormat::HexaDecimalStrippedFormat); LOG_INFO(GL, keys.first << " | " << keys.second); } TEST(crypto_utils, test_rsa_keys_hex) { - auto keys = Crypto::instance().generateRsaKeyPair(2048, KeyFormat::HexaDecimalStrippedFormat); + auto keys = generateRsaKeyPair(RSA_SIGNATURE_LENGTH); RSASigner signer(keys.first, KeyFormat::HexaDecimalStrippedFormat); RSAVerifier verifier(keys.second, KeyFormat::HexaDecimalStrippedFormat); std::string data = "Hello world"; @@ -51,7 +57,7 @@ TEST(crypto_utils, test_rsa_keys_hex) { } TEST(crypto_utils, test_rsa_keys_pem) { - auto keys = Crypto::instance().generateRsaKeyPair(2048, KeyFormat::PemFormat); + auto keys = generateRsaKeyPair(RSA_SIGNATURE_LENGTH, KeyFormat::PemFormat); RSASigner signer(keys.first, KeyFormat::PemFormat); RSAVerifier verifier(keys.second, KeyFormat::PemFormat); std::string data = "Hello world"; @@ -60,8 +66,8 @@ TEST(crypto_utils, test_rsa_keys_pem) { } TEST(crypto_utils, test_rsa_keys_combined_a) { - auto keys = Crypto::instance().generateRsaKeyPair(2048, KeyFormat::HexaDecimalStrippedFormat); - auto pemKeys = Crypto::instance().RsaHexToPem(keys); + auto keys = generateRsaKeyPair(RSA_SIGNATURE_LENGTH); + auto pemKeys = RsaHexToPem(keys); RSASigner signer(keys.first, KeyFormat::HexaDecimalStrippedFormat); RSAVerifier verifier(pemKeys.second, KeyFormat::PemFormat); std::string data = "Hello world"; @@ -70,8 +76,8 @@ TEST(crypto_utils, test_rsa_keys_combined_a) { } TEST(crypto_utils, test_rsa_keys_combined_b) { - auto keys = Crypto::instance().generateRsaKeyPair(2048, KeyFormat::HexaDecimalStrippedFormat); - auto pemKeys = Crypto::instance().RsaHexToPem(keys); + auto keys = generateRsaKeyPair(RSA_SIGNATURE_LENGTH); + auto pemKeys = RsaHexToPem(keys); RSASigner signer(pemKeys.first, KeyFormat::PemFormat); RSAVerifier verifier(keys.second, KeyFormat::HexaDecimalStrippedFormat); std::string data = "Hello world"; @@ -80,7 +86,7 @@ TEST(crypto_utils, test_rsa_keys_combined_b) { } TEST(crypto_utils, test_ecdsa_keys_hex) { - auto keys = Crypto::instance().generateECDSAKeyPair(KeyFormat::HexaDecimalStrippedFormat); + auto keys = generateECDSAKeyPair(KeyFormat::HexaDecimalStrippedFormat); ECDSASigner signer(keys.first, KeyFormat::HexaDecimalStrippedFormat); ECDSAVerifier verifier(keys.second, KeyFormat::HexaDecimalStrippedFormat); std::string data = "Hello world"; @@ -89,7 +95,7 @@ TEST(crypto_utils, test_ecdsa_keys_hex) { } TEST(crypto_utils, test_ecdsa_keys_pem) { - auto keys = Crypto::instance().generateECDSAKeyPair(KeyFormat::PemFormat); + auto keys = generateECDSAKeyPair(KeyFormat::PemFormat); ECDSASigner signer(keys.first, KeyFormat::PemFormat); ECDSAVerifier verifier(keys.second, KeyFormat::PemFormat); std::string data = "Hello world"; @@ -98,8 +104,8 @@ TEST(crypto_utils, test_ecdsa_keys_pem) { } TEST(crypto_utils, test_ecdsa_keys_pem_combined_a) { - auto keys = Crypto::instance().generateECDSAKeyPair(KeyFormat::HexaDecimalStrippedFormat); - auto pemKeys = Crypto::instance().ECDSAHexToPem(keys); + auto keys = generateECDSAKeyPair(KeyFormat::HexaDecimalStrippedFormat); + auto pemKeys = ECDSAHexToPem(keys); ECDSASigner signer(keys.first, KeyFormat::HexaDecimalStrippedFormat); ECDSAVerifier verifier(pemKeys.second, KeyFormat::PemFormat); std::string data = "Hello world"; @@ -108,8 +114,8 @@ TEST(crypto_utils, test_ecdsa_keys_pem_combined_a) { } TEST(crypto_utils, test_ecdsa_keys_pem_combined_b) { - auto keys = Crypto::instance().generateECDSAKeyPair(KeyFormat::HexaDecimalStrippedFormat); - auto pemKeys = Crypto::instance().ECDSAHexToPem(keys); + auto keys = generateECDSAKeyPair(KeyFormat::HexaDecimalStrippedFormat); + auto pemKeys = ECDSAHexToPem(keys); ECDSASigner signer(pemKeys.first, KeyFormat::PemFormat); ECDSAVerifier verifier(keys.second, KeyFormat::HexaDecimalStrippedFormat); std::string data = "Hello world"; diff --git a/util/test/cryptopp_digest_creator_test.cpp b/util/test/cryptopp_digest_creator_test.cpp index 78c93c883f..4589ca83a2 100644 --- a/util/test/cryptopp_digest_creator_test.cpp +++ b/util/test/cryptopp_digest_creator_test.cpp @@ -14,9 +14,9 @@ #include "gtest/gtest.h" #include "hex_tools.h" -#include "cryptopp_digest_creator.hpp" +#include "cryptopp/digest_creator.hpp" -using concord::util::digest::CryptoppDigestCreator; +using concord::util::crypto::cryptopp::CryptoppDigestCreator; using DigestGeneratorTest = CryptoppDigestCreator; diff --git a/util/test/cryptopp_digest_holder_test.cpp b/util/test/cryptopp_digest_holder_test.cpp new file mode 100644 index 0000000000..78dfaf2d5c --- /dev/null +++ b/util/test/cryptopp_digest_holder_test.cpp @@ -0,0 +1,142 @@ +// Concord +// +// Copyright (c) 2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 +// License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the subcomponent's license, as noted in the LICENSE +// file. +// + +#include "gtest/gtest.h" +#include "hex_tools.h" +#include "digest_holder.hpp" +#include "cryptopp/digest_creator.hpp" + +using concord::util::digest::DigestHolder; +using concord::util::crypto::cryptopp::CryptoppDigestCreator; + +using Digest = DigestHolder; + +// Hashes are generated via https://emn178.github.io/online-tools/sha256.html +struct SHA_Hashes { + std::string input; + std::string hash; +}; +SHA_Hashes sha256_hashes[] = {{"sha256", "5d5b09f6dcb2d53a5fffc60c4ac0d55fabdf556069d6631545f42aa6e3500f2e"}, + {"", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}, + {"vmware", "592cc302663c0021ffa92186bf3c1a579a97e5e01f8b28f766855e5b121f8bda"}, + {"5d5b09f6dcb2d53a5fffc60c4ac0d55fabdf556069d6631545f42aa6e3500f2e", "20a30eabfaa29aff866ce471dd7bc129cb3c368bc49409a499a1fbd5851b36cb"}/* Digest of digest (sha256_hashes[0].input). + Change the input type to Hex in online tool. To calculate digestOfDigest. */}; + +namespace { + +TEST(cryptopp_digest_holder_test, test_constructors) { + { + Digest digest; + ASSERT_EQ(true, digest.isZero()); + } + { + unsigned char c = 'a'; + Digest digest(c); + ASSERT_EQ(false, digest.isZero()); + ASSERT_EQ(0, memcmp(digest.content(), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", DIGEST_SIZE)); + + digest.makeZero(); + ASSERT_EQ(true, digest.isZero()); + } + { + const char* cp = "VMware."; + Digest digest(cp); + ASSERT_EQ(false, digest.isZero()); + ASSERT_EQ(0, memcmp(digest.content(), "VMware.", strlen(cp))); + + digest.makeZero(); + ASSERT_EQ(true, digest.isZero()); + } + { + const char* cp = "This is a string whose length is greater than DIGEST_SIZE."; + Digest digest(cp); + ASSERT_EQ(false, digest.isZero()); + ASSERT_EQ(0, memcmp(digest.content(), "This is a string whose length is", DIGEST_SIZE)); + + digest.makeZero(); + ASSERT_EQ(true, digest.isZero()); + } + { + const char* cp = "VMware."; + Digest digest(cp); + ASSERT_EQ(false, digest.isZero()); + ASSERT_EQ(0, memcmp(digest.content(), "VMware.", strlen(cp))); + + Digest digest_1 = digest; // Copy constructor test. + ASSERT_EQ(false, digest_1.isZero()); + ASSERT_EQ(0, memcmp(digest_1.content(), "VMware.", strlen(cp))); + + digest_1.makeZero(); + ASSERT_EQ(true, digest_1.isZero()); + } + { + Digest digest(sha256_hashes[0].input.data(), sha256_hashes[0].input.size()); + ASSERT_EQ(false, digest.isZero()); + ASSERT_EQ(0, + memcmp(sha256_hashes[0].hash.data(), + concordUtils::bufferToHex(digest.get(), DIGEST_SIZE, false).data(), + DIGEST_SIZE)); + + std::string s1 = concordUtils::bufferToHex(digest.getForUpdate(), DIGEST_SIZE, false); + std::string s2 = digest.toString(); + + ASSERT_EQ(s1, s2); + } +} + +TEST(cryptopp_digest_holder_test, test_overloaded_operators) { + { + const char* cp = "VMware."; + Digest digest_1(cp); + Digest digest_2(cp); + + ASSERT_EQ(true, digest_1 == digest_2); + ASSERT_EQ(false, digest_1 != digest_2); + + ASSERT_EQ(true, digest_2 == digest_1); + ASSERT_EQ(false, digest_2 != digest_1); + } + { + const char* cp = "VMware."; + Digest digest_1(cp); + Digest digest_2('c'); + + ASSERT_EQ(false, digest_1 == digest_2); + ASSERT_EQ(true, digest_1 != digest_2); + } + { + const char* cp = "VMware."; + Digest digest_1(cp); + Digest digest_2; + digest_2 = digest_1; // Assignment copy operator. + + ASSERT_EQ(true, digest_1 == digest_2); + ASSERT_EQ(false, digest_1 != digest_2); + } +} + +TEST(cryptopp_digest_holder_test, test_digest_of_digest) { + Digest digest(sha256_hashes[0].input.data(), sha256_hashes[0].input.size()); + Digest digest_of_digest; + + digest.digestOfDigest(digest_of_digest); + + ASSERT_EQ(true, digest_of_digest.toString() == sha256_hashes[3].hash); +} +} // namespace + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/util/test/cryptopp_utils_test.cpp b/util/test/cryptopp_utils_test.cpp new file mode 100644 index 0000000000..9548e08072 --- /dev/null +++ b/util/test/cryptopp_utils_test.cpp @@ -0,0 +1,134 @@ +// Concord +// +// Copyright (c) 2020 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 +// License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the subcomponent's license, as noted in the LICENSE +// file. +// + +#include "gtest/gtest.h" +#include "crypto.hpp" +#include "crypto/cryptopp/signers.hpp" +#include "crypto/cryptopp/verifiers.hpp" +#include "Logger.hpp" + +namespace { +using namespace concord::crypto::cryptopp; +using concord::crypto::KeyFormat; +using concord::crypto::cryptopp::RSA_SIGNATURE_LENGTH; +using concord::crypto::generateRsaKeyPair; +using concord::crypto::RsaHexToPem; +using concord::crypto::generateECDSAKeyPair; +using concord::crypto::ECDSAHexToPem; + +TEST(cryptopp_utils, generate_rsa_keys_hex_format) { + ASSERT_NO_THROW(generateRsaKeyPair(RSA_SIGNATURE_LENGTH)); + auto keys = generateRsaKeyPair(RSA_SIGNATURE_LENGTH); + LOG_INFO(GL, keys.first << " | " << keys.second); +} + +TEST(cryptopp_utils, generate_rsa_keys_pem_format) { + ASSERT_NO_THROW(generateRsaKeyPair(RSA_SIGNATURE_LENGTH, KeyFormat::PemFormat)); + auto keys = generateRsaKeyPair(RSA_SIGNATURE_LENGTH, KeyFormat::PemFormat); + LOG_INFO(GL, keys.first << " | " << keys.second); +} + +TEST(cryptopp_utils, generate_ECDSA_keys_pem_format) { + ASSERT_NO_THROW(generateECDSAKeyPair(KeyFormat::PemFormat)); + auto keys = generateECDSAKeyPair(KeyFormat::PemFormat); + LOG_INFO(GL, keys.first << " | " << keys.second); +} + +TEST(cryptopp_utils, generate_ECDSA_keys_hex_format) { + ASSERT_NO_THROW(generateECDSAKeyPair(KeyFormat::HexaDecimalStrippedFormat)); + auto keys = generateECDSAKeyPair(KeyFormat::HexaDecimalStrippedFormat); + LOG_INFO(GL, keys.first << " | " << keys.second); +} + +TEST(cryptopp_utils, test_rsa_keys_hex) { + auto keys = generateRsaKeyPair(RSA_SIGNATURE_LENGTH); + RSASigner signer(keys.first, KeyFormat::HexaDecimalStrippedFormat); + RSAVerifier verifier(keys.second, KeyFormat::HexaDecimalStrippedFormat); + std::string data = "Hello world"; + auto sig = signer.sign(data); + ASSERT_TRUE(verifier.verify(data, sig)); +} + +TEST(cryptopp_utils, test_rsa_keys_pem) { + auto keys = generateRsaKeyPair(RSA_SIGNATURE_LENGTH, KeyFormat::PemFormat); + RSASigner signer(keys.first, KeyFormat::PemFormat); + RSAVerifier verifier(keys.second, KeyFormat::PemFormat); + std::string data = "Hello world"; + auto sig = signer.sign(data); + ASSERT_TRUE(verifier.verify(data, sig)); +} + +TEST(cryptopp_utils, test_rsa_keys_combined_a) { + auto keys = generateRsaKeyPair(RSA_SIGNATURE_LENGTH); + auto pemKeys = RsaHexToPem(keys); + RSASigner signer(keys.first, KeyFormat::HexaDecimalStrippedFormat); + RSAVerifier verifier(pemKeys.second, KeyFormat::PemFormat); + std::string data = "Hello world"; + auto sig = signer.sign(data); + ASSERT_TRUE(verifier.verify(data, sig)); +} + +TEST(cryptopp_utils, test_rsa_keys_combined_b) { + auto keys = generateRsaKeyPair(RSA_SIGNATURE_LENGTH); + auto pemKeys = RsaHexToPem(keys); + RSASigner signer(pemKeys.first, KeyFormat::PemFormat); + RSAVerifier verifier(keys.second, KeyFormat::HexaDecimalStrippedFormat); + std::string data = "Hello world"; + auto sig = signer.sign(data); + ASSERT_TRUE(verifier.verify(data, sig)); +} + +TEST(cryptopp_utils, test_ecdsa_keys_hex) { + auto keys = generateECDSAKeyPair(KeyFormat::HexaDecimalStrippedFormat); + ECDSASigner signer(keys.first, KeyFormat::HexaDecimalStrippedFormat); + ECDSAVerifier verifier(keys.second, KeyFormat::HexaDecimalStrippedFormat); + std::string data = "Hello world"; + auto sig = signer.sign(data); + ASSERT_TRUE(verifier.verify(data, sig)); +} + +TEST(cryptopp_utils, test_ecdsa_keys_pem) { + auto keys = generateECDSAKeyPair(KeyFormat::PemFormat); + ECDSASigner signer(keys.first, KeyFormat::PemFormat); + ECDSAVerifier verifier(keys.second, KeyFormat::PemFormat); + std::string data = "Hello world"; + auto sig = signer.sign(data); + ASSERT_TRUE(verifier.verify(data, sig)); +} + +TEST(cryptopp_utils, test_ecdsa_keys_pem_combined_a) { + auto keys = generateECDSAKeyPair(KeyFormat::HexaDecimalStrippedFormat); + auto pemKeys = ECDSAHexToPem(keys); + ECDSASigner signer(keys.first, KeyFormat::HexaDecimalStrippedFormat); + ECDSAVerifier verifier(pemKeys.second, KeyFormat::PemFormat); + std::string data = "Hello world"; + auto sig = signer.sign(data); + ASSERT_TRUE(verifier.verify(data, sig)); +} + +TEST(cryptopp_utils, test_ecdsa_keys_pem_combined_b) { + auto keys = generateECDSAKeyPair(KeyFormat::HexaDecimalStrippedFormat); + auto pemKeys = ECDSAHexToPem(keys); + ECDSASigner signer(pemKeys.first, KeyFormat::PemFormat); + ECDSAVerifier verifier(keys.second, KeyFormat::HexaDecimalStrippedFormat); + std::string data = "Hello world"; + auto sig = signer.sign(data); + ASSERT_TRUE(verifier.verify(data, sig)); +} +} // namespace + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/util/test/digest_holder_test.cpp b/util/test/digest_holder_test.cpp index 76fd3987af..4728608bdb 100644 --- a/util/test/digest_holder_test.cpp +++ b/util/test/digest_holder_test.cpp @@ -15,7 +15,7 @@ #include "gtest/gtest.h" #include "hex_tools.h" #include "digest_holder.hpp" -#include "cryptopp_digest_creator.hpp" +#include "cryptopp/digest_creator.hpp" using concord::util::digest::DigestHolder; using concord::util::digest::CryptoppDigestCreator; diff --git a/util/test/openssl_digest_creator_test.cpp b/util/test/openssl_digest_creator_test.cpp index 36dc0e7774..459fa58de7 100644 --- a/util/test/openssl_digest_creator_test.cpp +++ b/util/test/openssl_digest_creator_test.cpp @@ -14,12 +14,11 @@ #include "gtest/gtest.h" #include "hex_tools.h" -#include "sha_hash.hpp" -#include "openssl_digest_creator.ipp" +#include "openssl/digest_creator.hpp" using concord::util::SHA2_256; using concord::util::SHA3_256; -using concord::util::digest::OpenSSLDigestCreator; +using concord::util::crypto::openssl::OpenSSLDigestCreator; using DigestGeneratorTest_SHA2_256 = OpenSSLDigestCreator; using DigestGeneratorTest_SHA3_256 = OpenSSLDigestCreator; diff --git a/util/test/openssl_digest_holder_test.cpp b/util/test/openssl_digest_holder_test.cpp new file mode 100644 index 0000000000..1efe4acdb2 --- /dev/null +++ b/util/test/openssl_digest_holder_test.cpp @@ -0,0 +1,253 @@ +// Concord +// +// Copyright (c) 2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 +// License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the subcomponent's license, as noted in the LICENSE +// file. +// + +#include "gtest/gtest.h" +#include "hex_tools.h" +#include "digest_holder.hpp" +#include "openssl/digest_creator.hpp" + +using concord::util::SHA2_256; +using concord::util::SHA3_256; +using concord::util::digest::DigestHolder; +using concord::util::crypto::openssl::OpenSSLDigestCreator; + +using Digest256 = DigestHolder>; +using Digest3_256 = DigestHolder>; + +// Hashes are generated via https://emn178.github.io/online-tools/sha256.html +struct SHA_Hashes { + std::string input; + std::string hash; +}; +SHA_Hashes sha256_hashes[] = {{"sha256", "5d5b09f6dcb2d53a5fffc60c4ac0d55fabdf556069d6631545f42aa6e3500f2e"}, + {"", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}, + {"vmware", "592cc302663c0021ffa92186bf3c1a579a97e5e01f8b28f766855e5b121f8bda"}, + {"5d5b09f6dcb2d53a5fffc60c4ac0d55fabdf556069d6631545f42aa6e3500f2e", "20a30eabfaa29aff866ce471dd7bc129cb3c368bc49409a499a1fbd5851b36cb"} + /* Digest of digest (sha256_hashes[0].input). Change the input type to Hex in online tool. To calculate digestOfDigest. */}; + +SHA_Hashes sha3_256_hashes[] = {{"sha3_256", "5ae36d2b4b37209703fb327119f63354c93b5a35a07e1397aad3285b37910fe9"}, + {"", "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"}, + {"vmware", "8c1f524205612f55c39b1f96ca6ebd07262b0b3fd3b25bc90d7b8694024524b9"}, + {"5ae36d2b4b37209703fb327119f63354c93b5a35a07e1397aad3285b37910fe9", "7a8bb5781327aa467e630d2a19f6f0a2fefe72b0e334322b70f70f9dab4c67b5"} + /* Digest of digest (sha3_256_hashes[0].input). Change the input type to Hex in online tool. To calculate digestOfDigest. */}; + +namespace { + +// SHA256 test cases. +TEST(openssl_digest_holder_test, test_constructors_sha256) { + { + Digest256 digest; + ASSERT_EQ(true, digest.isZero()); + } + { + unsigned char c = 'a'; + Digest256 digest(c); + ASSERT_EQ(false, digest.isZero()); + ASSERT_EQ(0, memcmp(digest.content(), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", DIGEST_SIZE)); + + digest.makeZero(); + ASSERT_EQ(true, digest.isZero()); + } + { + const char* cp = "VMware."; + Digest256 digest(cp); + ASSERT_EQ(false, digest.isZero()); + ASSERT_EQ(0, memcmp(digest.content(), "VMware.", strlen(cp))); + + digest.makeZero(); + ASSERT_EQ(true, digest.isZero()); + } + { + const char* cp = "This is a string whose length is greater than DIGEST_SIZE."; + Digest256 digest(cp); + ASSERT_EQ(false, digest.isZero()); + ASSERT_EQ(0, memcmp(digest.content(), "This is a string whose length is", DIGEST_SIZE)); + + digest.makeZero(); + ASSERT_EQ(true, digest.isZero()); + } + { + const char* cp = "VMware."; + Digest256 digest(cp); + ASSERT_EQ(false, digest.isZero()); + ASSERT_EQ(0, memcmp(digest.content(), "VMware.", strlen(cp))); + + Digest256 digest_1 = digest; // Copy constructor test. + ASSERT_EQ(false, digest_1.isZero()); + ASSERT_EQ(0, memcmp(digest_1.content(), "VMware.", strlen(cp))); + + digest_1.makeZero(); + ASSERT_EQ(true, digest_1.isZero()); + } + { + Digest256 digest(sha256_hashes[0].input.data(), sha256_hashes[0].input.size()); + ASSERT_EQ(false, digest.isZero()); + ASSERT_EQ(0, + memcmp(sha256_hashes[0].hash.data(), + concordUtils::bufferToHex(digest.get(), DIGEST_SIZE, false).data(), + DIGEST_SIZE)); + + std::string s1 = concordUtils::bufferToHex(digest.getForUpdate(), DIGEST_SIZE, false); + std::string s2 = digest.toString(); + + ASSERT_EQ(s1, s2); + } +} + +TEST(openssl_digest_holder_test, test_overloaded_operators_sha256) { + { + const char* cp = "VMware."; + Digest256 digest_1(cp); + Digest256 digest_2(cp); + + ASSERT_EQ(true, digest_1 == digest_2); + ASSERT_EQ(false, digest_1 != digest_2); + + ASSERT_EQ(true, digest_2 == digest_1); + ASSERT_EQ(false, digest_2 != digest_1); + } + { + const char* cp = "VMware."; + Digest256 digest_1(cp); + Digest256 digest_2('c'); + + ASSERT_EQ(false, digest_1 == digest_2); + ASSERT_EQ(true, digest_1 != digest_2); + } + { + const char* cp = "VMware."; + Digest256 digest_1(cp); + Digest256 digest_2; + digest_2 = digest_1; // Assignment copy operator. + + ASSERT_EQ(true, digest_1 == digest_2); + ASSERT_EQ(false, digest_1 != digest_2); + } +} + +TEST(openssl_digest_holder_test, test_digest_of_digest_sha256) { + Digest256 digest(sha256_hashes[0].input.data(), sha256_hashes[0].input.size()); + Digest256 digest_of_digest; + + digest.digestOfDigest(digest_of_digest); + + ASSERT_EQ(true, digest_of_digest.toString() == sha256_hashes[3].hash); +} + +// SHA3-256 test cases. +TEST(openssl_digest_holder_test, test_constructors_sha3_256) { + { + Digest3_256 digest; + ASSERT_EQ(true, digest.isZero()); + } + { + unsigned char c = 'a'; + Digest3_256 digest(c); + ASSERT_EQ(false, digest.isZero()); + ASSERT_EQ(0, memcmp(digest.content(), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", DIGEST_SIZE)); + + digest.makeZero(); + ASSERT_EQ(true, digest.isZero()); + } + { + const char* cp = "VMware."; + Digest3_256 digest(cp); + ASSERT_EQ(false, digest.isZero()); + ASSERT_EQ(0, memcmp(digest.content(), "VMware.", strlen(cp))); + + digest.makeZero(); + ASSERT_EQ(true, digest.isZero()); + } + { + const char* cp = "This is a string whose length is greater than DIGEST_SIZE."; + Digest3_256 digest(cp); + ASSERT_EQ(false, digest.isZero()); + ASSERT_EQ(0, memcmp(digest.content(), "This is a string whose length is", DIGEST_SIZE)); + + digest.makeZero(); + ASSERT_EQ(true, digest.isZero()); + } + { + const char* cp = "VMware."; + Digest3_256 digest(cp); + ASSERT_EQ(false, digest.isZero()); + ASSERT_EQ(0, memcmp(digest.content(), "VMware.", strlen(cp))); + + Digest3_256 digest_1 = digest; // Copy constructor test. + ASSERT_EQ(false, digest_1.isZero()); + ASSERT_EQ(0, memcmp(digest_1.content(), "VMware.", strlen(cp))); + + digest_1.makeZero(); + ASSERT_EQ(true, digest_1.isZero()); + } + { + Digest3_256 digest(sha3_256_hashes[0].input.data(), sha3_256_hashes[0].input.size()); + ASSERT_EQ(false, digest.isZero()); + ASSERT_EQ(0, + memcmp(sha3_256_hashes[0].hash.data(), + concordUtils::bufferToHex(digest.get(), DIGEST_SIZE, false).data(), + DIGEST_SIZE)); + + auto s1 = concordUtils::bufferToHex(digest.getForUpdate(), DIGEST_SIZE, false); + auto s2 = digest.toString(); + + ASSERT_EQ(s1, s2); + } +} + +TEST(openssl_digest_holder_test, test_overloaded_operators_sha3_256) { + { + const char* cp = "VMware."; + Digest3_256 digest_1(cp); + Digest3_256 digest_2(cp); + + ASSERT_EQ(true, digest_1 == digest_2); + ASSERT_EQ(false, digest_1 != digest_2); + + ASSERT_EQ(true, digest_2 == digest_1); + ASSERT_EQ(false, digest_2 != digest_1); + } + { + const char* cp = "VMware."; + Digest3_256 digest_1(cp); + Digest3_256 digest_2('c'); + + ASSERT_EQ(false, digest_1 == digest_2); + ASSERT_EQ(true, digest_1 != digest_2); + } + { + const char* cp = "VMware."; + Digest3_256 digest_1(cp); + Digest3_256 digest_2; + digest_2 = digest_1; // Assignment copy operator. + + ASSERT_EQ(true, digest_1 == digest_2); + ASSERT_EQ(false, digest_1 != digest_2); + } +} + +TEST(openssl_digest_holder_test, test_digest_of_digest_sha3_256) { + Digest3_256 digest(sha3_256_hashes[0].input.data(), sha3_256_hashes[0].input.size()); + Digest3_256 digest_of_digest; + + digest.digestOfDigest(digest_of_digest); + + ASSERT_EQ(true, digest_of_digest.toString() == sha3_256_hashes[3].hash); +} +} // namespace + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/util/test/openssl_utils_test.cpp b/util/test/openssl_utils_test.cpp new file mode 100644 index 0000000000..b760bd932a --- /dev/null +++ b/util/test/openssl_utils_test.cpp @@ -0,0 +1,194 @@ +// Concord +// +// Copyright (c) 2022 VMware, Inc. All Rights Reserved. +// +// This product is licensed to you under the Apache 2.0 license (the "License"). +// You may not use this product except in compliance with the Apache 2.0 +// License. +// +// This product may include a number of subcomponents with separate copyright +// notices and license terms. Your use of these subcomponents is subject to the +// terms and conditions of the subcomponent's license, as noted in the LICENSE +// file. +// + +#include "gtest/gtest.h" +#include "Logger.hpp" +#include "crypto/factory.hpp" +#include "crypto/openssl/EdDSA.hpp" +#include "crypto/openssl/EdDSASigner.hpp" +#include "crypto/openssl/EdDSAVerifier.hpp" +#include "crypto.hpp" + +namespace { +using concord::crypto::KeyFormat; +using concord::crypto::generateEdDSAKeyPair; +using concord::crypto::EdDSAHexToPem; +using concord::util::crypto::openssl::EdDSAPrivateKey; +using concord::util::crypto::openssl::EdDSAPublicKey; +using concord::util::crypto::openssl::EdDSAPrivateKeyByteSize; +using concord::util::crypto::openssl::deserializeKey; + +using TestTxnSigner = concord::crypto::openssl::EdDSASigner; +using TestTxnVerifier = concord::crypto::openssl::EdDSAVerifier; + +TEST(openssl_utils, check_eddsa_keys_hex_format_length) { + const auto hexKeys = generateEdDSAKeyPair(KeyFormat::HexaDecimalStrippedFormat); + ASSERT_EQ(hexKeys.first.size(), EdDSAPrivateKeyByteSize * 2); + ASSERT_EQ(hexKeys.second.size(), EdDSAPrivateKeyByteSize * 2); +} + +TEST(openssl_utils, generate_eddsa_keys_hex_format) { + ASSERT_NO_THROW(generateEdDSAKeyPair()); + const auto hexKeys1 = generateEdDSAKeyPair(); + LOG_INFO(GL, hexKeys1.first << " | " << hexKeys1.second); + + ASSERT_NO_THROW(generateEdDSAKeyPair(KeyFormat::HexaDecimalStrippedFormat)); + const auto hexKeys2 = generateEdDSAKeyPair(KeyFormat::HexaDecimalStrippedFormat); + LOG_INFO(GL, hexKeys2.first << " | " << hexKeys2.second); +} + +TEST(openssl_utils, generate_eddsa_keys_pem_format) { + ASSERT_NO_THROW(generateEdDSAKeyPair()); + ASSERT_NO_THROW(generateEdDSAKeyPair(KeyFormat::PemFormat)); + const auto pemKeys = generateEdDSAKeyPair(KeyFormat::PemFormat); + LOG_INFO(GL, pemKeys.first << " | " << pemKeys.second); +} + +TEST(openssl_utils, test_eddsa_keys_hex_ok) { + auto hexKeys = generateEdDSAKeyPair(); + + const auto signingKey = deserializeKey(hexKeys.first); + const auto verificationKey = deserializeKey(hexKeys.second); + + TestTxnSigner signer(signingKey.getBytes()); + TestTxnVerifier verifier(verificationKey.getBytes()); + + const std::string data = "Hello VMworld"; + auto sig = signer.sign(data); + ASSERT_TRUE(verifier.verify(data, sig)); +} + +TEST(openssl_utils, test_eddsa_keys_hex_nok) { + const auto hexKeys = generateEdDSAKeyPair(); + + const auto signingKey = deserializeKey(hexKeys.first); + const auto verificationKey = deserializeKey(hexKeys.second); + + TestTxnSigner signer(signingKey.getBytes()); + TestTxnVerifier verifier(verificationKey.getBytes()); + + const std::string data = "Hello VMworld"; + auto sig = signer.sign(data); + + // Corrupt data. + ++sig[0]; + + ASSERT_FALSE(verifier.verify(data, sig)); +} + +TEST(openssl_utils, test_eddsa_keys_pem_ok) { + const auto pemKeys = generateEdDSAKeyPair(KeyFormat::PemFormat); + + const auto signingKey = deserializeKey(pemKeys.first, KeyFormat::PemFormat); + const auto verificationKey = deserializeKey(pemKeys.second, KeyFormat::PemFormat); + + TestTxnSigner signer(signingKey.getBytes()); + TestTxnVerifier verifier(verificationKey.getBytes()); + + const std::string data = "Hello VMworld"; + auto sig = signer.sign(data); + ASSERT_TRUE(verifier.verify(data, sig)); +} + +TEST(openssl_utils, test_eddsa_keys_pem_nok) { + const auto pemKeys = generateEdDSAKeyPair(KeyFormat::PemFormat); + + const auto signingKey = deserializeKey(pemKeys.first, KeyFormat::PemFormat); + const auto verificationKey = deserializeKey(pemKeys.second, KeyFormat::PemFormat); + + TestTxnSigner signer(signingKey.getBytes()); + TestTxnVerifier verifier(verificationKey.getBytes()); + + const std::string data = "Hello VMworld"; + auto sig = signer.sign(data); + + // Corrupt data. + ++sig[0]; + + ASSERT_FALSE(verifier.verify(data, sig)); +} + +TEST(openssl_utils, test_eddsa_keys_combined_a_ok) { + const auto hexKeys = generateEdDSAKeyPair(); + const auto pemKeys = EdDSAHexToPem(hexKeys); + + const auto signingKey = deserializeKey(hexKeys.first); + const auto verificationKey = deserializeKey(pemKeys.second, KeyFormat::PemFormat); + + TestTxnSigner signer(signingKey.getBytes()); + TestTxnVerifier verifier(verificationKey.getBytes()); + + const std::string data = "Hello VMworld"; + auto sig = signer.sign(data); + ASSERT_TRUE(verifier.verify(data, sig)); +} + +TEST(openssl_utils, test_eddsa_keys_combined_a_nok) { + const auto hexKeys = generateEdDSAKeyPair(); + const auto pemKeys = EdDSAHexToPem(hexKeys); + + const auto signingKey = deserializeKey(hexKeys.first); + const auto verificationKey = deserializeKey(pemKeys.second, KeyFormat::PemFormat); + + TestTxnSigner signer(signingKey.getBytes()); + TestTxnVerifier verifier(verificationKey.getBytes()); + + const std::string data = "Hello VMworld"; + auto sig = signer.sign(data); + + // Corrupt data. + ++sig[0]; + + ASSERT_FALSE(verifier.verify(data, sig)); +} + +TEST(openssl_utils, test_eddsa_keys_combined_b_ok) { + const auto hexKeys = generateEdDSAKeyPair(); + const auto pemKeys = EdDSAHexToPem(hexKeys); + + const auto signingKey = deserializeKey(pemKeys.first, KeyFormat::PemFormat); + const auto verificationKey = deserializeKey(hexKeys.second); + + TestTxnSigner signer(signingKey.getBytes()); + TestTxnVerifier verifier(verificationKey.getBytes()); + + const std::string data = "Hello VMworld"; + auto sig = signer.sign(data); + ASSERT_TRUE(verifier.verify(data, sig)); +} + +TEST(openssl_utils, test_eddsa_keys_combined_b_nok) { + const auto hexKeys = generateEdDSAKeyPair(); + const auto pemKeys = EdDSAHexToPem(hexKeys); + + const auto signingKey = deserializeKey(pemKeys.first, KeyFormat::PemFormat); + const auto verificationKey = deserializeKey(hexKeys.second); + + TestTxnSigner signer(signingKey.getBytes()); + TestTxnVerifier verifier(verificationKey.getBytes()); + + std::string data = "Hello VMworld"; + auto sig = signer.sign(data); + + // Corrupt data. + ++sig[0]; + + ASSERT_FALSE(verifier.verify(data, sig)); +} +} // namespace + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +}