/ zpay32 / bech32.go
bech32.go
  1  package zpay32
  2  
  3  import (
  4  	"fmt"
  5  	"strings"
  6  )
  7  
  8  const charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
  9  
 10  var gen = []int{0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3}
 11  
 12  // NOTE: This method it a slight modification of the method bech32.Decode found
 13  // btcutil, allowing strings to be more than 90 characters.
 14  
 15  // decodeBech32 decodes a bech32 encoded string, returning the human-readable
 16  // part and the data part excluding the checksum.
 17  // Note: the data will be base32 encoded, that is each element of the returned
 18  // byte array will encode 5 bits of data. Use the ConvertBits method to convert
 19  // this to 8-bit representation.
 20  func decodeBech32(bech string) (string, []byte, error) {
 21  	// The maximum allowed length for a bech32 string is 90. It must also
 22  	// be at least 8 characters, since it needs a non-empty HRP, a
 23  	// separator, and a 6 character checksum.
 24  	// NB: The 90 character check specified in BIP173 is skipped here, to
 25  	// allow strings longer than 90 characters.
 26  	if len(bech) < 8 {
 27  		return "", nil, fmt.Errorf("invalid bech32 string length %d",
 28  			len(bech))
 29  	}
 30  	// Only	ASCII characters between 33 and 126 are allowed.
 31  	for i := 0; i < len(bech); i++ {
 32  		if bech[i] < 33 || bech[i] > 126 {
 33  			return "", nil, fmt.Errorf("invalid character in "+
 34  				"string: '%c'", bech[i])
 35  		}
 36  	}
 37  
 38  	// The characters must be either all lowercase or all uppercase.
 39  	lower := strings.ToLower(bech)
 40  	upper := strings.ToUpper(bech)
 41  	if bech != lower && bech != upper {
 42  		return "", nil, fmt.Errorf("string not all lowercase or all " +
 43  			"uppercase")
 44  	}
 45  
 46  	// We'll work with the lowercase string from now on.
 47  	bech = lower
 48  
 49  	// The string is invalid if the last '1' is non-existent, it is the
 50  	// first character of the string (no human-readable part) or one of the
 51  	// last 6 characters of the string (since checksum cannot contain '1'),
 52  	// or if the string is more than 90 characters in total.
 53  	one := strings.LastIndexByte(bech, '1')
 54  	if one < 1 || one+7 > len(bech) {
 55  		return "", nil, fmt.Errorf("invalid index of 1")
 56  	}
 57  
 58  	// The human-readable part is everything before the last '1'.
 59  	hrp := bech[:one]
 60  	data := bech[one+1:]
 61  
 62  	// Each character corresponds to the byte with value of the index in
 63  	// 'charset'.
 64  	decoded, err := toBytes(data)
 65  	if err != nil {
 66  		return "", nil, fmt.Errorf("failed converting data to bytes: "+
 67  			"%v", err)
 68  	}
 69  
 70  	if !bech32VerifyChecksum(hrp, decoded) {
 71  		moreInfo := ""
 72  		checksum := bech[len(bech)-6:]
 73  		expected, err := toChars(bech32Checksum(hrp,
 74  			decoded[:len(decoded)-6]))
 75  		if err == nil {
 76  			moreInfo = fmt.Sprintf("Expected %v, got %v.",
 77  				expected, checksum)
 78  		}
 79  
 80  		return "", nil, fmt.Errorf("checksum failed. %s", moreInfo)
 81  	}
 82  
 83  	// We exclude the last 6 bytes, which is the checksum.
 84  	return hrp, decoded[:len(decoded)-6], nil
 85  }
 86  
 87  // toBytes converts each character in the string 'chars' to the value of the
 88  // index of the corresponding character in 'charset'.
 89  func toBytes(chars string) ([]byte, error) {
 90  	decoded := make([]byte, 0, len(chars))
 91  	for i := 0; i < len(chars); i++ {
 92  		index := strings.IndexByte(charset, chars[i])
 93  		if index < 0 {
 94  			return nil, fmt.Errorf("invalid character not part of "+
 95  				"charset: %v", chars[i])
 96  		}
 97  		decoded = append(decoded, byte(index))
 98  	}
 99  	return decoded, nil
100  }
101  
102  // toChars converts the byte slice 'data' to a string where each byte in 'data'
103  // encodes the index of a character in 'charset'.
104  func toChars(data []byte) (string, error) {
105  	result := make([]byte, 0, len(data))
106  	for _, b := range data {
107  		if int(b) >= len(charset) {
108  			return "", fmt.Errorf("invalid data byte: %v", b)
109  		}
110  		result = append(result, charset[b])
111  	}
112  	return string(result), nil
113  }
114  
115  // For more details on the checksum calculation, please refer to BIP 173.
116  func bech32Checksum(hrp string, data []byte) []byte {
117  	// Convert the bytes to list of integers, as this is needed for the
118  	// checksum calculation.
119  	integers := make([]int, len(data))
120  	for i, b := range data {
121  		integers[i] = int(b)
122  	}
123  	values := append(bech32HrpExpand(hrp), integers...)
124  	values = append(values, []int{0, 0, 0, 0, 0, 0}...)
125  	polymod := bech32Polymod(values) ^ 1
126  	var res []byte
127  	for i := 0; i < 6; i++ {
128  		res = append(res, byte((polymod>>uint(5*(5-i)))&31))
129  	}
130  	return res
131  }
132  
133  // For more details on the polymod calculation, please refer to BIP 173.
134  func bech32Polymod(values []int) int {
135  	chk := 1
136  	for _, v := range values {
137  		b := chk >> 25
138  		chk = (chk&0x1ffffff)<<5 ^ v
139  		for i := 0; i < 5; i++ {
140  			if (b>>uint(i))&1 == 1 {
141  				chk ^= gen[i]
142  			}
143  		}
144  	}
145  	return chk
146  }
147  
148  // For more details on HRP expansion, please refer to BIP 173.
149  func bech32HrpExpand(hrp string) []int {
150  	v := make([]int, 0, len(hrp)*2+1)
151  	for i := 0; i < len(hrp); i++ {
152  		v = append(v, int(hrp[i]>>5))
153  	}
154  	v = append(v, 0)
155  	for i := 0; i < len(hrp); i++ {
156  		v = append(v, int(hrp[i]&31))
157  	}
158  	return v
159  }
160  
161  // For more details on the checksum verification, please refer to BIP 173.
162  func bech32VerifyChecksum(hrp string, data []byte) bool {
163  	integers := make([]int, len(data))
164  	for i, b := range data {
165  		integers[i] = int(b)
166  	}
167  	concat := append(bech32HrpExpand(hrp), integers...)
168  	return bech32Polymod(concat) == 1
169  }