-
Notifications
You must be signed in to change notification settings - Fork 79
/
crypto.py
139 lines (107 loc) · 3.56 KB
/
crypto.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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:])
def a32_to_str(a):
return struct.pack('>%dI' % len(a), *a)
def aes_cbc_encrypt(data, key):
aes = AES.new(key, AES.MODE_CBC, '\0' * 16)
return aes.encrypt(data)
def aes_cbc_encrypt_a32(data, key):
return str_to_a32(aes_cbc_encrypt(a32_to_str(data), a32_to_str(key)))
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 aes_cbc_decrypt(data, key):
decryptor = AES.new(key, AES.MODE_CBC, '\0' * 16)
return decryptor.decrypt(data)
def aes_cbc_decrypt_a32(data, key):
return str_to_a32(aes_cbc_decrypt(a32_to_str(data), a32_to_str(key)))
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