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 3444 : const std::string MESSAGE_MAGIC = "DarkCoin Signed Message:\n"; 26 : 27 41 : MessageVerificationResult MessageVerify( 28 : const std::string& address, 29 : const std::string& signature, 30 : const std::string& message) 31 : { 32 41 : CTxDestination destination = DecodeDestination(address); 33 41 : if (!IsValidDestination(destination)) { 34 3 : return MessageVerificationResult::ERR_INVALID_ADDRESS; 35 : } 36 : 37 38 : if (std::get_if<PKHash>(&destination) == nullptr) { 38 3 : return MessageVerificationResult::ERR_ADDRESS_NO_KEY; 39 : } 40 : 41 35 : auto signature_bytes = DecodeBase64(signature); 42 35 : if (!signature_bytes) { 43 3 : return MessageVerificationResult::ERR_MALFORMED_SIGNATURE; 44 : } 45 : 46 32 : CPubKey pubkey; 47 32 : if (!pubkey.RecoverCompact(MessageHash(message), *signature_bytes)) { 48 1 : return MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED; 49 : } 50 : 51 31 : if (!(CTxDestination(PKHash(pubkey)) == destination)) { 52 5 : return MessageVerificationResult::ERR_NOT_SIGNED; 53 : } 54 : 55 26 : return MessageVerificationResult::OK; 56 41 : } 57 : 58 432 : bool MessageSign( 59 : const CKey& privkey, 60 : const std::string& message, 61 : std::string& signature) 62 : { 63 432 : std::vector<unsigned char> signature_bytes; 64 : 65 432 : if (!privkey.SignCompact(MessageHash(message), signature_bytes)) { 66 1 : return false; 67 : } 68 : 69 431 : signature = EncodeBase64(signature_bytes); 70 : 71 431 : return true; 72 432 : } 73 : 74 465 : uint256 MessageHash(const std::string& message) 75 : { 76 465 : HashWriter hasher{}; 77 465 : hasher << MESSAGE_MAGIC << message; 78 : 79 465 : 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 : }