diff options
Diffstat (limited to 'samloader/crypt.py')
-rw-r--r-- | samloader/crypt.py | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/samloader/crypt.py b/samloader/crypt.py new file mode 100644 index 0000000..d5cf6de --- /dev/null +++ b/samloader/crypt.py @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-3.0+ +# Copyright (C) 2020 Nayil Mukhametshin + +# Calculate keys and decrypt encrypted firmware packages. + +import hashlib +import xml.etree.ElementTree as ET +from Crypto.Cipher import AES +from clint.textui import progress + +from . import request +from . import fusclient +from . import versionfetch + +unpad = lambda d: d[:-d[-1]] + +def getv4key(version, model, region): + client = fusclient.FUSClient() + req = request.binaryinform(version, region, model, client.nonce) + resp = client.makereq("NF_DownloadBinaryInform.do", req) + root = ET.fromstring(resp) + logicval = root.find("./FUSBody/Put/LOGIC_VALUE_FACTORY/Data").text + deckey = request.getlogiccheck(version, logicval) + return hashlib.md5(deckey.encode()).digest() + +def getv2key(version, model, region): + deckey = region + ":" + model + ":" + version + return hashlib.md5(deckey.encode()).digest() + +def decrypt_progress(inf, outf, key, length): + cipher = AES.new(key, AES.MODE_ECB) + assert length % 16 == 0 + chunks = length//4096+1 + for i in progress.bar(range(chunks)): + block = inf.read(4096) + if not block: + break + decblock = cipher.decrypt(block) + if i == chunks - 1: + outf.write(unpad(decblock)) + else: + outf.write(decblock) |