aboutsummaryrefslogtreecommitdiff
path: root/src/common/signmessage.cpp
diff options
context:
space:
mode:
authorRyan Ofsky <ryan@ofsky.org>2024-05-10 15:45:07 -0400
committerRyan Ofsky <ryan@ofsky.org>2024-05-16 11:16:08 -0400
commit6861f954f8ff42c87ad638037adae86a5bd89600 (patch)
treeb0ffb5123448dab063e0ca4b5669d9f4024de23a /src/common/signmessage.cpp
parentcc5f29fbea15d33e4d1aa95591253c6b86953fe7 (diff)
util: move util/message to common/signmessage
Move util/message to common/signmessage so it is named more clearly, and because the util library is not supposed to depend on other libraries besides the crypto library. The signmessage functions use CKey, CPubKey, PKHash, and DecodeDestination functions in the consensus and common libraries.
Diffstat (limited to 'src/common/signmessage.cpp')
-rw-r--r--src/common/signmessage.cpp93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/common/signmessage.cpp b/src/common/signmessage.cpp
new file mode 100644
index 0000000000..1612751e44
--- /dev/null
+++ b/src/common/signmessage.cpp
@@ -0,0 +1,93 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <common/signmessage.h>
+#include <hash.h>
+#include <key.h>
+#include <key_io.h>
+#include <pubkey.h>
+#include <uint256.h>
+#include <util/strencodings.h>
+
+#include <cassert>
+#include <optional>
+#include <string>
+#include <variant>
+#include <vector>
+
+/**
+ * Text used to signify that a signed message follows and to prevent
+ * inadvertently signing a transaction.
+ */
+const std::string MESSAGE_MAGIC = "Bitcoin Signed Message:\n";
+
+MessageVerificationResult MessageVerify(
+ const std::string& address,
+ const std::string& signature,
+ const std::string& message)
+{
+ CTxDestination destination = DecodeDestination(address);
+ if (!IsValidDestination(destination)) {
+ return MessageVerificationResult::ERR_INVALID_ADDRESS;
+ }
+
+ if (std::get_if<PKHash>(&destination) == nullptr) {
+ return MessageVerificationResult::ERR_ADDRESS_NO_KEY;
+ }
+
+ auto signature_bytes = DecodeBase64(signature);
+ if (!signature_bytes) {
+ return MessageVerificationResult::ERR_MALFORMED_SIGNATURE;
+ }
+
+ CPubKey pubkey;
+ if (!pubkey.RecoverCompact(MessageHash(message), *signature_bytes)) {
+ return MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED;
+ }
+
+ if (!(PKHash(pubkey) == *std::get_if<PKHash>(&destination))) {
+ return MessageVerificationResult::ERR_NOT_SIGNED;
+ }
+
+ return MessageVerificationResult::OK;
+}
+
+bool MessageSign(
+ const CKey& privkey,
+ const std::string& message,
+ std::string& signature)
+{
+ std::vector<unsigned char> signature_bytes;
+
+ if (!privkey.SignCompact(MessageHash(message), signature_bytes)) {
+ return false;
+ }
+
+ signature = EncodeBase64(signature_bytes);
+
+ return true;
+}
+
+uint256 MessageHash(const std::string& message)
+{
+ HashWriter hasher{};
+ hasher << MESSAGE_MAGIC << message;
+
+ return hasher.GetHash();
+}
+
+std::string SigningResultString(const SigningResult res)
+{
+ switch (res) {
+ case SigningResult::OK:
+ return "No error";
+ case SigningResult::PRIVATE_KEY_NOT_AVAILABLE:
+ return "Private key not available";
+ case SigningResult::SIGNING_FAILED:
+ return "Sign failed";
+ // no default case, so the compiler can warn about missing cases
+ }
+ assert(false);
+}