mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 23:09:44 -04:00
Make DecodeBase{32,64} return optional instead of taking bool*
This commit is contained in:
parent
a65931e3ce
commit
78f3ac51b7
11 changed files with 57 additions and 77 deletions
|
@ -132,10 +132,10 @@ static bool RPCAuthorized(const std::string& strAuth, std::string& strAuthUserna
|
||||||
if (strAuth.substr(0, 6) != "Basic ")
|
if (strAuth.substr(0, 6) != "Basic ")
|
||||||
return false;
|
return false;
|
||||||
std::string strUserPass64 = TrimString(strAuth.substr(6));
|
std::string strUserPass64 = TrimString(strAuth.substr(6));
|
||||||
bool invalid;
|
auto userpass_data = DecodeBase64(strUserPass64);
|
||||||
std::vector<unsigned char> userpass_data = DecodeBase64(strUserPass64, &invalid);
|
std::string strUserPass;
|
||||||
if (invalid) return false;
|
if (!userpass_data) return false;
|
||||||
std::string strUserPass(userpass_data.begin(), userpass_data.end());
|
strUserPass.assign(userpass_data->begin(), userpass_data->end());
|
||||||
|
|
||||||
if (strUserPass.find(':') != std::string::npos)
|
if (strUserPass.find(':') != std::string::npos)
|
||||||
strAuthUsernameOut = strUserPass.substr(0, strUserPass.find(':'));
|
strAuthUsernameOut = strUserPass.substr(0, strUserPass.find(':'));
|
||||||
|
|
|
@ -69,12 +69,11 @@ static std::string SwapBase64(const std::string& from)
|
||||||
static Binary DecodeI2PBase64(const std::string& i2p_b64)
|
static Binary DecodeI2PBase64(const std::string& i2p_b64)
|
||||||
{
|
{
|
||||||
const std::string& std_b64 = SwapBase64(i2p_b64);
|
const std::string& std_b64 = SwapBase64(i2p_b64);
|
||||||
bool invalid;
|
auto decoded = DecodeBase64(std_b64);
|
||||||
Binary decoded = DecodeBase64(std_b64, &invalid);
|
if (!decoded) {
|
||||||
if (invalid) {
|
|
||||||
throw std::runtime_error(strprintf("Cannot decode Base64: \"%s\"", i2p_b64));
|
throw std::runtime_error(strprintf("Cannot decode Base64: \"%s\"", i2p_b64));
|
||||||
}
|
}
|
||||||
return decoded;
|
return std::move(*decoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -234,17 +234,16 @@ bool CNetAddr::SetTor(const std::string& addr)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool invalid;
|
auto input = DecodeBase32(addr.substr(0, addr.size() - suffix_len));
|
||||||
const auto& input = DecodeBase32(addr.substr(0, addr.size() - suffix_len), &invalid);
|
|
||||||
|
|
||||||
if (invalid) {
|
if (!input) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.size() == torv3::TOTAL_LEN) {
|
if (input->size() == torv3::TOTAL_LEN) {
|
||||||
Span<const uint8_t> input_pubkey{input.data(), ADDR_TORV3_SIZE};
|
Span<const uint8_t> input_pubkey{input->data(), ADDR_TORV3_SIZE};
|
||||||
Span<const uint8_t> input_checksum{input.data() + ADDR_TORV3_SIZE, torv3::CHECKSUM_LEN};
|
Span<const uint8_t> input_checksum{input->data() + ADDR_TORV3_SIZE, torv3::CHECKSUM_LEN};
|
||||||
Span<const uint8_t> input_version{input.data() + ADDR_TORV3_SIZE + torv3::CHECKSUM_LEN, sizeof(torv3::VERSION)};
|
Span<const uint8_t> input_version{input->data() + ADDR_TORV3_SIZE + torv3::CHECKSUM_LEN, sizeof(torv3::VERSION)};
|
||||||
|
|
||||||
if (input_version != torv3::VERSION) {
|
if (input_version != torv3::VERSION) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -280,15 +279,14 @@ bool CNetAddr::SetI2P(const std::string& addr)
|
||||||
// can decode it.
|
// can decode it.
|
||||||
const std::string b32_padded = addr.substr(0, b32_len) + "====";
|
const std::string b32_padded = addr.substr(0, b32_len) + "====";
|
||||||
|
|
||||||
bool invalid;
|
auto address_bytes = DecodeBase32(b32_padded);
|
||||||
const auto& address_bytes = DecodeBase32(b32_padded.c_str(), &invalid);
|
|
||||||
|
|
||||||
if (invalid || address_bytes.size() != ADDR_I2P_SIZE) {
|
if (!address_bytes || address_bytes->size() != ADDR_I2P_SIZE) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_net = NET_I2P;
|
m_net = NET_I2P;
|
||||||
m_addr.assign(address_bytes.begin(), address_bytes.end());
|
m_addr.assign(address_bytes->begin(), address_bytes->end());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -388,13 +388,12 @@ std::string PSBTRoleName(PSBTRole role) {
|
||||||
|
|
||||||
bool DecodeBase64PSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx, std::string& error)
|
bool DecodeBase64PSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx, std::string& error)
|
||||||
{
|
{
|
||||||
bool invalid;
|
auto tx_data = DecodeBase64(base64_tx);
|
||||||
auto tx_data = DecodeBase64(base64_tx, &invalid);
|
if (!tx_data) {
|
||||||
if (invalid) {
|
|
||||||
error = "invalid base64";
|
error = "invalid base64";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return DecodeRawPSBT(psbt, MakeByteSpan(tx_data), error);
|
return DecodeRawPSBT(psbt, MakeByteSpan(*tx_data), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DecodeRawPSBT(PartiallySignedTransaction& psbt, Span<const std::byte> tx_data, std::string& error)
|
bool DecodeRawPSBT(PartiallySignedTransaction& psbt, Span<const std::byte> tx_data, std::string& error)
|
||||||
|
|
|
@ -198,12 +198,12 @@ void WalletFrame::gotoLoadPSBT(bool from_clipboard)
|
||||||
|
|
||||||
if (from_clipboard) {
|
if (from_clipboard) {
|
||||||
std::string raw = QApplication::clipboard()->text().toStdString();
|
std::string raw = QApplication::clipboard()->text().toStdString();
|
||||||
bool invalid;
|
auto result = DecodeBase64(raw);
|
||||||
data = DecodeBase64(raw, &invalid);
|
if (!result) {
|
||||||
if (invalid) {
|
|
||||||
Q_EMIT message(tr("Error"), tr("Unable to decode PSBT from clipboard (invalid base64)"), CClientUIInterface::MSG_ERROR);
|
Q_EMIT message(tr("Error"), tr("Unable to decode PSBT from clipboard (invalid base64)"), CClientUIInterface::MSG_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
data = std::move(*result);
|
||||||
} else {
|
} else {
|
||||||
QString filename = GUIUtil::getOpenFileName(this,
|
QString filename = GUIUtil::getOpenFileName(this,
|
||||||
tr("Load Transaction Data"), QString(),
|
tr("Load Transaction Data"), QString(),
|
||||||
|
|
|
@ -22,22 +22,16 @@ BOOST_AUTO_TEST_CASE(base32_testvectors)
|
||||||
BOOST_CHECK_EQUAL(strEnc, vstrOut[i]);
|
BOOST_CHECK_EQUAL(strEnc, vstrOut[i]);
|
||||||
strEnc = EncodeBase32(vstrIn[i], false);
|
strEnc = EncodeBase32(vstrIn[i], false);
|
||||||
BOOST_CHECK_EQUAL(strEnc, vstrOutNoPadding[i]);
|
BOOST_CHECK_EQUAL(strEnc, vstrOutNoPadding[i]);
|
||||||
bool invalid;
|
auto dec = DecodeBase32(vstrOut[i]);
|
||||||
auto dec = DecodeBase32(vstrOut[i], &invalid);
|
BOOST_REQUIRE(dec);
|
||||||
BOOST_CHECK(!invalid);
|
BOOST_CHECK_MESSAGE(MakeByteSpan(*dec) == MakeByteSpan(vstrIn[i]), vstrOut[i]);
|
||||||
BOOST_CHECK_MESSAGE(MakeByteSpan(dec) == MakeByteSpan(vstrIn[i]), vstrOut[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decoding strings with embedded NUL characters should fail
|
// Decoding strings with embedded NUL characters should fail
|
||||||
bool failure;
|
BOOST_CHECK(!DecodeBase32("invalid\0"s)); // correct size, invalid due to \0
|
||||||
(void)DecodeBase32("invalid\0"s, &failure); // correct size, invalid due to \0
|
BOOST_CHECK(DecodeBase32("AWSX3VPP"s)); // valid
|
||||||
BOOST_CHECK(failure);
|
BOOST_CHECK(!DecodeBase32("AWSX3VPP\0invalid"s)); // correct size, invalid due to \0
|
||||||
(void)DecodeBase32("AWSX3VPP"s, &failure); // valid
|
BOOST_CHECK(!DecodeBase32("AWSX3VPPinvalid"s)); // invalid size
|
||||||
BOOST_CHECK(!failure);
|
|
||||||
(void)DecodeBase32("AWSX3VPP\0invalid"s, &failure); // correct size, invalid due to \0
|
|
||||||
BOOST_CHECK(failure);
|
|
||||||
(void)DecodeBase32("AWSX3VPPinvalid"s, &failure); // invalid size
|
|
||||||
BOOST_CHECK(failure);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
|
@ -19,10 +19,9 @@ BOOST_AUTO_TEST_CASE(base64_testvectors)
|
||||||
{
|
{
|
||||||
std::string strEnc = EncodeBase64(vstrIn[i]);
|
std::string strEnc = EncodeBase64(vstrIn[i]);
|
||||||
BOOST_CHECK_EQUAL(strEnc, vstrOut[i]);
|
BOOST_CHECK_EQUAL(strEnc, vstrOut[i]);
|
||||||
bool invalid;
|
auto dec = DecodeBase64(strEnc);
|
||||||
auto dec = DecodeBase64(strEnc, &invalid);
|
BOOST_REQUIRE(dec);
|
||||||
BOOST_CHECK(!invalid);
|
BOOST_CHECK_MESSAGE(MakeByteSpan(*dec) == MakeByteSpan(vstrIn[i]), vstrOut[i]);
|
||||||
BOOST_CHECK_MESSAGE(MakeByteSpan(dec) == MakeByteSpan(vstrIn[i]), vstrOut[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -36,15 +35,10 @@ BOOST_AUTO_TEST_CASE(base64_testvectors)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decoding strings with embedded NUL characters should fail
|
// Decoding strings with embedded NUL characters should fail
|
||||||
bool failure;
|
BOOST_CHECK(!DecodeBase64("invalid\0"s));
|
||||||
(void)DecodeBase64("invalid\0"s, &failure);
|
BOOST_CHECK(DecodeBase64("nQB/pZw="s));
|
||||||
BOOST_CHECK(failure);
|
BOOST_CHECK(!DecodeBase64("nQB/pZw=\0invalid"s));
|
||||||
(void)DecodeBase64("nQB/pZw="s, &failure);
|
BOOST_CHECK(!DecodeBase64("nQB/pZw=invalid\0"s));
|
||||||
BOOST_CHECK(!failure);
|
|
||||||
(void)DecodeBase64("nQB/pZw=\0invalid"s, &failure);
|
|
||||||
BOOST_CHECK(failure);
|
|
||||||
(void)DecodeBase64("nQB/pZw=invalid\0"s, &failure);
|
|
||||||
BOOST_CHECK(failure);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
|
@ -36,17 +36,16 @@ FUZZ_TARGET_INIT(base_encode_decode, initialize_base_encode_decode)
|
||||||
assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string)));
|
assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pf_invalid;
|
auto result = DecodeBase32(random_encoded_string);
|
||||||
decoded = DecodeBase32(random_encoded_string, &pf_invalid);
|
if (result) {
|
||||||
if (!pf_invalid) {
|
const std::string encoded_string = EncodeBase32(*result);
|
||||||
const std::string encoded_string = EncodeBase32(decoded);
|
|
||||||
assert(encoded_string == TrimString(encoded_string));
|
assert(encoded_string == TrimString(encoded_string));
|
||||||
assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string)));
|
assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string)));
|
||||||
}
|
}
|
||||||
|
|
||||||
decoded = DecodeBase64(random_encoded_string, &pf_invalid);
|
result = DecodeBase64(random_encoded_string);
|
||||||
if (!pf_invalid) {
|
if (result) {
|
||||||
const std::string encoded_string = EncodeBase64(decoded);
|
const std::string encoded_string = EncodeBase64(*result);
|
||||||
assert(encoded_string == TrimString(encoded_string));
|
assert(encoded_string == TrimString(encoded_string));
|
||||||
assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string)));
|
assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,14 +35,13 @@ MessageVerificationResult MessageVerify(
|
||||||
return MessageVerificationResult::ERR_ADDRESS_NO_KEY;
|
return MessageVerificationResult::ERR_ADDRESS_NO_KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool invalid = false;
|
auto signature_bytes = DecodeBase64(signature);
|
||||||
std::vector<unsigned char> signature_bytes = DecodeBase64(signature, &invalid);
|
if (!signature_bytes) {
|
||||||
if (invalid) {
|
|
||||||
return MessageVerificationResult::ERR_MALFORMED_SIGNATURE;
|
return MessageVerificationResult::ERR_MALFORMED_SIGNATURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPubKey pubkey;
|
CPubKey pubkey;
|
||||||
if (!pubkey.RecoverCompact(MessageHash(message), signature_bytes)) {
|
if (!pubkey.RecoverCompact(MessageHash(message), *signature_bytes)) {
|
||||||
return MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED;
|
return MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -126,7 +126,7 @@ std::string EncodeBase64(Span<const unsigned char> input)
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> DecodeBase64(const char* p, bool* pf_invalid)
|
std::optional<std::vector<unsigned char>> DecodeBase64(const char* p)
|
||||||
{
|
{
|
||||||
static const int8_t decode64_table[256]{
|
static const int8_t decode64_table[256]{
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
@ -167,18 +167,17 @@ std::vector<unsigned char> DecodeBase64(const char* p, bool* pf_invalid)
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
valid = valid && (p - e) % 4 == 0 && p - q < 4;
|
valid = valid && (p - e) % 4 == 0 && p - q < 4;
|
||||||
*pf_invalid = !valid;
|
if (!valid) return {};
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> DecodeBase64(const std::string& str, bool* pf_invalid)
|
std::optional<std::vector<unsigned char>> DecodeBase64(const std::string& str)
|
||||||
{
|
{
|
||||||
if (!ValidAsCString(str)) {
|
if (!ValidAsCString(str)) {
|
||||||
*pf_invalid = true;
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return DecodeBase64(str.c_str(), pf_invalid);
|
return DecodeBase64(str.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EncodeBase32(Span<const unsigned char> input, bool pad)
|
std::string EncodeBase32(Span<const unsigned char> input, bool pad)
|
||||||
|
@ -201,7 +200,7 @@ std::string EncodeBase32(const std::string& str, bool pad)
|
||||||
return EncodeBase32(MakeUCharSpan(str), pad);
|
return EncodeBase32(MakeUCharSpan(str), pad);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> DecodeBase32(const char* p, bool* pf_invalid)
|
std::optional<std::vector<unsigned char>> DecodeBase32(const char* p)
|
||||||
{
|
{
|
||||||
static const int8_t decode32_table[256]{
|
static const int8_t decode32_table[256]{
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
@ -242,18 +241,17 @@ std::vector<unsigned char> DecodeBase32(const char* p, bool* pf_invalid)
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
valid = valid && (p - e) % 8 == 0 && p - q < 8;
|
valid = valid && (p - e) % 8 == 0 && p - q < 8;
|
||||||
*pf_invalid = !valid;
|
if (!valid) return {};
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> DecodeBase32(const std::string& str, bool* pf_invalid)
|
std::optional<std::vector<unsigned char>> DecodeBase32(const std::string& str)
|
||||||
{
|
{
|
||||||
if (!ValidAsCString(str)) {
|
if (!ValidAsCString(str)) {
|
||||||
*pf_invalid = true;
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return DecodeBase32(str.c_str(), pf_invalid);
|
return DecodeBase32(str.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -64,13 +64,13 @@ bool IsHex(std::string_view str);
|
||||||
* Return true if the string is a hex number, optionally prefixed with "0x"
|
* Return true if the string is a hex number, optionally prefixed with "0x"
|
||||||
*/
|
*/
|
||||||
bool IsHexNumber(std::string_view str);
|
bool IsHexNumber(std::string_view str);
|
||||||
std::vector<unsigned char> DecodeBase64(const char* p, bool* pf_invalid);
|
std::optional<std::vector<unsigned char>> DecodeBase64(const char* p);
|
||||||
std::vector<unsigned char> DecodeBase64(const std::string& str, bool* pf_invalid);
|
std::optional<std::vector<unsigned char>> DecodeBase64(const std::string& str);
|
||||||
std::string EncodeBase64(Span<const unsigned char> input);
|
std::string EncodeBase64(Span<const unsigned char> input);
|
||||||
inline std::string EncodeBase64(Span<const std::byte> input) { return EncodeBase64(MakeUCharSpan(input)); }
|
inline std::string EncodeBase64(Span<const std::byte> input) { return EncodeBase64(MakeUCharSpan(input)); }
|
||||||
inline std::string EncodeBase64(const std::string& str) { return EncodeBase64(MakeUCharSpan(str)); }
|
inline std::string EncodeBase64(const std::string& str) { return EncodeBase64(MakeUCharSpan(str)); }
|
||||||
std::vector<unsigned char> DecodeBase32(const char* p, bool* pf_invalid);
|
std::optional<std::vector<unsigned char>> DecodeBase32(const char* p);
|
||||||
std::vector<unsigned char> DecodeBase32(const std::string& str, bool* pf_invalid);
|
std::optional<std::vector<unsigned char>> DecodeBase32(const std::string& str);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base32 encode.
|
* Base32 encode.
|
||||||
|
|
Loading…
Add table
Reference in a new issue