Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto 2 : // Copyright (c) 2009-2021 The Bitcoin Core developers 3 : // Distributed under the MIT software license, see the accompanying 4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 5 : 6 : #include <hash.h> 7 : #include <key.h> 8 : #include <key_io.h> 9 : #include <pubkey.h> 10 : #include <script/standard.h> 11 : #include <uint256.h> 12 : #include <util/message.h> 13 : #include <util/strencodings.h> 14 : 15 : #include <cassert> 16 : #include <optional> 17 : #include <string> 18 : #include <variant> 19 : #include <vector> 20 : 21 : /** 22 : * Text used to signify that a signed message follows and to prevent 23 : * inadvertently signing a transaction. 24 : */ 25 146 : const std::string MESSAGE_MAGIC = "DarkCoin Signed Message:\n"; 26 : 27 7 : MessageVerificationResult MessageVerify( 28 : const std::string& address, 29 : const std::string& signature, 30 : const std::string& message) 31 : { 32 7 : CTxDestination destination = DecodeDestination(address); 33 7 : if (!IsValidDestination(destination)) { 34 1 : return MessageVerificationResult::ERR_INVALID_ADDRESS; 35 : } 36 : 37 6 : if (std::get_if<PKHash>(&destination) == nullptr) { 38 1 : return MessageVerificationResult::ERR_ADDRESS_NO_KEY; 39 : } 40 : 41 5 : auto signature_bytes = DecodeBase64(signature); 42 5 : if (!signature_bytes) { 43 1 : return MessageVerificationResult::ERR_MALFORMED_SIGNATURE; 44 : } 45 : 46 4 : CPubKey pubkey; 47 4 : if (!pubkey.RecoverCompact(MessageHash(message), *signature_bytes)) { 48 1 : return MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED; 49 : } 50 : 51 3 : if (!(CTxDestination(PKHash(pubkey)) == destination)) { 52 1 : return MessageVerificationResult::ERR_NOT_SIGNED; 53 : } 54 : 55 2 : return MessageVerificationResult::OK; 56 7 : } 57 : 58 2 : bool MessageSign( 59 : const CKey& privkey, 60 : const std::string& message, 61 : std::string& signature) 62 : { 63 2 : std::vector<unsigned char> signature_bytes; 64 : 65 2 : if (!privkey.SignCompact(MessageHash(message), signature_bytes)) { 66 1 : return false; 67 : } 68 : 69 1 : signature = EncodeBase64(signature_bytes); 70 : 71 1 : return true; 72 2 : } 73 : 74 7 : uint256 MessageHash(const std::string& message) 75 : { 76 7 : HashWriter hasher{}; 77 7 : hasher << MESSAGE_MAGIC << message; 78 : 79 7 : return hasher.GetHash(); 80 : } 81 : 82 0 : std::string SigningResultString(const SigningResult res) 83 : { 84 0 : switch (res) { 85 : case SigningResult::OK: 86 0 : return "No error"; 87 : case SigningResult::PRIVATE_KEY_NOT_AVAILABLE: 88 0 : return "Private key not available"; 89 : case SigningResult::SIGNING_FAILED: 90 0 : return "Sign failed"; 91 : // no default case, so the compiler can warn about missing cases 92 : } 93 0 : assert(false); 94 0 : }