+++ /dev/null
-package bech32
-
-import (
- "fmt"
- "strings"
-)
-
-const charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
-
-var gen = []int{0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3}
-
-// Decode decodes a bech32 encoded string, returning the human-readable
-// part and the data part excluding the checksum.
-func Bech32Decode(bech string) (string, []byte, error) {
- // The maximum allowed length for a bech32 string is 90. It must also
- // be at least 8 characters, since it needs a non-empty HRP, a
- // separator, and a 6 character checksum.
- if len(bech) < 8 || len(bech) > 90 {
- return "", nil, fmt.Errorf("invalid bech32 string length %d",
- len(bech))
- }
- // Only ASCII characters between 33 and 126 are allowed.
- for i := 0; i < len(bech); i++ {
- if bech[i] < 33 || bech[i] > 126 {
- return "", nil, fmt.Errorf("invalid character in "+
- "string: '%c'", bech[i])
- }
- }
-
- // The characters must be either all lowercase or all uppercase.
- lower := strings.ToLower(bech)
- upper := strings.ToUpper(bech)
- if bech != lower && bech != upper {
- return "", nil, fmt.Errorf("string not all lowercase or all " +
- "uppercase")
- }
-
- // We'll work with the lowercase string from now on.
- bech = lower
-
- // The string is invalid if the last '1' is non-existent, it is the
- // first character of the string (no human-readable part) or one of the
- // last 6 characters of the string (since checksum cannot contain '1'),
- // or if the string is more than 90 characters in total.
- one := strings.LastIndexByte(bech, '1')
- if one < 1 || one+7 > len(bech) {
- return "", nil, fmt.Errorf("invalid index of 1")
- }
-
- // The human-readable part is everything before the last '1'.
- hrp := bech[:one]
- data := bech[one+1:]
-
- // Each character corresponds to the byte with value of the index in
- // 'charset'.
- decoded, err := toBytes(data)
- if err != nil {
- return "", nil, fmt.Errorf("failed converting data to bytes: "+
- "%v", err)
- }
-
- if !bech32VerifyChecksum(hrp, decoded) {
- moreInfo := ""
- checksum := bech[len(bech)-6:]
- expected, err := toChars(bech32Checksum(hrp,
- decoded[:len(decoded)-6]))
- if err == nil {
- moreInfo = fmt.Sprintf("Expected %v, got %v.",
- expected, checksum)
- }
- return "", nil, fmt.Errorf("checksum failed. " + moreInfo)
- }
-
- // We exclude the last 6 bytes, which is the checksum.
- return hrp, decoded[:len(decoded)-6], nil
-}
-
-// Encode encodes a byte slice into a bech32 string with the
-// human-readable part hrb. Note that the bytes must each encode 5 bits
-// (base32).
-func Bech32Encode(hrp string, data []byte) (string, error) {
- // Calculate the checksum of the data and append it at the end.
- checksum := bech32Checksum(hrp, data)
- combined := append(data, checksum...)
-
- // The resulting bech32 string is the concatenation of the hrp, the
- // separator 1, data and checksum. Everything after the separator is
- // represented using the specified charset.
- dataChars, err := toChars(combined)
- if err != nil {
- return "", fmt.Errorf("unable to convert data bytes to chars: "+
- "%v", err)
- }
- return hrp + "1" + dataChars, nil
-}
-
-// toBytes converts each character in the string 'chars' to the value of the
-// index of the correspoding character in 'charset'.
-func toBytes(chars string) ([]byte, error) {
- decoded := make([]byte, 0, len(chars))
- for i := 0; i < len(chars); i++ {
- index := strings.IndexByte(charset, chars[i])
- if index < 0 {
- return nil, fmt.Errorf("invalid character not part of "+
- "charset: %v", chars[i])
- }
- decoded = append(decoded, byte(index))
- }
- return decoded, nil
-}
-
-// toChars converts the byte slice 'data' to a string where each byte in 'data'
-// encodes the index of a character in 'charset'.
-func toChars(data []byte) (string, error) {
- result := make([]byte, 0, len(data))
- for _, b := range data {
- if int(b) >= len(charset) {
- return "", fmt.Errorf("invalid data byte: %v", b)
- }
- result = append(result, charset[b])
- }
- return string(result), nil
-}
-
-// ConvertBits converts a byte slice where each byte is encoding fromBits bits,
-// to a byte slice where each byte is encoding toBits bits.
-func ConvertBits(data []byte, fromBits, toBits uint8, pad bool) ([]byte, error) {
- if fromBits < 1 || fromBits > 8 || toBits < 1 || toBits > 8 {
- return nil, fmt.Errorf("only bit groups between 1 and 8 allowed")
- }
-
- // The final bytes, each byte encoding toBits bits.
- var regrouped []byte
-
- // Keep track of the next byte we create and how many bits we have
- // added to it out of the toBits goal.
- nextByte := byte(0)
- filledBits := uint8(0)
-
- for _, b := range data {
-
- // Discard unused bits.
- b = b << (8 - fromBits)
-
- // How many bits remaining to extract from the input data.
- remFromBits := fromBits
- for remFromBits > 0 {
- // How many bits remaining to be added to the next byte.
- remToBits := toBits - filledBits
-
- // The number of bytes to next extract is the minimum of
- // remFromBits and remToBits.
- toExtract := remFromBits
- if remToBits < toExtract {
- toExtract = remToBits
- }
-
- // Add the next bits to nextByte, shifting the already
- // added bits to the left.
- nextByte = (nextByte << toExtract) | (b >> (8 - toExtract))
-
- // Discard the bits we just extracted and get ready for
- // next iteration.
- b = b << toExtract
- remFromBits -= toExtract
- filledBits += toExtract
-
- // If the nextByte is completely filled, we add it to
- // our regrouped bytes and start on the next byte.
- if filledBits == toBits {
- regrouped = append(regrouped, nextByte)
- filledBits = 0
- nextByte = 0
- }
- }
- }
-
- // We pad any unfinished group if specified.
- if pad && filledBits > 0 {
- nextByte = nextByte << (toBits - filledBits)
- regrouped = append(regrouped, nextByte)
- filledBits = 0
- nextByte = 0
- }
-
- // Any incomplete group must be <= 4 bits, and all zeroes.
- if filledBits > 0 && (filledBits > 4 || nextByte != 0) {
- return nil, fmt.Errorf("invalid incomplete group")
- }
-
- return regrouped, nil
-}
-
-// For more details on the checksum calculation, please refer to BIP 173.
-func bech32Checksum(hrp string, data []byte) []byte {
- // Convert the bytes to list of integers, as this is needed for the
- // checksum calculation.
- integers := make([]int, len(data))
- for i, b := range data {
- integers[i] = int(b)
- }
- values := append(bech32HrpExpand(hrp), integers...)
- values = append(values, []int{0, 0, 0, 0, 0, 0}...)
- polymod := bech32Polymod(values) ^ 1
- var res []byte
- for i := 0; i < 6; i++ {
- res = append(res, byte((polymod>>uint(5*(5-i)))&31))
- }
- return res
-}
-
-// For more details on the polymod calculation, please refer to BIP 173.
-func bech32Polymod(values []int) int {
- chk := 1
- for _, v := range values {
- b := chk >> 25
- chk = (chk&0x1ffffff)<<5 ^ v
- for i := 0; i < 5; i++ {
- if (b>>uint(i))&1 == 1 {
- chk ^= gen[i]
- }
- }
- }
- return chk
-}
-
-// For more details on HRP expansion, please refer to BIP 173.
-func bech32HrpExpand(hrp string) []int {
- v := make([]int, 0, len(hrp)*2+1)
- for i := 0; i < len(hrp); i++ {
- v = append(v, int(hrp[i]>>5))
- }
- v = append(v, 0)
- for i := 0; i < len(hrp); i++ {
- v = append(v, int(hrp[i]&31))
- }
- return v
-}
-
-// For more details on the checksum verification, please refer to BIP 173.
-func bech32VerifyChecksum(hrp string, data []byte) bool {
- integers := make([]int, len(data))
- for i, b := range data {
- integers[i] = int(b)
- }
- concat := append(bech32HrpExpand(hrp), integers...)
- return bech32Polymod(concat) == 1
-}