pub struct ApModel { /* private fields */ }Expand description
AP deobfuscation model for a single SA17 page-store file.
Build one with ApModel::learn, then call ApModel::deobfuscate
to recover plaintext for any page.
The model is cheap to clone; it stores at most one u8 per 16-page block.
Implementations§
Source§impl ApModel
impl ApModel
Sourcepub fn learn(store: &PageStore) -> Self
pub fn learn(store: &PageStore) -> Self
Construct an ApModel by scanning every pure-AP page in store.
Pure-AP page types — '@', 'C', 'H', 'M' — have bodies
dominated by the AP fill (sectors 1..6 are almost entirely fill).
From those sectors we can back-calculate bv(block) precisely.
Pages of other types, whose plaintext is dense, contribute nothing to the calibration. At least one pure-AP page must exist in the store (SA17 files always have some).
Sourcepub fn bv_at(&self, bi: u64) -> u8
pub fn bv_at(&self, bi: u64) -> u8
Return the bv for block bi, falling back to bv0 for unknown blocks.
For files where every block has at least one pure-AP page, every block
will be in bv_map. For the rare blocks that lack one, bv0 is used
(an approximation that degrades gracefully).
Sourcepub fn deobfuscate(&self, raw: &[u8], pn: u64) -> Vec<u8> ⓘ
pub fn deobfuscate(&self, raw: &[u8], pn: u64) -> Vec<u8> ⓘ
Deobfuscate a full 4 KiB page.
pn is the zero-based page index within the store.
The page trailer (0xFF0..0xFFC) and CRC footer (0xFFC..0x1000) are
copied verbatim; they are stored in plaintext and must not be modified.
For blocks whose bv was not learned from a pure-AP page this falls
back to bv0. Use ApModel::deobfuscate_with_store to get the
correct bv for every block.
Sourcepub fn learned_block_count(&self) -> usize
pub fn learned_block_count(&self) -> usize
Number of blocks for which bv was directly learned from a pure-AP page.
Sourcepub fn recover_bv_for_block(&self, store: &PageStore, bi: u64) -> u8
pub fn recover_bv_for_block(&self, store: &PageStore, bi: u64) -> u8
Brute-force recover bv for a block that has no pure-AP page.
For each candidate bv (0..=255), score it by computing the peak of the
histogram of (stored[i] - (pn + si - bias) - i*step) mod 256 for each
candidate step, then summing the best-step peak across all sectors of up
to 3 sample pages in the block. The candidate with the highest total
score is returned.
The algorithm matches APModel._recover_bv_for_block in the Python
reference implementation. At ~2.7 M arithmetic ops per block it is fast
in release mode (< 2 ms on modern hardware).
Sourcepub fn deobfuscate_with_store(
&self,
raw: &[u8],
pn: u64,
store: &PageStore,
) -> Vec<u8> ⓘ
pub fn deobfuscate_with_store( &self, raw: &[u8], pn: u64, store: &PageStore, ) -> Vec<u8> ⓘ
Deobfuscate a full 4 KiB page, recovering the block’s bv from the
store on demand if it was not learned from pure-AP pages.
Use this variant when you need accurate deobfuscation for blocks that have no pure-AP pages (which is the common case for dense data blocks that consist entirely of ‘E’-type pages).