Kode i primtal

I oktober 1999 udgav en gruppe ledet af den dengang 16-årige nordmand Jon Lech Johansen DeCSS- programmet for at omgå Content Scramble System (CSS) DVD-afspilningsbeskyttelse. CSS brugte 40-bit kryptering, hvis nøgler blev distribueret til licenserede producenter, til at begrænse DVD-afspilning. Fordi distributionen af koden faldt ind under den amerikanske DMCA og var juridisk forbudt, søgte aktivister måder at skjule koden som en matematisk enhed.


Phil Carmody konstruerede derefter et primtal, som, når det fortolkes binært efter gzip-dekomprimering, indeholder den komplette kildekode til DeCSS. Kernen i DeCSS-algoritmen kan implementeres i TypeScript som følger, hvor bitoperationerne direkte kortlægger sektordekrypteringslogikken.:

function CSSdescramble(sec: Uint8Array, key: Uint8Array): void {
    let t1: number, t2: number, t3: number, t4: number, t5: number, t6: number;
    const end = 0x800;

    t1 = (key[0] ^ sec[0x54]) | 0x100;
    t2 = key[1] ^ sec[0x55];

    const keyView = new DataView(key.buffer, key.byteOffset);
    const secView = new DataView(sec.buffer, sec.byteOffset);

    t3 = (keyView.getUint32(2, true) ^ secView.getUint32(0x56, true)) >>> 0;
    t4 = t3 & 7;
    t3 = (t3 * 2 + 8 - t4) >>> 0;

    let offset = 0x80;
    t5 = 0;

    while (offset < end) {
        t4 = CSStab2[t2] ^ CSStab3[t1];
        t2 = t1 >>> 1;
        t1 = ((t1 & 1) << 8) ^ t4;
        t4 = CSStab5[t4];
        t6 = (((((((t3 >>> 3) ^ t3) >>> 1) ^ t3) >>> 8) ^ t3) >>> 5) & 0xff;
        t3 = (((t3 << 8) >>> 0) | t6) >>> 0;
        t6 = CSStab4[t6];
        t5 += t6 + t4;

        sec[offset] = CSStab1[sec[offset]] ^ (t5 & 0xff);
        t5 >>>= 8;
        offset++;
    }
}

Princippet bag primtallet er at fortolke hele kildekoden som et enkelt, solidt heltal. Da ingen given fil nogensinde er et primtal, forøges tallet kunstigt med yderligere bytes (polstring). Denne polstring øges i en løkke, indtil en primality-test, såsom Miller-Rabin-testen, bekræfter, at tallet er et primtal. Følgende generator bruger den ovenfor beskrevne DeCSS-kode og søger efter en tilsvarende primtalrepræsentation.:

import { isPrime } from 'crypto-utils-lib'; // Hypothetical library for primality testing

async function generateIllegalPrime(code: string): Promise<bigint | null> {
    const encoder = new TextEncoder();
    const bytes = encoder.encode(code);

    let hexBase = Array.from(bytes)
        .map(b => b.toString(16).padStart(2, '0'))
        .join('');

    // Start bei 1, da 0x00 immer gerade und damit keine Primzahl ist
    for (let i = 1; i < 256; i++) {
        const candidateHex = hexBase + i.toString(16).padStart(2, '0');
        const candidateInt = BigInt('0x' + candidateHex);

        if (await isPrime(candidateInt)) {
            return candidateInt;
        }
    }
    return null;
}

const source = `void CSSdescramble(unsigned char *sec, unsigned char *key) { ... }`;
generateIllegalPrime(source).then(p => console.log(p));

Primtalstricket var aldrig genstand for en separat retssag, og det behøvede det heller ikke at være. Selvom Carmodys oprindelige primtal havde 1401 cifre, var det for lille til toplisterne over de største primtal på det tidspunkt. Han skabte senere en version fra 1905, kunstigt oppustet med nulbytes, for at opnå en tiendeplads på ECPP-ranglisten . Denne succes demonstrerede umuligheden af at censurere ren matematik, da tallet fik sin plads på listen udelukkende på baggrund af dets matematiske egenskaber.

Tilbage