forked from graham/python_xid
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbase32hex.py
More file actions
130 lines (98 loc) · 3 KB
/
base32hex.py
File metadata and controls
130 lines (98 loc) · 3 KB
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
129
130
# 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)