-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbinascii.py
113 lines (98 loc) · 3.51 KB
/
binascii.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
from ubinascii import *
if not "unhexlify" in globals():
def unhexlify(data):
if len(data) % 2 != 0:
raise ValueError("Odd-length string")
return bytes([ int(data[i:i+2], 16) for i in range(0, len(data), 2) ])
b2a_hex = hexlify
a2b_hex = unhexlify
# ____________________________________________________________
PAD = '='
table_a2b_base64 = [
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, # Note PAD->-1 here
-1, 0, 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,-1, -1,-1,-1,-1,
-1,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,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
]
def _transform(n):
if n == -1:
return '\xff'
else:
return chr(n)
table_a2b_base64 = ''.join(map(_transform, table_a2b_base64))
assert len(table_a2b_base64) == 256
def a2b_base64(ascii):
"Decode a line of base64 data."
res = []
quad_pos = 0
leftchar = 0
leftbits = 0
last_char_was_a_pad = False
for c in ascii:
c = chr(c)
if c == PAD:
if quad_pos > 2 or (quad_pos == 2 and last_char_was_a_pad):
break # stop on 'xxx=' or on 'xx=='
last_char_was_a_pad = True
else:
n = ord(table_a2b_base64[ord(c)])
if n == 0xff:
continue # ignore strange characters
#
# Shift it in on the low end, and see if there's
# a byte ready for output.
quad_pos = (quad_pos + 1) & 3
leftchar = (leftchar << 6) | n
leftbits += 6
#
if leftbits >= 8:
leftbits -= 8
res.append((leftchar >> leftbits).to_bytes(1, 'big'))
leftchar &= ((1 << leftbits) - 1)
#
last_char_was_a_pad = False
else:
if leftbits != 0:
raise Exception("Incorrect padding")
return b''.join(res)
# ____________________________________________________________
table_b2a_base64 = (
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
def b2a_base64(bin):
"Base64-code line of data."
newlength = (len(bin) + 2) // 3
newlength = newlength * 4 + 1
res = []
leftchar = 0
leftbits = 0
for c in bin:
# Shift into our buffer, and output any 6bits ready
leftchar = (leftchar << 8) | c
leftbits += 8
res.append(table_b2a_base64[(leftchar >> (leftbits-6)) & 0x3f])
leftbits -= 6
if leftbits >= 6:
res.append(table_b2a_base64[(leftchar >> (leftbits-6)) & 0x3f])
leftbits -= 6
#
if leftbits == 2:
res.append(table_b2a_base64[(leftchar & 3) << 4])
res.append(PAD)
res.append(PAD)
elif leftbits == 4:
res.append(table_b2a_base64[(leftchar & 0xf) << 2])
res.append(PAD)
res.append('\n')
return ''.join(res).encode('ascii')