wallet_api: expose signed message verification details
What changed, and why it matters
This commit adds a new wallet API function that exposes more details when verifying a signed message, such as which key was used and which signature version was detected. It does not change existing behavior; the old simple true/false check still works exactly as before. There is no indication this fixes a security bug or introduces a vulnerability.
No security action required; treat as normal feature/API improvement. Reviewers may optionally verify that the new API returns sensible defaults and does not leak sensitive data beyond what wallet2 already exposes internally.
Security signals we found
No security-relevant signal: pure API enhancement exposing previously internal verification metadata
Existing verifySignedMessage() behavior preserved by returning only the valid flag
No changes to cryptographic verification implementation
Evidence from the diff
The patch refactors WalletImpl::verifySignedMessage() to call a new verifySignedMessageWithDetails() method and return only the .valid field. It adds a public MessageSignatureResult struct and MessageSignatureType enum to wallet2_api.h, and updates wallet2.h’s internal message_signature_result_t to use default member initializers plus a new sign_with_invalid_key sentinel. The change is purely additive API surface; the underlying verification logic in wallet2::verify() is not modified.
Changed components
src/wallet/api/wallet.cppsrc/wallet/api/wallet.hsrc/wallet/api/wallet2_api.hsrc/wallet/wallet2.hInspect captured patch +39 / −4
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 07e09dd..2c31920 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -2262,13 +2262,26 @@ std::string WalletImpl::signMessage(const std::string &message, const std::strin
}
bool WalletImpl::verifySignedMessage(const std::string &message, const std::string &address, const std::string &signature) const
+{
+ return verifySignedMessageWithDetails(message, address, signature).valid;
+}
+
+Wallet::MessageSignatureResult WalletImpl::verifySignedMessageWithDetails(const std::string &message, const std::string &address, const std::string &signature) const
{
cryptonote::address_parse_info info;
if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address))
- return false;
+ return {};
- return m_wallet->verify(message, info.address, signature).valid;
+ const tools::wallet2::message_signature_result_t result = m_wallet->verify(message, info.address, signature);
+ MessageSignatureType type = MessageSignatureType_Invalid;
+ switch (result.type)
+ {
+ case tools::wallet2::sign_with_spend_key: type = MessageSignatureType_Spend; break;
+ case tools::wallet2::sign_with_view_key: type = MessageSignatureType_View; break;
+ default: break;
+ }
+ return {result.valid, result.version, result.old, type};
}
std::string WalletImpl::signMultisigParticipant(const std::string &message) const
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index 931f31d..30659cd 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -211,6 +211,7 @@ public:
virtual bool checkReserveProof(const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &total, uint64_t &spent) const override;
virtual std::string signMessage(const std::string &message, const std::string &address) override;
virtual bool verifySignedMessage(const std::string &message, const std::string &address, const std::string &signature) const override;
+ virtual MessageSignatureResult verifySignedMessageWithDetails(const std::string &message, const std::string &address, const std::string &signature) const override;
virtual std::string signMultisigParticipant(const std::string &message) const override;
virtual bool verifyMessageWithPublicKey(const std::string &message, const std::string &publicKey, const std::string &signature) const override;
virtual void startRefresh() override;
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index a8c1e8d..de13e55 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -445,6 +445,19 @@ struct Wallet
BackgroundSync_CustomPassword = 2
};
+ enum MessageSignatureType {
+ MessageSignatureType_Invalid = 0,
+ MessageSignatureType_Spend,
+ MessageSignatureType_View
+ };
+
+ struct MessageSignatureResult {
+ bool valid = false;
+ unsigned version = 0;
+ bool old = false;
+ MessageSignatureType type = MessageSignatureType_Invalid;
+ };
+
virtual ~Wallet() = 0;
virtual std::string seed(const std::string& seed_offset = "") const = 0;
virtual std::string getSeedLanguage() const = 0;
@@ -1052,6 +1065,14 @@ struct Wallet
* \return true if the signature verified, false otherwise
*/
virtual bool verifySignedMessage(const std::string &message, const std::string &addres, const std::string &signature) const = 0;
+ /*!
+ * \brief verifySignedMessageWithDetails - verify a signature and identify the signing key and algorithm
+ * \param message - the message (arbitrary byte data)
+ * \param address - the address the signature claims to be made with
+ * \param signature - the signature
+ * \return the verification result, including the signature version and key type
+ */
+ virtual MessageSignatureResult verifySignedMessageWithDetails(const std::string &message, const std::string &address, const std::string &signature) const = 0;
/*!
* \brief signMultisigParticipant signs given message with the multisig public signer key
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 5c4b414..e0a778b 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -1304,9 +1304,9 @@ private:
*/
void set_account_tag_description(const std::string& tag, const std::string& description);
- enum message_signature_type_t { sign_with_spend_key, sign_with_view_key };
+ enum message_signature_type_t { sign_with_spend_key, sign_with_view_key, sign_with_invalid_key };
std::string sign(const std::string &data, message_signature_type_t signature_type, cryptonote::subaddress_index index = {0, 0}) const;
- struct message_signature_result_t { bool valid; unsigned version; bool old; message_signature_type_t type; };
+ struct message_signature_result_t { bool valid = false; unsigned version = 0; bool old = false; message_signature_type_t type = sign_with_invalid_key; };
message_signature_result_t verify(const std::string &data, const cryptonote::account_public_address &address, const std::string &signature) const;
/*!
Why this scored 17/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.