2022-11-17 01:56:45 +00:00
|
|
|
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")
|