Skip to content

Commit

Permalink
WIP: Config flag for signing/verification algorithm.
Browse files Browse the repository at this point in the history
  • Loading branch information
Pankaj committed Jul 25, 2022
1 parent b2ea5fe commit 3d9a254
Show file tree
Hide file tree
Showing 20 changed files with 220 additions and 192 deletions.
11 changes: 11 additions & 0 deletions bftengine/include/bftengine/ReplicaConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <chrono>
#include "string.hpp"
#include "kvstream.h"
#include "sign_verify_utils.hpp"

#include "Serializable.h"

Expand Down Expand Up @@ -281,6 +282,16 @@ class ReplicaConfig : public concord::serialize::SerializableFactory<ReplicaConf
"the concord-ctl script");
CONFIG_PARAM(kvBlockchainVersion, std::uint32_t, 1u, "Default version of KV blockchain for this replica");

CONFIG_PARAM(replicaMsgSigningAlgo,
concord::crypto::signature::SIGN_VERIFY_ALGO,
concord::crypto::signature::SIGN_VERIFY_ALGO::EDDSA,
"A flag to specify the replica message signing algorithm. It is defaulted to use EDDSA algo.");

CONFIG_PARAM(operatorMsgSigningAlgo,
concord::crypto::signature::SIGN_VERIFY_ALGO,
concord::crypto::signature::SIGN_VERIFY_ALGO::EDDSA,
"A flag to specify the operator message signing algorithm. It is defaulted to use EDDSA algo.");

// Parameter to enable/disable waiting for transaction data to be persisted.
// Not predefined configuration parameters
// Example of usage:
Expand Down
20 changes: 9 additions & 11 deletions bftengine/src/bftengine/KeyExchangeManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,15 @@
#include "concord.cmf.hpp"
#include "communication/StateControl.hpp"
#include "openssl_utils.hpp"
#include "sign_verify_utils.hpp"

namespace bftEngine::impl {

using concord::util::crypto::KeyFormat;
using concord::crypto::openssl::CertificateUtils;

#ifdef USE_CRYPTOPP_RSA
using concord::crypto::signature::SIGN_VERIFY_ALGO;
using concord::crypto::cryptopp::Crypto;
#elif USE_EDDSA_SINGLE_SIGN
using concord::crypto::openssl::OpenSSLCryptoImpl;
#endif

KeyExchangeManager::KeyExchangeManager(InitData* id)
: repID_{ReplicaConfig::instance().getreplicaId()},
Expand Down Expand Up @@ -164,13 +162,13 @@ void KeyExchangeManager::exchangeTlsKeys(const std::string& type, const SeqNum&
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";

#ifdef USE_CRYPTOPP_RSA
std::string prev_key_pem =
Crypto::instance().RsaHexToPem(std::make_pair(SigManager::instance()->getSelfPrivKey(), "")).first;
#elif USE_EDDSA_SINGLE_SIGN
std::string prev_key_pem =
OpenSSLCryptoImpl::instance().EdDSAHexToPem(std::make_pair(SigManager::instance()->getSelfPrivKey(), "")).first;
#endif
std::string prev_key_pem;
if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) {
prev_key_pem = Crypto::instance().RsaHexToPem(std::make_pair(SigManager::instance()->getSelfPrivKey(), "")).first;
} else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) {
prev_key_pem =
OpenSSLCryptoImpl::instance().EdDSAHexToPem(std::make_pair(SigManager::instance()->getSelfPrivKey(), "")).first;
}

