-
Notifications
You must be signed in to change notification settings - Fork 9
/
base64_decode.py
55 lines (43 loc) · 1.44 KB
/
base64_decode.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
#! /usr/bin/python3
#
# Decode base64 manually. Written by davidhcefx, 2020.7.27.
import readline
from sys import stderr
from string import ascii_uppercase, ascii_lowercase, digits
CHARSET = ascii_uppercase + ascii_lowercase + digits + '+/' # length: 64
TABLE = {ch: '{:0>6}'.format(bin(i)[2:]) for i, ch in enumerate(CHARSET)}
def warn(msg: str):
print('Warning: {}'.format(msg), file=stderr)
def valid_check(binary: str, paddings: int):
if (len(binary) + paddings * 6) % 24 != 0:
warn('Input length incorrect!')
return
if paddings == 1: # 16 bits
if binary[-2:] != '00':
warn('Malformed encoding. (1)')
elif paddings == 2: # 8 bits
if binary[-4:] != '0000':
warn('Malformed encoding. (2)')
elif paddings >= 3:
warn('Too many paddings!')
def main():
s = input().strip()
binary = ''.join(map(TABLE.get, s.strip('=')))
# discard any remainders
hex_code = list(map(
lambda b: hex(int(b, 2)),
filter(
lambda b: len(b) == 8,
(binary[i:i+8] for i in range(0, len(binary), 8)))))
text = ''.join(map(lambda h: chr(int(h, 16)), hex_code))
print('hex:', hex_code)
print('ascii:', text)
valid_check(binary, s.count('=', -3))
if __name__ == '__main__':
main()
### Examples:
# - BA== (correct)
# - BA (no padding)
# - B/== (wrong encoding)
### Update log:
# - 8/14 rewrite with functions, constant table lookup