I oktober 1999 släppte en grupp ledd av den då 16-årige norrmannen Jon Lech Johansen programmet DeCSS för att kringgå DVD-uppspelningsskyddet Content Scramble System (CSS). CSS använde 40-bitars kryptering, vars nycklar distribuerades till licensierade tillverkare, för att begränsa DVD-uppspelning. Eftersom distributionen av koden faller under den amerikanska DMCA-lagen och är lagligt förbjuden, sökte aktivister sätt att dölja koden som en matematisk enhet.
Phil Carmody konstruerade sedan ett primtal som, när det tolkas binärt efter gzip-dekomprimering, innehåller den fullständiga källkoden för DeCSS. Kärnan i DeCSS-algoritmen kan implementeras i TypeScript enligt följande, där bitoperationerna direkt mappar sektordekrypteringslogiken.:
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++;
}
}
Principen bakom primtalet är att tolka hela källkoden som ett enda, heltal. Eftersom ingen given fil någonsin är ett primtal, utökas talet artificiellt med ytterligare byte (utfyllnad). Denna utfyllnad ökas i en loop tills ett primalitetstest, såsom Miller-Rabin-testet, bekräftar att talet är primtal. Följande generator använder DeCSS-koden som beskrivs ovan och söker efter en motsvarande primtalsrepresentation.:
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 blev aldrig föremål för ett separat rättsfall, och det behövde det inte heller vara. Även om Carmodys ursprungliga primtal hade 1401 siffror, var det för litet för topplistorna över de största primtalen vid den tiden. Han skapade senare en version med 1905 siffror, artificiellt uppblåst med nollbyte, för att uppnå tionde plats i ECPP-rankningen . Denna framgång visade att det var omöjligt att censurera ren matematik, eftersom talet förtjänade sin plats på listan enbart på grundval av sina matematiska egenskaper.