github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/lib/others/bech32/bech32.go (about) 1 package bech32 2 3 import ( 4 "bytes" 5 ) 6 7 func bech32_polymod_step(pre uint32) uint32 { 8 b := uint32(pre >> 25) 9 return ((pre & 0x1FFFFFF) << 5) ^ 10 (-((b >> 0) & 1) & 0x3b6a57b2) ^ 11 (-((b >> 1) & 1) & 0x26508e6d) ^ 12 (-((b >> 2) & 1) & 0x1ea119fa) ^ 13 (-((b >> 3) & 1) & 0x3d4233dd) ^ 14 (-((b >> 4) & 1) & 0x2a1462b3) 15 } 16 17 func bech32_final_constant(bech32m bool) uint32 { 18 if bech32m { 19 return 0x2bc830a3 20 } 21 return 1 22 } 23 24 const ( 25 charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" 26 ) 27 28 var ( 29 charset_rev = [128]byte{ 30 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 31 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 32 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 33 15, 99, 10, 17, 21, 20, 26, 30, 7, 5, 99, 99, 99, 99, 99, 99, 34 99, 29, 99, 24, 13, 25, 9, 8, 23, 99, 18, 22, 31, 27, 19, 99, 35 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, 99, 99, 99, 99, 99, 36 99, 29, 99, 24, 13, 25, 9, 8, 23, 99, 18, 22, 31, 27, 19, 99, 37 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, 99, 99, 99, 99, 99} 38 ) 39 40 // Encode returns an empty string on error. 41 func Encode(hrp string, data []byte, bech32m bool) string { 42 var chk uint32 = 1 43 var i int 44 output := new(bytes.Buffer) 45 for i = range hrp { 46 ch := int(hrp[i]) 47 if ch < 33 || ch > 126 { 48 return "" 49 } 50 51 if ch >= 'A' && ch <= 'Z' { 52 return "" 53 } 54 chk = bech32_polymod_step(chk) ^ (uint32(ch) >> 5) 55 i++ 56 } 57 if i+7+len(data) > 90 { 58 return "" 59 } 60 chk = bech32_polymod_step(chk) 61 for i := range hrp { 62 tmp := hrp[i] 63 chk = bech32_polymod_step(chk) ^ uint32(tmp&0x1f) 64 output.WriteByte(tmp) 65 } 66 output.WriteByte('1') 67 68 for i = range data { 69 if (data[i] >> 5) != 0 { 70 return "" 71 } 72 chk = bech32_polymod_step(chk) ^ uint32(data[i]) 73 output.WriteByte(charset[data[i]]) 74 } 75 for i = 0; i < 6; i++ { 76 chk = bech32_polymod_step(chk) 77 } 78 chk ^= bech32_final_constant(bech32m) 79 for i = 0; i < 6; i++ { 80 output.WriteByte(charset[(chk>>uint((5-i)*5))&0x1f]) 81 } 82 return output.String() 83 } 84 85 // Decode returns ("", nil) on error. 86 func Decode(input string) (res_hrp string, res_data []byte, bech32m bool) { 87 var chk uint32 = 1 88 var i, data_len, hrp_len int 89 var have_lower, have_upper bool 90 if len(input) < 8 || len(input) > 90 { 91 return 92 } 93 for data_len < len(input) && input[(len(input)-1)-data_len] != '1' { 94 data_len++ 95 } 96 hrp_len = len(input) - (1 + data_len) 97 if hrp_len < 1 || data_len < 6 { 98 return 99 } 100 data_len -= 6 101 hrp := make([]byte, hrp_len) 102 data := make([]byte, data_len) 103 for i = 0; i < hrp_len; i++ { 104 ch := input[i] 105 if ch < 33 || ch > 126 { 106 return 107 } 108 if ch >= 'a' && ch <= 'z' { 109 have_lower = true 110 } else if ch >= 'A' && ch <= 'Z' { 111 have_upper = true 112 ch = (ch - 'A') + 'a' 113 } 114 hrp[i] = ch 115 chk = bech32_polymod_step(chk) ^ uint32(ch>>5) 116 } 117 chk = bech32_polymod_step(chk) 118 for i = 0; i < hrp_len; i++ { 119 chk = bech32_polymod_step(chk) ^ uint32(input[i]&0x1f) 120 } 121 i++ 122 for i < len(input) { 123 if (input[i] & 0x80) != 0 { 124 return 125 } 126 v := charset_rev[(input[i])] 127 if v > 31 { 128 return 129 } 130 if input[i] >= 'a' && input[i] <= 'z' { 131 have_lower = true 132 } 133 if input[i] >= 'A' && input[i] <= 'Z' { 134 have_upper = true 135 } 136 chk = bech32_polymod_step(chk) ^ uint32(v) 137 if i+6 < len(input) { 138 data[i-(1+hrp_len)] = v 139 } 140 i++ 141 } 142 if have_lower && have_upper { 143 return 144 } 145 if chk == bech32_final_constant(false) { 146 res_hrp = string(hrp) 147 res_data = data 148 } else if chk == bech32_final_constant(true) { 149 res_hrp = string(hrp) 150 res_data = data 151 bech32m = true 152 } 153 return 154 }