from Crypto.Cipher import AES import json import base64 import struct import binascii import random def aes_cbc_encrypt(data, key): aes_cipher = AES.new(key, AES.MODE_CBC, '\0' * 16) return aes_cipher.encrypt(data) def aes_cbc_decrypt(data, key): aes_cipher = AES.new(key, AES.MODE_CBC, '\0' * 16) return aes_cipher.decrypt(data) def aes_cbc_encrypt_a32(data, key): return str_to_a32(aes_cbc_encrypt(a32_to_str(data), a32_to_str(key))) def aes_cbc_decrypt_a32(data, key): return str_to_a32(aes_cbc_decrypt(a32_to_str(data), a32_to_str(key))) def stringhash(str, aeskey): s32 = str_to_a32(str) h32 = [0, 0, 0, 0] for i in range(len(s32)): h32[i % 4] ^= s32[i] for r in range(0x4000): h32 = aes_cbc_encrypt_a32(h32, aeskey) return a32_to_base64((h32[0], h32[2])) def prepare_key(arr): pkey = [0x93C467E3, 0x7DB0C7A4, 0xD1BE3F81, 0x0152CB56] for r in range(0x10000): for j in range(0, len(arr), 4): key = [0, 0, 0, 0] for i in range(4): if i + j < len(arr): key[i] = arr[i + j] pkey = aes_cbc_encrypt_a32(pkey, key) return pkey def encrypt_key(a, key): return sum( (aes_cbc_encrypt_a32(a[i:i + 4], key) for i in range(0, len(a), 4)), ()) def decrypt_key(a, key): return sum( (aes_cbc_decrypt_a32(a[i:i + 4], key) for i in range(0, len(a), 4)), ()) def encrypt_attr(attr, key): attr = 'MEGA' + json.dumps(attr) if len(attr) % 16: attr += '\0' * (16 - len(attr) % 16) return aes_cbc_encrypt(attr, a32_to_str(key)) def decrypt_attr(attr, key): attr = aes_cbc_decrypt(attr, a32_to_str(key)).rstrip('\0') return json.loads(attr[4:]) if attr[:6] == 'MEGA{"' else False def a32_to_str(a): return struct.pack('>%dI' % len(a), *a) def str_to_a32(b): if len(b) % 4: # pad to multiple of 4 b += '\0' * (4 - len(b) % 4) return struct.unpack('>%dI' % (len(b) / 4), b) def mpi_to_int(s): return int(binascii.hexlify(s[2:]), 16) def base64_url_decode(data): data += '=='[(2 - len(data) * 3) % 4:] for search, replace in (('-', '+'), ('_', '/'), (',', '')): data = data.replace(search, replace) return base64.b64decode(data) def base64_to_a32(s): return str_to_a32(base64_url_decode(s)) def base64_url_encode(data): data = base64.b64encode(data) for search, replace in (('+', '-'), ('/', '_'), ('=', '')): data = data.replace(search, replace) return data def a32_to_base64(a): return base64_url_encode(a32_to_str(a)) def get_chunks(size): chunks = {} p = pp = 0 i = 1 while i <= 8 and p < size - i * 0x20000: chunks[p] = i * 0x20000 pp = p p += chunks[p] i += 1 while p < size: chunks[p] = 0x100000 pp = p p += chunks[p] chunks[pp] = size - pp if not chunks[pp]: del chunks[pp] return chunks # more general functions def make_id(length): text = '' possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" for i in range(length): text += random.choice(possible) return text