eaapi/eaapi/crypt.py

51 lines
1.2 KiB
Python

import binascii
import hashlib
import time
import re
from Crypto.Cipher import ARC4
from .misc import assert_true
from .keys import EA_KEY
def new_prng():
state = 0x41c64e6d
while True:
x = (state * 0x838c9cda) + 0x6072
# state = (state * 0x41c64e6d + 0x3039)
# state = (state * 0x41c64e6d + 0x3039)
state = (state * 0xc2a29a69 + 0xd3dc167e) & 0xffffffff
yield (x & 0x7fff0000) | state >> 15 & 0xffff
prng = new_prng()
def validate_key(info):
match = re.match(r"^(\d)-([0-9a-f]{8})-([0-9a-f]{4})$", info)
assert_true(match is not None, "Invalid eamuse info key")
assert match is not None
version = match.group(1)
assert_true(version == "1", f"Unsupported encryption version ({version})")
seconds = binascii.unhexlify(match.group(2)) # 4 bytes
rng = binascii.unhexlify(match.group(3)) # 2 bytes
return seconds, rng
def get_key(prng_=None):
return f"1-{int(time.time()):08x}-{(next(prng_ or prng) & 0xffff):04x}"
def ea_symmetric_crypt(data, info):
seconds, rng = validate_key(info)
key = hashlib.md5(seconds + rng + EA_KEY).digest()
return ARC4.new(key).encrypt(data)
__all__ = ("new_prng", "prng", "validate_key", "get_key", "ea_symmetric_crypt")