fix: encryption IV is constant, and don't overwrite encryption IV with header IV.

This commit is contained in:
beerpsi 2024-07-22 13:48:20 +00:00
parent fcde905a13
commit e55107fe2a

View File

@ -22,6 +22,7 @@ from construct import (
# ---- Configuration # ---- Configuration
ENCRYPTION_KEY = bytes.fromhex("") ENCRYPTION_KEY = bytes.fromhex("")
ENCRYPTION_IV = bytes.fromhex("")
INPUT_FILE = "" # Should not be encrypted. INPUT_FILE = "" # Should not be encrypted.
OUTPUT_FILE = "" OUTPUT_FILE = ""
BOOTID = { BOOTID = {
@ -48,7 +49,9 @@ BOOTID = {
"unk2": 0, "unk2": 0,
"hw_family": b"ACA", "hw_family": b"ACA",
"hw_generation": 0, "hw_generation": 0,
"org_timestamp": {
# Fill in orig_timestamp/orig_version if you're making an app patch.
"orig_timestamp": {
"year": 0, "year": 0,
"month": 0, "month": 0,
"day": 0, "day": 0,
@ -57,11 +60,12 @@ BOOTID = {
"second": 0, "second": 0,
"milli": 0, "milli": 0,
}, },
"org_version": { "orig_version": {
"release": 0, "release": 0,
"minor": 0, "minor": 0,
"major": 0, "major": 0,
}, },
"os_version": { "os_version": {
"release": 1, "release": 1,
"minor": 54, "minor": 54,
@ -136,8 +140,8 @@ BootID = Struct(
"unk2" / Int64ul, "unk2" / Int64ul,
"hw_family" / Bytes(3), "hw_family" / Bytes(3),
"hw_generation" / Int8ul, "hw_generation" / Int8ul,
"org_timestamp" / Timestamp, "orig_timestamp" / Timestamp,
"org_version" / Version, "orig_version" / Version,
"os_version" / Version, "os_version" / Version,
"strings" / Bytes(0x27AC), "strings" / Bytes(0x27AC),
) )
@ -147,26 +151,19 @@ def get_page_iv(iv: bytes, offset: int):
return bytes(x ^ (offset >> (8 * (i % 8))) & 0xFF for (i, x) in enumerate(iv)) return bytes(x ^ (offset >> (8 * (i % 8))) & 0xFF for (i, x) in enumerate(iv))
iv = secrets.token_bytes(16)
if BOOTID["type"] == 0x02:
iv = bytes(x ^ EXFAT_HEADER[i] ^ OPTION_IV[i] for (i, x) in enumerate(iv))
print(f"Generated IV: {iv.hex()}")
filesize = os.stat(INPUT_FILE).st_size filesize = os.stat(INPUT_FILE).st_size
BOOTID["block_count"] = ceil(filesize / BOOTID["block_size"]) + 8 BOOTID["block_count"] = ceil(filesize / BOOTID["block_size"]) + 8
key = secrets.token_bytes(16) header_key = secrets.token_bytes(16)
iv = secrets.token_bytes(16) header_iv = secrets.token_bytes(16)
encrypted_keypair = PKCS1_OAEP.new(HEADER_META_PUBKEY).encrypt(key + iv) encrypted_keypair = PKCS1_OAEP.new(HEADER_META_PUBKEY).encrypt(header_key + header_iv)
header_meta = struct.pack("<Q", int(time.time())) + os.path.abspath(INPUT_FILE).encode( header_meta = struct.pack("<Q", int(time.time())) + os.path.abspath(INPUT_FILE).encode(
"utf-8" "utf-8"
) + b"\x00" ) + b"\x00"
header_meta += secrets.token_bytes( header_meta += secrets.token_bytes(
BOOTID["block_size"] - len(header_meta) - len(encrypted_keypair) BOOTID["block_size"] - len(header_meta) - len(encrypted_keypair)
) )
header_meta = encrypted_keypair + AES.new(key, AES.MODE_CBC, iv).encrypt(header_meta) header_meta = encrypted_keypair + AES.new(header_key, AES.MODE_CBC, header_iv).encrypt(header_meta)
header_meta_crc32 = zlib.crc32(header_meta) header_meta_crc32 = zlib.crc32(header_meta)
block_crc32s = [ block_crc32s = [
0, 0,
@ -201,7 +198,7 @@ with open(INPUT_FILE, "rb") as fin, open(OUTPUT_FILE, "w+b") as fout:
block_crc32 = 0 block_crc32 = 0
while to_read > 0: while to_read > 0:
page_iv = get_page_iv(iv, total_written) page_iv = get_page_iv(ENCRYPTION_IV, total_written)
contents = fin.read(4096) contents = fin.read(4096)
contents_len = len(contents) contents_len = len(contents)