Created
August 31, 2017 12:19
-
-
Save j178/eb33cddcdd4348e76684aa4d1d64910f to your computer and use it in GitHub Desktop.
Reinvent the wheel: implemente base64 encoding and decoing in Python.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CHARS = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' | |
NUMS = [62, 0, 0, 0, 63, | |
*range(52, 62), | |
0, 0, 0, 0, 0, 0, 0, | |
*range(26), | |
0, 0, 0, 0, 0, 0, | |
*range(26, 52)] | |
def to_val(c): | |
return NUMS[c - ord('+')] | |
def group(s, step): | |
i = 0 | |
while i + step < len(s): | |
yield s[i:i + step] | |
i += step | |
yield list(s[i:]) + [0 for _ in range(i + step - len(s))] | |
def base64_encode(s): | |
rv = [] | |
for i, j, k in group(s, 3): | |
a = i >> 2 | |
b = ((i & 0b11) << 4) + (j >> 4) | |
c = ((j & 0b1111) << 2) + (k >> 6) | |
d = k & 0b111111 | |
rv.extend([CHARS[a], CHARS[b], CHARS[c], CHARS[d]]) | |
# 最后的 A 或者 AA 需要替换为 = | |
# 如果 Base64 编码字符串不会相互拼接在传输,最后的=也可以省略。 | |
# 在解码时发现长度不能被4整除,则先补充=号,再解码。 | |
if len(s) % 3: | |
for i in range(3 - len(s) % 3): | |
rv[-(i + 1)] = ord('=') | |
return bytes(rv) | |
def base64_decode(s): | |
nequal = len(s) - s.find(b'=') | |
rv = [] | |
for a, b, c, d in group(s, 4): | |
a, b, c, d = to_val(a), to_val(b), to_val(c), to_val(d) | |
i = (a << 2) + (b >> 4) | |
j = ((b & 0b1111) << 4) + (c >> 2) | |
k = ((c & 0b11) << 6) + d | |
rv.extend([i, j, k]) | |
for _ in range(nequal): | |
rv.pop() | |
return bytes(rv) | |
if __name__ == '__main__': | |
print(base64_decode(b'YQ==')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment