Im Oktober 1999 veröffentlichte eine Gruppe um den damals 16-jährigen Norweger Jon Lech Johansen das Programm DeCSS, um den DVD-Wiedergabeschutz Content Scramble System (CSS) zu umgehen. CSS nutzte eine 40-Bit-Verschlüsselung, deren Schlüssel an lizenzierte Hersteller ausgegeben wurden, um die Wiedergabe von DVDs zu beschränken. Da die Verbreitung des Codes unter den US-amerikanischen DMCA fiel und gerichtlich untersagt wurde, suchten Aktivisten nach Wegen, den Code als mathematische Entität zu tarnen.
Phil Carmody konstruierte daraufhin eine Primzahl, die binär interpretiert nach gzip-Dekompression den vollständigen Quellcode von DeCSS enthält. Der Kern des DeCSS-Algorithmus lässt sich in TypeScript wie folgt implementieren, wobei die Bit-Operationen direkt die Entschlüsselungslogik der Sektoren abbilden:
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++;
}
}
Das Prinzip hinter der Primzahl besteht darin, den gesamten Quellcode als eine einzige, massive Ganzzahl zu interpretieren. Da eine beliebige Datei selten eine Primzahl ist, wird die Zahl künstlich durch zusätzliche Bytes (Padding) erweitert. In einer Schleife wird dieses Padding so lange inkrementiert, bis ein Primzahltest wie der Miller-Rabin-Test die Zahl als prim bestätigt. Der folgende Generator nutzt den oben beschriebenen DeCSS-Code und sucht nach einer entsprechenden Primzahl-Reprä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));
Der Trick mit der Primzahl war nie Gegenstand eines eigenen Gerichtsverfahrens und musste es auch nicht sein. Obwohl Carmodys ursprüngliche Primzahl 1401 Stellen hatte, war sie für die damaligen Top-Listen der größten Primzahlen zu klein. Er erstellte später eine 1905-stellige Version, die künstlich durch Nullbytes aufgebläht wurde, um den zehnten Platz in der ECPP-Rangliste zu erreichen. Dieser Erfolg demonstrierte die Unmöglichkeit, reine Mathematik zu zensieren, da die Zahl ihren Platz in der Liste allein aufgrund ihrer mathematischen Eigenschaften verdiente.