Closed FiloSottile closed 3 years ago
I'm no longer active on this project, but for reference for the new maintainers, you guys might want to go ahead and back port the updated version from Decred at https://github.com/decred/dcrd/tree/master/bech32. We originally based it on this implementation from the LL folks, but improved it in many ways, which includes handling what this issue raises properly.
The primary improvements made are:
EncodeFromBase256
and DecodeToBase256
which automatically handles the typical case of converting to base32 with padding before encoding and back to base256 without padding when decodinggithub.com/decred/dcrd/bech32
) and thus provide a tighter module with a smaller API surface which results in less notifications of new versions for consumers due to other things not related to bech32 changingI've slightly modified the code provided by @FiloSottile accordingly to show the improved version works as expected:
https://play.golang.org/p/5wzMOhgiz9Y
package main
import (
"log"
"strings"
"github.com/decred/dcrd/bech32"
)
func main() {
s, err := bech32.EncodeFromBase256("UPPERCASE", []byte("xxx"))
if err != nil {
log.Fatal(err)
}
log.Print("encoded: ", s)
log.Print(bech32.DecodeToBase256(s))
log.Print(bech32.DecodeToBase256(strings.ToUpper(s)))
}
Output:
... encoded: uppercase10pu8sss7kmp
... uppercase[120 120 120] <nil>
... uppercase[120 120 120] <nil>
bech32.Encode will accept an uppercase HRP and generate an invalid bech32 encoding instead of normalizing it or returning an error.
BIP 0173 is clear that mixed case encodings are invalid, and that the lowercase encoding should be used for checksum purposes. This means there are two ways to handle an uppercase HRP in Encode:
Instead, this library will use the uppercase values for the checksum and return a mixed case encoding. Decode will correctly reject the mixed case encoding, and will fail the checksum of the lowercase version.
https://play.golang.org/p/h0ekj8VmiPV