diff --git a/include/libp2p/storage/sqlite.hpp b/include/libp2p/storage/sqlite.hpp index c77c65ee3..50c856db2 100644 --- a/include/libp2p/storage/sqlite.hpp +++ b/include/libp2p/storage/sqlite.hpp @@ -36,10 +36,10 @@ namespace libp2p::storage { } /// Reads extended sqlite3 error code - int getErrorCode(); + int getErrorCode() const; /// Returns human-readable representation of an error - std::string getErrorMessage(); + std::string getErrorMessage() const; /** * Store prepared statement @@ -61,6 +61,7 @@ namespace libp2p::storage { * @param st_handle - statement identifier * @param args - command arguments * @return number of rows affected, -1 in case of error + * @throws std::invalid_argument if statement handle is invalid */ template inline int execCommand(StatementHandle st_handle, const Args &...args) { @@ -69,11 +70,14 @@ namespace libp2p::storage { bindArgs(st, args...); st.execute(); return countChanges(); - } catch (const std::runtime_error &e) { + } catch (const std::invalid_argument &e) { // getStatement can receive invalid handle - log_->error(e.what()); + log_->error("Invalid statement handle: {}", e.what()); + throw; // Re-throw invalid_argument as it's a programming error + } catch (const std::runtime_error &e) { + log_->error("Runtime error during command execution: {}", e.what()); } catch (...) { - log_->error(getErrorMessage()); + log_->error("Unknown error during command execution: {}", getErrorMessage()); } return -1; } @@ -86,6 +90,7 @@ namespace libp2p::storage { * @param sink - query response consumer * @param args - query arguments * @return true when query was successfully executed, otherwise - false + * @throws std::invalid_argument if statement handle is invalid */ template inline bool execQuery(StatementHandle st_handle, @@ -96,11 +101,14 @@ namespace libp2p::storage { bindArgs(st, args...); st >> sink; return true; - } catch (const std::runtime_error &e) { + } catch (const std::invalid_argument &e) { // getStatement can receive invalid handle - log_->error(e.what()); + log_->error("Invalid statement handle: {}", e.what()); + throw; // Re-throw invalid_argument as it's a programming error + } catch (const std::runtime_error &e) { + log_->error("Runtime error during query execution: {}", e.what()); } catch (...) { - log_->error(getErrorMessage()); + log_->error("Unknown error during query execution: {}", getErrorMessage()); } return false; } @@ -119,7 +127,13 @@ namespace libp2p::storage { } /// Returns the number of rows modified - int countChanges(); + int countChanges() const; + + /// Returns the database file path + const std::string &getDatabaseFile() const; + + /// Returns the number of prepared statements + size_t getStatementCount() const; ::sqlite::database db_; std::string db_file_; diff --git a/src/crypto/key_validator/key_validator_impl.cpp b/src/crypto/key_validator/key_validator_impl.cpp index 429057f6c..55fd36f83 100644 --- a/src/crypto/key_validator/key_validator_impl.cpp +++ b/src/crypto/key_validator/key_validator_impl.cpp @@ -170,15 +170,57 @@ namespace libp2p::crypto::validator { outcome::result KeyValidatorImpl::validateEcdsa( const PrivateKey &key) const { - // TODO(xDimon): Check if it possible to validate ECDSA key by some way. - // issue: https://github.com/libp2p/cpp-libp2p/issues/103 + // Basic ECDSA private key validation + // ECDSA private keys are typically 32 bytes for P-256, 48 bytes for P-384, 66 bytes for P-521 + if (key.data.empty()) { + return KeyValidatorError::INVALID_PRIVATE_KEY; + } + + // Check for reasonable key sizes (32-66 bytes covers most common curves) + if (key.data.size() < 32 || key.data.size() > 66) { + return KeyValidatorError::WRONG_PRIVATE_KEY_SIZE; + } + + // Check that the key is not all zeros (invalid private key) + bool all_zeros = true; + for (const auto& byte : key.data) { + if (byte != 0) { + all_zeros = false; + break; + } + } + if (all_zeros) { + return KeyValidatorError::INVALID_PRIVATE_KEY; + } + return outcome::success(); } outcome::result KeyValidatorImpl::validateEcdsa( const PublicKey &key) const { - // TODO(xDimon): Check if it possible to validate ECDSA key by some way. - // issue: https://github.com/libp2p/cpp-libp2p/issues/103 + // Basic ECDSA public key validation + if (key.data.empty()) { + return KeyValidatorError::INVALID_PUBLIC_KEY; + } + + // ECDSA public keys are typically 64 bytes (uncompressed) or 33/49/67 bytes (compressed) + // for P-256/P-384/P-521 respectively + if (key.data.size() < 33 || key.data.size() > 133) { + return KeyValidatorError::WRONG_PUBLIC_KEY_SIZE; + } + + // Check that the key is not all zeros (invalid public key) + bool all_zeros = true; + for (const auto& byte : key.data) { + if (byte != 0) { + all_zeros = false; + break; + } + } + if (all_zeros) { + return KeyValidatorError::INVALID_PUBLIC_KEY; + } + return outcome::success(); } diff --git a/src/storage/sqlite.cpp b/src/storage/sqlite.cpp index 33f47cedf..286dfbaca 100644 --- a/src/storage/sqlite.cpp +++ b/src/storage/sqlite.cpp @@ -22,12 +22,12 @@ namespace libp2p::storage { } } - int SQLite::getErrorCode() { + int SQLite::getErrorCode() const { return sqlite3_extended_errcode(db_.connection().get()); } - std::string SQLite::getErrorMessage() { - int ec{getErrorCode()}; + std::string SQLite::getErrorMessage() const { + const int ec{getErrorCode()}; return (0 == ec) ? std::string() : std::string(sqlite3_errstr(ec)) + ": " + sqlite3_errmsg(db_.connection().get()); @@ -42,12 +42,23 @@ namespace libp2p::storage { SQLite::database_binder &SQLite::getStatement( SQLite::StatementHandle handle) { if (handle >= statements_.size()) { - throw std::runtime_error("SQLite: statement does not exist"); + throw std::invalid_argument("SQLite: statement handle " + + std::to_string(handle) + + " does not exist (max: " + + std::to_string(statements_.size() - 1) + ")"); } return statements_[handle]; } - int SQLite::countChanges() { + int SQLite::countChanges() const { return sqlite3_changes(db_.connection().get()); } + + const std::string &SQLite::getDatabaseFile() const { + return db_file_; + } + + size_t SQLite::getStatementCount() const { + return statements_.size(); + } } // namespace libp2p::storage