Merge #16792: Assert that the HRP is lowercase in Bech32::Encode

2457aea83c1f9fba708e2335bb197950bf0b6244 Assert that the HRP is lowercase in Bech32::Encode (Samuel Dobson)

Pull request description:

  From BIP-173:
  > The lowercase form is used when determining a character's value for checksum purposes.
  > Encoders MUST always output an all lowercase Bech32 string. If an uppercase version of the encoding result is desired, (e.g.- for presentation purposes, or QR code use), then an uppercasing procedure can be performed external to the encoding process.

  Currently if HRP contains uppercase characters, the checksum will be generated over these uppercase characters resulting in mixed-case output that will always be invalid even if the case is changed manually after encoding. This shouldn't happen because both prefix's `bc` and `tb` are lowercase currently, but we assert this condition anyway.

  This is consistent also with the [C reference implementation](2b0aac650c/ref/c/segwit_addr.c (L59))

ACKs for top commit:
  laanwj:
    ACK 2457aea83c1f9fba708e2335bb197950bf0b6244

Tree-SHA512: 24fcbbc2f315c72c550cc3d82b4332443eea6378fc73d571f98b87492604d023378dd102377c9e05467192cae6049606dee98e4c5688c8d5e4caac50c970284b
This commit is contained in:
Wladimir J. van der Laan 2019-09-05 13:30:59 +02:00 committed by pasta
parent d36d5efee5
commit e8f63fc657
2 changed files with 8 additions and 2 deletions

View File

@ -5,6 +5,8 @@
#include <bech32.h> #include <bech32.h>
#include <util/vector.h> #include <util/vector.h>
#include <assert.h>
namespace namespace
{ {
@ -52,7 +54,7 @@ uint32_t PolyMod(const data& v)
// During the course of the loop below, `c` contains the bitpacked coefficients of the // During the course of the loop below, `c` contains the bitpacked coefficients of the
// polynomial constructed from just the values of v that were processed so far, mod g(x). In // polynomial constructed from just the values of v that were processed so far, mod g(x). In
// the above example, `c` initially corresponds to 1 mod (x), and after processing 2 inputs of // the above example, `c` initially corresponds to 1 mod g(x), and after processing 2 inputs of
// v, it corresponds to x^2 + v0*x + v1 mod g(x). As 1 mod g(x) = 1, that is the starting value // v, it corresponds to x^2 + v0*x + v1 mod g(x). As 1 mod g(x) = 1, that is the starting value
// for `c`. // for `c`.
uint32_t c = 1; uint32_t c = 1;
@ -139,6 +141,10 @@ namespace bech32
/** Encode a Bech32 string. */ /** Encode a Bech32 string. */
std::string Encode(const std::string& hrp, const data& values) { std::string Encode(const std::string& hrp, const data& values) {
// First ensure that the HRP is all lowercase. BIP-173 requires an encoder
// to return a lowercase Bech32 string, but if given an uppercase HRP, the
// result will always be invalid.
for (const char& c : hrp) assert(c < 'A' || c > 'Z');
data checksum = CreateChecksum(hrp, values); data checksum = CreateChecksum(hrp, values);
data combined = Cat(values, checksum); data combined = Cat(values, checksum);
std::string ret = hrp + '1'; std::string ret = hrp + '1';

View File

@ -19,7 +19,7 @@
namespace bech32 namespace bech32
{ {
/** Encode a Bech32 string. Returns the empty string in case of failure. */ /** Encode a Bech32 string. If hrp contains uppercase characters, this will cause an assertion error. */
std::string Encode(const std::string& hrp, const std::vector<uint8_t>& values); std::string Encode(const std::string& hrp, const std::vector<uint8_t>& values);
/** Decode a Bech32 string. Returns (hrp, data). Empty hrp means failure. */ /** Decode a Bech32 string. Returns (hrp, data). Empty hrp means failure. */