|
import base64 as b64 |
|
import hashlib |
|
import hmac |
|
import json |
|
import time |
|
|
|
from Crypto.Cipher import AES |
|
from Crypto.Util.Padding import pad, unpad |
|
import phpserialize |
|
|
|
|
|
def calc_mac(data, key): |
|
return hmac.new( |
|
key, (data["iv"] + data["value"]).encode(), digestmod=hashlib.sha256 |
|
).hexdigest() |
|
|
|
|
|
def decode(cookie, key): |
|
if isinstance(key, str) and key.startswith("base64:"): |
|
return decode(cookie, b64.b64decode(key.removeprefix("base64:"))) |
|
|
|
data = json.loads(b64.b64decode(cookie)) |
|
if calc_mac(data, key) != data["mac"]: |
|
print("WARNING", "mac was incorrect") |
|
|
|
iv, val = map(b64.b64decode, (data["iv"], data["value"])) |
|
|
|
c = AES.new(key=key, mode=AES.MODE_CBC, IV=iv) |
|
p = unpad(c.decrypt(val), 16) |
|
try: |
|
return phpserialize.loads(json.loads(p)["data"].encode()) |
|
except: |
|
return p |
|
|
|
|
|
def encode(plain, key): |
|
if isinstance(key, str) and key.startswith("base64:"): |
|
return encode(plain, b64.b64decode(key.removeprefix("base64:"))) |
|
|
|
c = AES.new(key=key, mode=AES.MODE_CBC) |
|
val = c.encrypt( |
|
pad( |
|
json.dumps( |
|
{ |
|
"data": phpserialize.dumps(plain).decode(), |
|
"expires": int(time.time() + 360000), |
|
} |
|
).encode(), |
|
16, |
|
) |
|
) |
|
data = { |
|
"iv": b64.b64encode(c.iv).decode(), |
|
"value": b64.b64encode(val).decode(), |
|
} |
|
data["mac"] = calc_mac(data, key) |
|
|
|
return b64.b64encode(json.dumps(data).encode()).decode() |
|
|
|
|
|
if __name__ == "__main__": |
|
import sys |
|
|
|
action, *args = sys.argv[1:] |
|
if action == "decode": |
|
print(decode(args[0], args[1])) |
|
if action == "encode": |
|
print(encode(json.loads(args[0]), args[1])) |