Deployed b30e6d7 with MkDocs version: 1.6.1

This commit is contained in:
2026-09-18 14:57:39 +00:00
parent 1c7509aa8d
commit 41956b3027
3 changed files with 9 additions and 7 deletions
+2 -2
View File
@@ -2401,10 +2401,10 @@
</ul>
<p>unshackle pushes keys from every source, not only a local CDM. A run against a remote server that licenses with its own CDM (<code>--remote</code>) writes the keys the server returns, and <code>unshackle import</code> writes the keys it reads from an export file.</p>
<h3 id="wrong-keys-from-a-poisoned-vault">Wrong keys from a poisoned vault<a class="headerlink" href="#wrong-keys-from-a-poisoned-vault" title="Permanent link">&para;</a></h3>
<p>A public vault can return the right KID with a wrong content key. The decrypters accept a wrong content key and write noise. unshackle therefore trusts a content key from a vault only after FFmpeg decodes the first seconds of the decrypted track with strict error detection. Content keys from a licence skip this check. A file this FFmpeg build cannot judge counts as a pass, never as a wrong content key: a codec it has no decoder for, or a header it cannot read. Without FFmpeg there is no check at all.</p>
<p>A public vault can return the right KID with a wrong content key. The decrypters accept a wrong content key and write noise. unshackle therefore trusts a content key from a vault only after FFmpeg decodes the decrypted track with strict error detection. For a fragmented MP4, unshackle reads from the encrypted file which fragments each KID encrypts, and FFmpeg decodes up to three windows of each KID: from its first, middle and last fragment on through the next fragments of that KID, for up to 10 seconds. A window never runs into a fragment of another KID or a clear fragment. A clear lead or a lead under another KID therefore cannot hide a wrong content key, and only the KID that fails is flagged. A KID that is not in this map, and every KID of any other file, gets one check of the whole file. FFmpeg decodes the first seconds and the last seconds. A failure there flags each of those KIDs. Content keys from a licence skip this check. A file this FFmpeg build cannot judge counts as a pass, never as a wrong content key: a codec it has no decoder for, or a header it cannot read. Without FFmpeg there is no check at all.</p>
<p>When the decode fails, unshackle:</p>
<ol>
<li>Flags the KID:KEY in the <code>bad_keys</code> table of every local SQLite vault, with the service and the name of the vault it came from. The pair also goes out of the service table, except in a vault marked <code>no_push</code>, where only the flag is written.</li>
<li>Flags the KID:KEY in the <code>bad_keys</code> table of every local SQLite vault, with the service and the name of the vault it came from. The pair also goes out of the service table, except in a vault marked <code>no_push</code>, where only the flag is written. A flagged pair cannot go back into a local vault, from a later run or from <code>kv copy</code>. An <code>API</code> vault that served the pair also gets a report; <code>HTTP</code> and <code>MySQL</code> vaults have no report route. A pair from a local vault goes to no remote vault, even when a remote vault holds the same pair.</li>
<li>Restores the ciphertext from a hard link it made before decryption, then asks for the content key again. Every vault lookup skips a flagged pair, so the request reaches the remaining vaults and then the CDM. A remote answer that arrived after the winning one is reused instead of queried again.</li>
<li>Removes the flag when the CDM returns the same content key, because then the decode check was wrong, not the content key. A content key from another vault is checked in its turn, and flagged as well if it also fails.</li>
</ol>
+6 -4
View File
@@ -2096,10 +2096,12 @@ name) and a <code>name</code>, plus backend-specific keys.</p>
</div>
<div class="admonition note">
<p class="admonition-title">Bad content keys</p>
<p>A content key from a vault is proven by a short FFmpeg decode of the decrypted output.
A content key that fails the decode is written to the <code>bad_keys</code> table of every <code>SQLite</code>
vault with the name of the vault that supplied it, and every vault lookup skips a flagged
pair from then on. Only the <code>SQLite</code> backend stores flags. A <code>serve</code> instance with
<p>A content key from a vault is proven by short FFmpeg decodes of the decrypted output,
with windows inside the fragments of each KID in a fragmented MP4. A content key that
fails the decode is written to the <code>bad_keys</code> table of every <code>SQLite</code> vault with the name
of the vault that supplied it, and every vault lookup skips a flagged pair from then on. A <code>SQLite</code> vault also refuses to
store a flagged pair again. Only the <code>SQLite</code> backend stores flags; an <code>API</code> vault that
supplied the pair gets a report. A <code>serve</code> instance with
<code>server_cdm</code> flags a pair the same way when a remote client reports it, so a server whose
<code>key_vaults</code> hold no <code>SQLite</code> entry cannot remember a bad content key.</p>
</div>
File diff suppressed because one or more lines are too long