mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-27 03:33:27 -03:00
8dd067088d
Make sure that nothing else can change WitnessUnknown's data members by making them private. Also change the program to use a vector rather than C-style array.
93 lines
2.4 KiB
C++
93 lines
2.4 KiB
C++
// 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 <hash.h>
|
|
#include <key.h>
|
|
#include <key_io.h>
|
|
#include <pubkey.h>
|
|
#include <uint256.h>
|
|
#include <util/message.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);
|
|
}
|