github.com/gcash/bchutil@v0.0.0-20210113190856-6ea28dff4000/bech32/bech32.go (about) 1 // Copyright (c) 2017 The btcsuite developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package bech32 6 7 import ( 8 "fmt" 9 "strings" 10 ) 11 12 const charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" 13 14 var gen = []int{0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3} 15 16 // Decode decodes a bech32 encoded string, returning the human-readable 17 // part and the data part excluding the checksum. 18 func Decode(bech string) (string, []byte, error) { 19 // The maximum allowed length for a bech32 string is 90. It must also 20 // be at least 8 characters, since it needs a non-empty HRP, a 21 // separator, and a 6 character checksum. 22 if len(bech) < 8 || len(bech) > 90 { 23 return "", nil, fmt.Errorf("invalid bech32 string length %d", 24 len(bech)) 25 } 26 // Only ASCII characters between 33 and 126 are allowed. 27 for i := 0; i < len(bech); i++ { 28 if bech[i] < 33 || bech[i] > 126 { 29 return "", nil, fmt.Errorf("invalid character in "+ 30 "string: '%c'", bech[i]) 31 } 32 } 33 34 // The characters must be either all lowercase or all uppercase. 35 lower := strings.ToLower(bech) 36 upper := strings.ToUpper(bech) 37 if bech != lower && bech != upper { 38 return "", nil, fmt.Errorf("string not all lowercase or all " + 39 "uppercase") 40 } 41 42 // We'll work with the lowercase string from now on. 43 bech = lower 44 45 // The string is invalid if the last '1' is non-existent, it is the 46 // first character of the string (no human-readable part) or one of the 47 // last 6 characters of the string (since checksum cannot contain '1'), 48 // or if the string is more than 90 characters in total. 49 one := strings.LastIndexByte(bech, '1') 50 if one < 1 || one+7 > len(bech) { 51 return "", nil, fmt.Errorf("invalid index of 1") 52 } 53 54 // The human-readable part is everything before the last '1'. 55 hrp := bech[:one] 56 data := bech[one+1:] 57 58 // Each character corresponds to the byte with value of the index in 59 // 'charset'. 60 decoded, err := toBytes(data) 61 if err != nil { 62 return "", nil, fmt.Errorf("failed converting data to bytes: "+ 63 "%v", err) 64 } 65 66 if !bech32VerifyChecksum(hrp, decoded) { 67 moreInfo := "" 68 checksum := bech[len(bech)-6:] 69 expected, err := toChars(bech32Checksum(hrp, 70 decoded[:len(decoded)-6])) 71 if err == nil { 72 moreInfo = fmt.Sprintf("Expected %v, got %v.", 73 expected, checksum) 74 } 75 return "", nil, fmt.Errorf("checksum failed. " + moreInfo) 76 } 77 78 // We exclude the last 6 bytes, which is the checksum. 79 return hrp, decoded[:len(decoded)-6], nil 80 } 81 82 // Encode encodes a byte slice into a bech32 string with the 83 // human-readable part hrb. Note that the bytes must each encode 5 bits 84 // (base32). 85 func Encode(hrp string, data []byte) (string, error) { 86 // Calculate the checksum of the data and append it at the end. 87 checksum := bech32Checksum(hrp, data) 88 combined := append(data, checksum...) 89 90 // The resulting bech32 string is the concatenation of the hrp, the 91 // separator 1, data and checksum. Everything after the separator is 92 // represented using the specified charset. 93 dataChars, err := toChars(combined) 94 if err != nil { 95 return "", fmt.Errorf("unable to convert data bytes to chars: "+ 96 "%v", err) 97 } 98 return hrp + "1" + dataChars, nil 99 } 100 101 // toBytes converts each character in the string 'chars' to the value of the 102 // index of the correspoding character in 'charset'. 103 func toBytes(chars string) ([]byte, error) { 104 decoded := make([]byte, 0, len(chars)) 105 for i := 0; i < len(chars); i++ { 106 index := strings.IndexByte(charset, chars[i]) 107 if index < 0 { 108 return nil, fmt.Errorf("invalid character not part of "+ 109 "charset: %v", chars[i]) 110 } 111 decoded = append(decoded, byte(index)) 112 } 113 return decoded, nil 114 } 115 116 // toChars converts the byte slice 'data' to a string where each byte in 'data' 117 // encodes the index of a character in 'charset'. 118 func toChars(data []byte) (string, error) { 119 result := make([]byte, 0, len(data)) 120 for _, b := range data { 121 if int(b) >= len(charset) { 122 return "", fmt.Errorf("invalid data byte: %v", b) 123 } 124 result = append(result, charset[b]) 125 } 126 return string(result), nil 127 } 128 129 // ConvertBits converts a byte slice where each byte is encoding fromBits bits, 130 // to a byte slice where each byte is encoding toBits bits. 131 func ConvertBits(data []byte, fromBits, toBits uint8, pad bool) ([]byte, error) { 132 if fromBits < 1 || fromBits > 8 || toBits < 1 || toBits > 8 { 133 return nil, fmt.Errorf("only bit groups between 1 and 8 allowed") 134 } 135 136 // The final bytes, each byte encoding toBits bits. 137 var regrouped []byte 138 139 // Keep track of the next byte we create and how many bits we have 140 // added to it out of the toBits goal. 141 nextByte := byte(0) 142 filledBits := uint8(0) 143 144 for _, b := range data { 145 146 // Discard unused bits. 147 b = b << (8 - fromBits) 148 149 // How many bits remaining to extract from the input data. 150 remFromBits := fromBits 151 for remFromBits > 0 { 152 // How many bits remaining to be added to the next byte. 153 remToBits := toBits - filledBits 154 155 // The number of bytes to next extract is the minimum of 156 // remFromBits and remToBits. 157 toExtract := remFromBits 158 if remToBits < toExtract { 159 toExtract = remToBits 160 } 161 162 // Add the next bits to nextByte, shifting the already 163 // added bits to the left. 164 nextByte = (nextByte << toExtract) | (b >> (8 - toExtract)) 165 166 // Discard the bits we just extracted and get ready for 167 // next iteration. 168 b = b << toExtract 169 remFromBits -= toExtract 170 filledBits += toExtract 171 172 // If the nextByte is completely filled, we add it to 173 // our regrouped bytes and start on the next byte. 174 if filledBits == toBits { 175 regrouped = append(regrouped, nextByte) 176 filledBits = 0 177 nextByte = 0 178 } 179 } 180 } 181 182 // We pad any unfinished group if specified. 183 if pad && filledBits > 0 { 184 nextByte = nextByte << (toBits - filledBits) 185 regrouped = append(regrouped, nextByte) 186 filledBits = 0 187 nextByte = 0 188 } 189 190 // Any incomplete group must be <= 4 bits, and all zeroes. 191 if filledBits > 0 && (filledBits > 4 || nextByte != 0) { 192 return nil, fmt.Errorf("invalid incomplete group") 193 } 194 195 return regrouped, nil 196 } 197 198 // For more details on the checksum calculation, please refer to BIP 173. 199 func bech32Checksum(hrp string, data []byte) []byte { 200 // Convert the bytes to list of integers, as this is needed for the 201 // checksum calculation. 202 integers := make([]int, len(data)) 203 for i, b := range data { 204 integers[i] = int(b) 205 } 206 values := append(bech32HrpExpand(hrp), integers...) 207 values = append(values, []int{0, 0, 0, 0, 0, 0}...) 208 polymod := bech32Polymod(values) ^ 1 209 var res []byte 210 for i := 0; i < 6; i++ { 211 res = append(res, byte((polymod>>uint(5*(5-i)))&31)) 212 } 213 return res 214 } 215 216 // For more details on the polymod calculation, please refer to BIP 173. 217 func bech32Polymod(values []int) int { 218 chk := 1 219 for _, v := range values { 220 b := chk >> 25 221 chk = (chk&0x1ffffff)<<5 ^ v 222 for i := 0; i < 5; i++ { 223 if (b>>uint(i))&1 == 1 { 224 chk ^= gen[i] 225 } 226 } 227 } 228 return chk 229 } 230 231 // For more details on HRP expansion, please refer to BIP 173. 232 func bech32HrpExpand(hrp string) []int { 233 v := make([]int, 0, len(hrp)*2+1) 234 for i := 0; i < len(hrp); i++ { 235 v = append(v, int(hrp[i]>>5)) 236 } 237 v = append(v, 0) 238 for i := 0; i < len(hrp); i++ { 239 v = append(v, int(hrp[i]&31)) 240 } 241 return v 242 } 243 244 // For more details on the checksum verification, please refer to BIP 173. 245 func bech32VerifyChecksum(hrp string, data []byte) bool { 246 integers := make([]int, len(data)) 247 for i, b := range data { 248 integers[i] = int(b) 249 } 250 concat := append(bech32HrpExpand(hrp), integers...) 251 return bech32Polymod(concat) == 1 252 }