Add HASHAB signing to iTunesCDB header + fix sync_itunescdb

- Set hashing_scheme=3 at offset 0x30 (iPod Nano 7G requirement)
- Compute and write HASHAB signature at offset 0xAB
- Import compute_hashab from hashab module
- iTunesCDB.ext creation restored (was removed accidentally)
- 0-byte iTunesDB placeholder (firmware expects this file)
This commit is contained in:
Maksim Totmin 2026-05-31 19:10:44 +07:00
parent 01902d252a
commit fba3fe7d05

View File

@ -1200,30 +1200,59 @@ class Nano7Database:
"""
import zlib
import re
from hashab import compute_hashab
# Read current Library.itdb
with open(self.sqlite_path, "rb") as f:
lib_data = f.read()
# Compute new SHA1 hash
# Compute new SHA1 hash of Library.itdb for iTunesCDB.ext
new_hash = hashlib.sha1(lib_data).hexdigest()
compressed = zlib.compress(lib_data)
total_size = 244 + len(compressed)
# Build proper mhfd header
# Build mhfd header
header = bytearray(244)
header[0:4] = b"mhfd"
struct.pack_into("<I", header, 4, 244)
struct.pack_into("<I", header, 8, total_size)
struct.pack_into("<I", header, 12, 0x00020002)
# Set hashing_scheme = 3 (HASHAB) at offset 0x30
struct.pack_into("<H", header, 0x30, 3)
# Build full iTunesCDB (header + compressed payload)
itdb_data = bytes(header) + compressed
# Compute HASHAB signature and write it at offset 0xAB
if self.firewire_id and len(self.firewire_id) >= 8:
try:
signature = compute_hashab(hashlib.sha1(itdb_data).digest(), self.firewire_id)
header[0xAB:0xAB + 57] = signature
itdb_data = bytes(header) + compressed
logger.info("HASHAB signature written to iTunesCDB header")
except Exception as e:
logger.warning("HASHAB signing failed for iTunesCDB: %s", e)
# Write new iTunesCDB
with open(self.cdb_path, "wb") as f:
f.write(bytes(header) + compressed)
f.write(itdb_data)
logger.info(f"Synced iTunesCDB: hash={new_hash}, compressed={len(compressed)} bytes")
# Update hash in iTunesCDB.ext
if not os.path.exists(self.cdb_ext_path):
ext_content = f"[iTunesCDB]\nitunesdb_hash={new_hash}\n"
else:
with open(self.cdb_ext_path, "r") as f:
ext_content = f.read()
new_ext_content = re.sub(r"itunesdb_hash=\w+", f"itunesdb_hash={new_hash}", ext_content)
with open(self.cdb_ext_path, "w") as f:
f.write(new_ext_content)
logger.info(f"Updated iTunesCDB.ext: hash={new_hash}")
def sync_locations_cbk(self):
"""Regenerate Locations.itdb.cbk with HASHAB-signed block checksums.