bech32.go raw

   1  // Package bech32 encodes and decodes segwit addresses.
   2  //
   3  // It implements only the part a swap wallet needs: P2WPKH and P2WSH, which are witness
   4  // version 0 and therefore the original BIP173 checksum. A future witness version needs the
   5  // BIP350 checksum instead, so this package refuses any version but 0 rather than encoding
   6  // an address another wallet would reject.
   7  package bech32
   8  
   9  import (
  10  	"fmt"
  11  	"strings"
  12  )
  13  
  14  // charset is the bech32 alphabet, in the order the checksum depends on.
  15  const charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
  16  
  17  // reverse maps a character to its value, built once.
  18  var reverse = func() map[byte]int {
  19  	out := make(map[byte]int, len(charset))
  20  
  21  	for i := 0; i < len(charset); i++ {
  22  		out[charset[i]] = i
  23  	}
  24  
  25  	return out
  26  }()
  27  
  28  // generator holds the bech32 checksum constants.
  29  var generator = [5]uint32{0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3}
  30  
  31  // polymod is the bech32 checksum function.
  32  func polymod(values []int) uint32 {
  33  	checksum := uint32(1)
  34  
  35  	for _, value := range values {
  36  		top := checksum >> 25
  37  		checksum = (checksum&0x1ffffff)<<5 ^ uint32(value)
  38  
  39  		for i := 0; i < 5; i++ {
  40  			if (top>>uint(i))&1 == 1 {
  41  				checksum ^= generator[i]
  42  			}
  43  		}
  44  	}
  45  
  46  	return checksum
  47  }
  48  
  49  // expandHRP spreads the human-readable part into the values the checksum covers.
  50  func expandHRP(hrp string) []int {
  51  	out := make([]int, 0, len(hrp)*2+1)
  52  
  53  	for i := 0; i < len(hrp); i++ {
  54  		out = append(out, int(hrp[i])>>5)
  55  	}
  56  
  57  	out = append(out, 0)
  58  
  59  	for i := 0; i < len(hrp); i++ {
  60  		out = append(out, int(hrp[i])&31)
  61  	}
  62  
  63  	return out
  64  }
  65  
  66  // convertBits regroups a byte slice into 5-bit groups, or back.
  67  func convertBits(data []byte, from, to uint, pad bool) ([]int, error) {
  68  	acc := uint32(0)
  69  	bits := uint(0)
  70  	maxValue := uint32(1)<<to - 1
  71  
  72  	var out []int
  73  
  74  	for _, value := range data {
  75  		if uint32(value)>>from != 0 {
  76  			return nil, fmt.Errorf("value %d does not fit in %d bits", value, from)
  77  		}
  78  
  79  		acc = acc<<from | uint32(value)
  80  		bits += from
  81  
  82  		for bits >= to {
  83  			bits -= to
  84  			out = append(out, int((acc>>bits)&maxValue))
  85  		}
  86  	}
  87  
  88  	if pad {
  89  		if bits > 0 {
  90  			out = append(out, int((acc<<(to-bits))&maxValue))
  91  		}
  92  
  93  		return out, nil
  94  	}
  95  
  96  	if bits >= from {
  97  		return nil, fmt.Errorf("excess padding")
  98  	}
  99  
 100  	if (acc<<(to-bits))&maxValue != 0 {
 101  		return nil, fmt.Errorf("non-zero padding")
 102  	}
 103  
 104  	return out, nil
 105  }
 106  
 107  // Encode turns a human-readable part and a payload into a bech32 string with the BIP173
 108  // checksum.
 109  func Encode(hrp string, data []int) (string, error) {
 110  	if hrp == "" {
 111  		return "", fmt.Errorf("a bech32 string needs a human-readable part")
 112  	}
 113  
 114  	for i := 0; i < len(hrp); i++ {
 115  		if hrp[i] < 33 || hrp[i] > 126 {
 116  			return "", fmt.Errorf("the human-readable part contains %q", hrp[i])
 117  		}
 118  
 119  		if hrp[i] >= 'A' && hrp[i] <= 'Z' {
 120  			return "", fmt.Errorf("the human-readable part must be lowercase")
 121  		}
 122  	}
 123  
 124  	values := append(expandHRP(hrp), data...)
 125  	values = append(values, 0, 0, 0, 0, 0, 0)
 126  
 127  	checksum := polymod(values) ^ 1
 128  
 129  	var out strings.Builder
 130  
 131  	out.WriteString(hrp)
 132  	out.WriteByte('1')
 133  
 134  	for _, value := range data {
 135  		out.WriteByte(charset[value])
 136  	}
 137  
 138  	for i := 0; i < 6; i++ {
 139  		out.WriteByte(charset[(checksum>>uint(5*(5-i)))&31])
 140  	}
 141  
 142  	return out.String(), nil
 143  }
 144  
 145  // Decode splits a bech32 string into its human-readable part and payload values.
 146  func Decode(text string) (string, []int, error) {
 147  	if len(text) < 8 {
 148  		return "", nil, fmt.Errorf("a bech32 string is at least 8 characters")
 149  	}
 150  
 151  	if len(text) > 90 {
 152  		return "", nil, fmt.Errorf("a bech32 address is at most 90 characters, not %d",
 153  			len(text))
 154  	}
 155  
 156  	// Mixed case is not valid: the checksum is defined over one case, and accepting both
 157  	// would let two different strings be the same address.
 158  	lower := strings.ToLower(text)
 159  
 160  	if lower != text && strings.ToUpper(text) != text {
 161  		return "", nil, fmt.Errorf("a bech32 string may not mix upper and lower case")
 162  	}
 163  
 164  	text = lower
 165  
 166  	separator := strings.LastIndexByte(text, '1')
 167  
 168  	if separator < 1 || separator+7 > len(text) {
 169  		return "", nil, fmt.Errorf("a bech32 string needs a separator and a checksum")
 170  	}
 171  
 172  	hrp := text[:separator]
 173  	data := make([]int, 0, len(text)-separator-1)
 174  
 175  	for i := separator + 1; i < len(text); i++ {
 176  		value, ok := reverse[text[i]]
 177  
 178  		if !ok {
 179  			return "", nil, fmt.Errorf("%q is not a bech32 character", text[i])
 180  		}
 181  
 182  		data = append(data, value)
 183  	}
 184  
 185  	if polymod(append(expandHRP(hrp), data...)) != 1 {
 186  		return "", nil, fmt.Errorf("the bech32 checksum does not match")
 187  	}
 188  
 189  	return hrp, data[:len(data)-6], nil
 190  }
 191  
 192  // EncodeSegwit builds a witness version 0 address: P2WPKH for a 20-byte program, P2WSH for
 193  // a 32-byte one.
 194  func EncodeSegwit(hrp string, version byte, program []byte) (string, error) {
 195  	if version != 0 {
 196  		return "", fmt.Errorf(
 197  			"this wallet encodes witness version 0 only; version %d needs the BIP350 "+
 198  				"checksum", version,
 199  		)
 200  	}
 201  
 202  	if len(program) != 20 && len(program) != 32 {
 203  		return "", fmt.Errorf(
 204  			"a witness version 0 program is 20 or 32 bytes, not %d", len(program),
 205  		)
 206  	}
 207  
 208  	grouped, err := convertBits(program, 8, 5, true)
 209  
 210  	if err != nil {
 211  		return "", err
 212  	}
 213  
 214  	return Encode(hrp, append([]int{int(version)}, grouped...))
 215  }
 216  
 217  // DecodeSegwit reads a witness address and returns its version and program.
 218  func DecodeSegwit(address string) (string, byte, []byte, error) {
 219  	hrp, data, err := Decode(address)
 220  
 221  	if err != nil {
 222  		return "", 0, nil, err
 223  	}
 224  
 225  	if len(data) < 1 {
 226  		return "", 0, nil, fmt.Errorf("the address has no witness version")
 227  	}
 228  
 229  	if data[0] != 0 {
 230  		return "", 0, nil, fmt.Errorf(
 231  			"this wallet reads witness version 0 only; the address is version %d", data[0],
 232  		)
 233  	}
 234  
 235  	program, err := convertBits(intsToBytes(data[1:]), 5, 8, false)
 236  
 237  	if err != nil {
 238  		return "", 0, nil, err
 239  	}
 240  
 241  	if len(program) != 20 && len(program) != 32 {
 242  		return "", 0, nil, fmt.Errorf("the witness program is %d bytes", len(program))
 243  	}
 244  
 245  	out := make([]byte, len(program))
 246  
 247  	for i, value := range program {
 248  		out[i] = byte(value)
 249  	}
 250  
 251  	return hrp, 0, out, nil
 252  }
 253  
 254  // intsToBytes narrows the 5-bit values into a byte slice.
 255  func intsToBytes(values []int) []byte {
 256  	out := make([]byte, len(values))
 257  
 258  	for i, value := range values {
 259  		out[i] = byte(value)
 260  	}
 261  
 262  	return out
 263  }
 264