auto cert = CertificateUtils::generateSelfSignedCert(cert_path, keys.second, prev_key_pem);
// Now that we have generated new key pair and certificate, lets do the actual exchange on this replica
Expand Down
10 changes: 7 additions & 3 deletions bftengine/src/bftengine/SigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ SigManager::SigManager(PrincipalId myId,

ConcordAssert(publicKeysMapping.size() >= numPublickeys);
if (!mySigPrivateKey.first.empty()) {
mySigner_ = SignerFactory::getReplicaSigner(mySigPrivateKey.first, mySigPrivateKey.second);
mySigner_ = SignerFactory::getReplicaSigner(
mySigPrivateKey.first, ReplicaConfig::instance().replicaMsgSigningAlgo, mySigPrivateKey.second);
}
for (const auto& p : publicKeysMapping) {
ConcordAssert(verifiers_.count(p.first) == 0);
Expand All @@ -151,7 +152,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::shared_ptr<IVerifier>(VerifierFactory::getReplicaVerifier(key, format));
verifiers_[p.first] = std::shared_ptr<IVerifier>(
VerifierFactory::getReplicaVerifier(key, ReplicaConfig::instance().replicaMsgSigningAlgo, format));
publicKeyIndexToVerifier[p.second] = verifiers_[p.first];
} else {
verifiers_[p.first] = iter->second;
Expand Down Expand Up @@ -258,7 +260,9 @@ void SigManager::setClientPublicKey(const std::string& key, PrincipalId id, KeyF
if (replicasInfo_.isIdOfExternalClient(id) || replicasInfo_.isIdOfClientService(id)) {
try {
std::unique_lock lock(mutex_);
verifiers_.insert_or_assign(id, std::shared_ptr<IVerifier>(VerifierFactory::getReplicaVerifier(key, format)));
verifiers_.insert_or_assign(id,
std::shared_ptr<IVerifier>(VerifierFactory::getReplicaVerifier(
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;
Expand Down
24 changes: 16 additions & 8 deletions bftengine/tests/SigManager/SigManager_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ using concord::crypto::IVerifier;
using concord::crypto::signature::SignerFactory;
using concord::crypto::signature::VerifierFactory;
using concord::crypto::openssl::OpenSSLCryptoImpl;
using bftEngine::ReplicaConfig;

#ifdef USE_CRYPTOPP_RSA
constexpr char ALGO_NAME[] = "rsa";
Expand Down Expand Up @@ -88,8 +89,9 @@ TEST(SignerAndVerifierTest, LoadSignVerifyFromHexKeyPair) {
const auto keyPair = OpenSSLCryptoImpl::instance().generateEdDSAKeyPair();
generateRandomData(data, RANDOM_DATA_SIZE);

const auto signer_ = SignerFactory::getReplicaSigner(keyPair.first);
const auto verifier_ = VerifierFactory::getReplicaVerifier(keyPair.second);
const auto signer_ = SignerFactory::getReplicaSigner(keyPair.first, ReplicaConfig::instance().replicaMsgSigningAlgo);
const auto verifier_ =
VerifierFactory::getReplicaVerifier(keyPair.second, ReplicaConfig::instance().replicaMsgSigningAlgo);

// sign with RSASigner/EdDSASigner
std::string sig;
Expand Down Expand Up @@ -129,8 +131,10 @@ TEST(SignerAndVerifierTest, LoadSignVerifyFromPemfiles) {
readFile(privateKeyFullPath, privKey);
readFile(publicKeyFullPath, pubkey);

const auto signer_ = SignerFactory::getReplicaSigner(privKey, KeyFormat::PemFormat);
const auto verifier_ = VerifierFactory::getReplicaVerifier(pubkey, KeyFormat::PemFormat);
const auto signer_ =
SignerFactory::getReplicaSigner(privKey, ReplicaConfig::instance().replicaMsgSigningAlgo, KeyFormat::PemFormat);
const auto verifier_ = VerifierFactory::getReplicaVerifier(
pubkey, ReplicaConfig::instance().replicaMsgSigningAlgo, KeyFormat::PemFormat);

// sign with RSASigner/EdDSASigner
size_t expectedSignerSigLen = signer_->signatureLength();
Expand Down Expand Up @@ -177,7 +181,8 @@ TEST(SigManagerTest, ReplicasOnlyCheckVerify) {
myPrivKey = privKey;
continue;
}
signers[pid] = SignerFactory::getReplicaSigner(privKey, KeyFormat::PemFormat);
signers[pid] =
SignerFactory::getReplicaSigner(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));
Expand Down Expand Up @@ -240,7 +245,8 @@ TEST(SigManagerTest, ReplicasOnlyCheckSign) {
string pubKeyFullPath({string(KEYS_BASE_PATH) + string("/") + to_string(1) + string("/") + PUB_KEY_NAME});
readFile(pubKeyFullPath, pubKey);

verifier = VerifierFactory::getReplicaVerifier(pubKey, KeyFormat::PemFormat);
verifier = VerifierFactory::getReplicaVerifier(
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) {
Expand Down Expand Up @@ -305,7 +311,8 @@ TEST(SigManagerTest, ReplicasAndClientsCheckVerify) {
myPrivKey = privKey;
continue;
}
signers[signerIndex] = SignerFactory::getReplicaSigner(privKey, KeyFormat::PemFormat);
signers[signerIndex] =
SignerFactory::getReplicaSigner(privKey, ReplicaConfig::instance().replicaMsgSigningAlgo, KeyFormat::PemFormat);

string pubKeyFullPath({string(KEYS_BASE_PATH) + string("/") + to_string(i) + string("/") + PUB_KEY_NAME});
readFile(pubKeyFullPath, pubKey);
Expand All @@ -320,7 +327,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] = SignerFactory::getReplicaSigner(privKey, KeyFormat::PemFormat);
signers[signerIndex] =
SignerFactory::getReplicaSigner(privKey, ReplicaConfig::instance().replicaMsgSigningAlgo, KeyFormat::PemFormat);
string pubKeyFullPath({string(KEYS_BASE_PATH) + string("/") + to_string(i) + string("/") + PUB_KEY_NAME});
set<PrincipalId> principalIds;
for (size_t j{0}; j < numBftClientsInParticipantNodes; ++j) {
Expand Down
56 changes: 29 additions & 27 deletions bftengine/tests/clientsManager/ClientsManager_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,24 +43,16 @@ using std::this_thread::sleep_for;
using std::unique_ptr;
using std::vector;

#ifdef USE_CRYPTOPP_RSA
using concord::crypto::cryptopp::Crypto;
using concord::crypto::cryptopp::RSA_SIGNATURE_LENGTH;
#elif USE_EDDSA_SINGLE_SIGN
using concord::crypto::openssl::OpenSSLCryptoImpl;
#endif
using concord::crypto::signature::SIGN_VERIFY_ALGO;

// Testing values to be used for certain Concord-BFT configuration that ClientsManager and/or its dependencies may
// reference.
const ReplicaId kReplicaIdForTesting = 0;
const KeyFormat kKeyFormatForTesting = KeyFormat::HexaDecimalStrippedFormat;

#ifdef USE_CRYPTOPP_RSA
const SigManager::Key kReplicaPrivateKeyForTesting(Crypto::instance().generateRsaKeyPair(RSA_SIGNATURE_LENGTH).first);
#elif USE_EDDSA_SINGLE_SIGN
const SigManager::Key kReplicaPrivateKeyForTesting(OpenSSLCryptoImpl::instance().generateEdDSAKeyPair().first);
#endif

const set<pair<PrincipalId, const string>> kPublicKeysOfReplicasForTesting{};
const set<pair<const string, set<uint16_t>>> kInitialPublicKeysOfClientsForTesting;
unique_ptr<ReplicasInfo> sigManagerReplicasInfoForTesting;
Expand Down Expand Up @@ -155,6 +147,12 @@ static void setMockReservedPages(shared_ptr<ReservedPagesMock<ClientsManager>>&
}

static void resetSigManager() {
SigManager::Key kReplicaPrivateKeyForTesting;
if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) {
kReplicaPrivateKeyForTesting = Crypto::instance().generateRsaKeyPair(RSA_SIGNATURE_LENGTH).first;
} else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) {
kReplicaPrivateKeyForTesting = OpenSSLCryptoImpl::instance().generateEdDSAKeyPair().first;
}
sig_manager_for_key_exchange_manager.reset(SigManager::init(kReplicaIdForTesting,
kReplicaPrivateKeyForTesting,
kPublicKeysOfReplicasForTesting,
Expand Down Expand Up @@ -235,7 +233,8 @@ static bool verifyClientPublicKeyLoadedToKEM(NodeIdType client_id, const pair<st
if (!(SigManager::instance()->hasVerifier(client_id))) {
return false;
}
const auto signer = SignerFactory::getReplicaSigner(expected_key.first, kKeyFormatForTesting);
const auto signer = SignerFactory::getReplicaSigner(
expected_key.first, ReplicaConfig::instance().replicaMsgSigningAlgo, kKeyFormatForTesting);
string signature = signer->sign(kArbitraryMessageForTestingKeyAgreement);
return SigManager::instance()->verifySig(client_id,
kArbitraryMessageForTestingKeyAgreement.data(),
Expand Down Expand Up @@ -322,11 +321,11 @@ TEST(ClientsManager, loadInfoFromReservedPagesLoadsCorrectInfo) {

map<NodeIdType, pair<string, string>> client_keys;

#ifdef USE_CRYPTOPP_RSA
client_keys[2] = Crypto::instance().generateRsaKeyPair(RSA_SIGNATURE_LENGTH);
#elif USE_EDDSA_SINGLE_SIGN
client_keys[2] = OpenSSLCryptoImpl::instance().generateEdDSAKeyPair();
#endif
if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) {
client_keys[2] = Crypto::instance().generateRsaKeyPair(RSA_SIGNATURE_LENGTH);
} else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) {
client_keys[2] = OpenSSLCryptoImpl::instance().generateEdDSAKeyPair();
}

map<NodeIdType, pair<ReqId, string>> client_replies;
client_replies[2] = {9, "reply 9 to client 2"};
Expand Down Expand Up @@ -444,11 +443,12 @@ TEST(ClientsManager, loadInfoFromReservedPagesHandlesNoInfoAvailable) {
}

TEST(ClientsManager, loadInfoFromReservedPagesHandlesSingleClientClientsManager) {
#ifdef USE_CRYPTOPP_RSA
pair<string, string> client_key_pair = Crypto::instance().generateRsaKeyPair(RSA_SIGNATURE_LENGTH);
#elif USE_EDDSA_SINGLE_SIGN
pair<string, string> client_key_pair = OpenSSLCryptoImpl::instance().generateEdDSAKeyPair();
#endif
pair<string, string> client_key_pair;
if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) {
client_key_pair = Crypto::instance().generateRsaKeyPair(RSA_SIGNATURE_LENGTH);
} else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) {
client_key_pair = OpenSSLCryptoImpl::instance().generateEdDSAKeyPair();
}

string reply_message = "reply 1 to client 2";

Expand Down Expand Up @@ -1326,13 +1326,15 @@ TEST(ClientsManager, setClientPublicKey) {
resetMockReservedPages();
map<NodeIdType, pair<string, string>> client_keys;

#ifdef USE_CRYPTOPP_RSA
pair<string, string> client_2_key = Crypto::instance().generateRsaKeyPair(RSA_SIGNATURE_LENGTH);
pair<string, string> client_7_key = Crypto::instance().generateRsaKeyPair(RSA_SIGNATURE_LENGTH);
#elif USE_EDDSA_SINGLE_SIGN
pair<string, string> client_2_key = OpenSSLCryptoImpl::instance().generateEdDSAKeyPair();
pair<string, string> client_7_key = OpenSSLCryptoImpl::instance().generateEdDSAKeyPair();
#endif
pair<string, string> client_2_key;
pair<string, string> client_7_key;
if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) {
client_2_key = Crypto::instance().generateRsaKeyPair(RSA_SIGNATURE_LENGTH);
client_7_key = Crypto::instance().generateRsaKeyPair(RSA_SIGNATURE_LENGTH);
} else if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) {
client_2_key = OpenSSLCryptoImpl::instance().generateEdDSAKeyPair();
client_7_key = OpenSSLCryptoImpl::instance().generateEdDSAKeyPair();
}

unique_ptr<ClientsManager> cm(new ClientsManager({}, {4, 5, 7}, {}, {}, metrics));
cm->setClientPublicKey(7, client_7_key.second, kKeyFormatForTesting);
Expand Down
5 changes: 4 additions & 1 deletion client/bftclient/src/bft_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@
#include "secrets_manager_plain.h"
#include "communication/StateControl.hpp"
#include "sign_verify_utils.hpp"
#include "ReplicaConfig.hpp"

using namespace concord::diagnostics;
using namespace concord::secretsmanager;
using namespace bftEngine;
using namespace bftEngine::impl;
using concord::util::crypto::KeyFormat;
using concord::crypto::signature::SignerFactory;
using bftEngine::ReplicaConfig;

namespace bft::client {

Expand Down Expand Up @@ -61,7 +63,8 @@ Client::Client(SharedCommPtr comm, const ClientConfig& config, std::shared_ptr<c
if (!key_plaintext) {
throw InvalidPrivateKeyException(file_path, config.secrets_manager_config != std::nullopt);
}
transaction_signer_ = SignerFactory::getReplicaSigner(key_plaintext.value(), KeyFormat::PemFormat);
transaction_signer_ = SignerFactory::getReplicaSigner(
key_plaintext.value(), ReplicaConfig::instance().replicaMsgSigningAlgo, KeyFormat::PemFormat);
}
communication_->setReceiver(config_.id.val, &receiver_);
communication_->start();
Expand Down
5 changes: 4 additions & 1 deletion client/bftclient/test/bft_client_api_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "msg_receiver.h"
#include "sign_verify_utils.hpp"
#include "Logger.hpp"
#include "ReplicaConfig.hpp"

using namespace std;
using namespace bft::client;
Expand All @@ -45,6 +46,7 @@ using namespace concord::secretsmanager;
using concord::util::crypto::KeyFormat;
using concord::crypto::signature::VerifierFactory;
using namespace CryptoPP;
using bftEngine::ReplicaConfig;

using ReplicaId_t = bft::client::ReplicaId;

Expand Down Expand Up @@ -187,7 +189,8 @@ TEST_P(ClientApiTestParametrizedFixture, print_received_messages_and_timeout) {
stream << file.rdbuf();
auto pub_key_str = stream.str();

transaction_verifier_ = VerifierFactory::getReplicaVerifier(pub_key_str, KeyFormat::PemFormat);
transaction_verifier_ = VerifierFactory::getReplicaVerifier(
pub_key_str, ReplicaConfig::instance().replicaMsgSigningAlgo, KeyFormat::PemFormat);
}
unique_ptr<FakeCommunication> comm;
if (sign_transaction) {
Expand Down
24 changes: 13 additions & 11 deletions client/reconfiguration/src/default_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@ namespace fs = std::experimental::filesystem;

namespace concord::client::reconfiguration::handlers {

#ifdef USE_CRYPTOPP_RSA
using bftEngine::ReplicaConfig;
using concord::crypto::signature::SIGN_VERIFY_ALGO;
using concord::crypto::cryptopp::Crypto;
#elif USE_EDDSA_SINGLE_SIGN
using concord::crypto::openssl::OpenSSLCryptoImpl;
using concord::crypto::openssl::CertificateUtils;
#endif

template <typename T>
bool validateInputState(const State& state, std::optional<uint64_t> init_block = std::nullopt) {
Expand Down Expand Up @@ -157,14 +156,17 @@ 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
#ifdef USE_CRYPTOPP_RSA
auto hex_keys = Crypto::instance().generateRsaKeyPair(concord::crypto::cryptopp::RSA_SIGNATURE_LENGTH);
auto pem_keys = Crypto::instance().RsaHexToPem(hex_keys);
#elif USE_EDDSA_SINGLE_SIGN
auto hex_keys = OpenSSLCryptoImpl::instance().generateEdDSAKeyPair();
auto pem_keys = OpenSSLCryptoImpl::instance().EdDSAHexToPem(hex_keys);
#endif
// Generate new key pair
std::pair<std::string, std::string> hex_keys;
std::pair<std::string, std::string> pem_keys;
if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::RSA) {
hex_keys = Crypto::instance().generateRsaKeyPair(concord::crypto::cryptopp::RSA_SIGNATURE_LENGTH);
pem_keys = Crypto::instance().RsaHexToPem(hex_keys);
}
if (ReplicaConfig::instance().replicaMsgSigningAlgo == SIGN_VERIFY_ALGO::EDDSA) {
hex_keys = OpenSSLCryptoImpl::instance().generateEdDSAKeyPair();
pem_keys = OpenSSLCryptoImpl::instance().EdDSAHexToPem(hex_keys);
}

LOG_INFO(getLogger(), "Generated pem keys:" << KVLOG(pem_keys.first, pem_keys.second));

Expand Down
Loading

0 comments on commit 3d9a254

Please sign in to comment.