Skip to content

Commit 5667b0d

Browse files
committed
Merge #16792: Assert that the HRP is lowercase in Bech32::Encode
2457aea 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](https://github.com/sipa/bech32/blob/2b0aac650ce560fb2b2a2bebeacaa5c87d7e5938/ref/c/segwit_addr.c#L59) ACKs for top commit: laanwj: ACK 2457aea Tree-SHA512: 24fcbbc2f315c72c550cc3d82b4332443eea6378fc73d571f98b87492604d023378dd102377c9e05467192cae6049606dee98e4c5688c8d5e4caac50c970284b
2 parents cbde2bc + 2457aea commit 5667b0d

File tree

2 files changed

+8
-2
lines changed

2 files changed

+8
-2
lines changed

src/bech32.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
#include <bech32.h>
66

7+
#include <assert.h>
8+
79
namespace
810
{
911

@@ -58,7 +60,7 @@ uint32_t PolyMod(const data& v)
5860

5961
// During the course of the loop below, `c` contains the bitpacked coefficients of the
6062
// polynomial constructed from just the values of v that were processed so far, mod g(x). In
61-
// the above example, `c` initially corresponds to 1 mod (x), and after processing 2 inputs of
63+
// the above example, `c` initially corresponds to 1 mod g(x), and after processing 2 inputs of
6264
// v, it corresponds to x^2 + v0*x + v1 mod g(x). As 1 mod g(x) = 1, that is the starting value
6365
// for `c`.
6466
uint32_t c = 1;
@@ -145,6 +147,10 @@ namespace bech32
145147

146148
/** Encode a Bech32 string. */
147149
std::string Encode(const std::string& hrp, const data& values) {
150+
// First ensure that the HRP is all lowercase. BIP-173 requires an encoder
151+
// to return a lowercase Bech32 string, but if given an uppercase HRP, the
152+
// result will always be invalid.
153+
for (const char& c : hrp) assert(c < 'A' || c > 'Z');
148154
data checksum = CreateChecksum(hrp, values);
149155
data combined = Cat(values, checksum);
150156
std::string ret = hrp + '1';

src/bech32.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
namespace bech32
2020
{
2121

22-
/** Encode a Bech32 string. Returns the empty string in case of failure. */
22+
/** Encode a Bech32 string. If hrp contains uppercase characters, this will cause an assertion error. */
2323
std::string Encode(const std::string& hrp, const std::vector<uint8_t>& values);
2424

2525
/** Decode a Bech32 string. Returns (hrp, data). Empty hrp means failure. */

0 commit comments

Comments
 (0)