-
Notifications
You must be signed in to change notification settings - Fork 25
/
base32hex.py
128 lines (98 loc) · 3 KB
/
base32hex.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# implementation of RFC 4648 using extended hex alphabet
# https://tools.ietf.org/html/rfc4648#page-10
# Used by golang in a number of places but doesn't seem to
# exist in the python standard library.
encodeHex = "0123456789ABCDEFGHIJKLMNOPQRSTUV"
decodeHexMap = {}
for index, i in enumerate(encodeHex):
decodeHexMap[i] = index
padChar = "="
class BadPadding(Exception):
pass
def encode(src, str_map):
dst = []
src_len = 0
if len(src) == 0:
return ''
while len(src):
src_len = len(src)
next_byte = [0] * 8
if src_len > 4:
next_byte[7] = src[4] & 0x1f
next_byte[6] = src[4] >> 5
if src_len > 3:
next_byte[6] = next_byte[6] | (src[3] << 3) & 0x1f
next_byte[5] = (src[3] >> 2) & 0x1f
next_byte[4] = src[3] >> 7
if src_len > 2:
next_byte[4] = next_byte[4] | (src[2] << 1) & 0x1f
next_byte[3] = (src[2] >> 4) & 0x1f
if src_len > 1:
next_byte[3] = next_byte[3] | (src[1] << 4) & 0x1f
next_byte[2] = (src[1] >> 1) & 0x1f
next_byte[1] = (src[1] >> 6) & 0x1f
if src_len > 0:
next_byte[1] = next_byte[1] | (src[0] << 2) & 0x1f
next_byte[0] = src[0] >> 3
for nb in next_byte:
dst.append(str_map[nb])
src = src[5:]
if src_len < 5:
dst[-1] = '='
if src_len < 4:
dst[-2] = '='
dst[-3] = '='
if src_len < 3:
dst[-4] = '='
if src_len < 2:
dst[-5] = '='
dst[-6] = '='
return ''.join(dst)
def decode(src, str_map):
src = src.upper()
end = False
result = []
while len(src) > 0 and not end:
dst = [0] * 5
dbuf = [0] * 8
src_len = 8
for i in range(0, 8):
if i >= len(src):
src_len = i
end = True
break
char = src[i]
if char == padChar:
end = True
src_len = i
break
else:
dbuf[i] = decodeHexMap[char]
if src_len >= 8:
dst[4] = (dbuf[6] << 5) | (dbuf[7])
if src_len >= 7:
dst[3] = (dbuf[4] << 7) | (dbuf[5] << 2) | (dbuf[6] >> 3)
if src_len >= 5:
dst[2] = (dbuf[3] << 4) | (dbuf[4] >> 1)
if src_len >= 4:
dst[1] = (dbuf[1] << 6) | (dbuf[2] << 1) | (dbuf[3] >> 4)
if src_len >= 2:
dst[0] = (dbuf[0] << 3) | (dbuf[1] >> 2)
dst = list(map(lambda x: x & 0xff, dst))
if src_len == 2:
dst = dst[:1]
elif src_len == 4:
dst = dst[:2]
elif src_len == 5:
dst = dst[:3]
elif src_len == 7:
dst = dst[:4]
elif src_len == 8:
dst = dst[:5]
result.extend(dst)
src = src[8:]
return result
def b32encode(src):
return encode(list(map(ord, src)), encodeHex)
def b32decode(src):
return decode(src, encodeHex)