from binascii import unhexlify B64_ALPHABET list ABCDEFGHIJKLMNOPQRST

 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
from binascii import unhexlify
B64_ALPHABET = list(
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
)
def hex_to_b64(val_hex):
val_bytes = unhexlify(val_hex)
print('|'.join((format(x, '08b') for x in val_bytes)))
len_bytes = len(val_bytes)
len_bits = len_bytes * 8
b64_digits = []
for idx in range(0, len_bits, 6):
print('----------- idx=%d' % idx)
# first take two bytes, `start` bit is placed
# in first of two bytes
byte_start, tail = divmod(idx, 8)
print('byte start', byte_start, 'tail', tail)
num_bytes = val_bytes[byte_start:byte_start + 2]
print('len:num_bytes', len(num_bytes))
if len(num_bytes) == 1:
num = int.from_bytes(num_bytes, 'big') << 8
else:
num = int.from_bytes(num_bytes, 'big')
print('NUM', num, 'as bits', format(num, '016b'))
# clear left bits
start_in_byte = idx % 8
print('start in byte', start_in_byte)
num = (num << start_in_byte) % (2**16)
print('shifted left', num, 'as bits', format(num, '016b'))
num = num >> start_in_byte
print('shifted back', num, 'as bits', format(num, '016b'))
# move right
num = num >> (10 - start_in_byte)
print('result num', num, 'as bits', format(num, '016b'))
char = B64_ALPHABET[num]
print('result b64 char: [%s]' % char)
b64_digits.append(char)
return ''.join(b64_digits)
def main():
val_hex = '49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d'
val_b64 = 'SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t'
calc_b64 = hex_to_b64(val_hex)
print('Calculated b64', calc_b64)
assert calc_b64 == val_b64
if __name__ == '__main__':
main()