bech32
bech32 copied to clipboard
Haskell implementation of `bech32Encode` generates invalid output if the HRP contains upper case characters.
Overview
When bech32Encode is called with a human-readable part that contains one or more upper-case characters, it produces in an invalid Bech32 string that cannot be decoded with the bech32Decode function.
Analysis
As part of the encoding process, the human-readable part is converted to lower case:
https://github.com/sipa/bech32/blob/a4e672df3b79be54a9b14a33ae5fdb7d10a1dd26/ref/haskell/src/Codec/Binary/Bech32.hs#L85
However, the checksum is calculated before the conversion to lower case takes place:
https://github.com/sipa/bech32/blob/a4e672df3b79be54a9b14a33ae5fdb7d10a1dd26/ref/haskell/src/Codec/Binary/Bech32.hs#L83
This contradicts the Bech32 specification, which states:
"The lowercase form is used when determining a character's value for checksum purposes."
Therefore, if the original human-readable part contains one or more upper case characters:
- the generated checksum will be inconsistent with the human-readable prefix of the output string
- the output string will fail to decode.
Example
Consider the following two calls to bech32Encode, differing only in the case of the human-readable part:
> bech32Encode "test" []
> bech32Encode "TEST" []
Expected Behaviour
Both calls to bech32Encode should result in the same output string:
> bech32Encode "test" []
Just "test12hrzfj"
> bech32Encode "TEST" []
Just "test12hrzfj"
> bech32Encode "test" [] == bech32Encode "TEST" []
True
Actual Behaviour
The above calls to bech32Encode actually result in different output strings:
> bech32Encode "test" []
Just "test12hrzfj"
> bech32Encode "TEST" []
Just "test13jgcyw"
> bech32Encode "test" [] == bech32Encode "TEST" []
False
Attempting to decode the string produced by bech32Encode "TEST" [] results in Nothing:
> bech32Decode "test13jgcyw"
Nothing
I haven't looked at the details but seems related to #38.
I've created a PR that fixes the issue here: https://github.com/sipa/bech32/pull/50