Code en nombres premiers

En octobre 1999, un groupe dirigé par le Norvégien Jon Lech Johansen, alors âgé de 16 ans, a diffusé le programme DeCSS afin de contourner le système de cryptage CSS (Content Scramble System), une protection de lecture des DVD. Le CSS utilisait un chiffrement 40 bits, dont les clés étaient distribuées aux fabricants agréés, pour restreindre la lecture des DVD. La distribution du code étant soumise à la loi américaine DMCA et donc illégale, les militants ont cherché des moyens de le dissimuler sous l'apparence d'une entité mathématique.


Phil Carmody a ensuite construit un nombre premier qui, interprété en binaire après décompression gzip, contient le code source complet de DeCSS. Le cœur de l'algorithme DeCSS peut être implémenté en TypeScript comme suit, les opérations binaires correspondant directement à la logique de décryptage des secteurs.:

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++;
    }
}

Le principe du nombre premier consiste à interpréter l'intégralité du code source comme un seul entier. Puisqu'aucun fichier ne peut être un nombre premier, ce nombre est artificiellement augmenté d'octets supplémentaires (remplissage). Ce remplissage est incrémenté en boucle jusqu'à ce qu'un test de primalité, tel que le test de Miller-Rabin, confirme que le nombre est premier. Le générateur suivant utilise le code DeCSS décrit ci-dessus et recherche une représentation sous forme de nombre premier.:

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));

L'astuce du nombre premier n'a jamais fait l'objet d'un procès distinct, et cela n'était d'ailleurs pas nécessaire. Bien que le nombre premier original de Carmody comptât 1401 chiffres, il était trop petit pour figurer dans les classements des plus grands nombres premiers de l'époque. Il créa par la suite une version à 1905 chiffres, artificiellement gonflée d'octets nuls, pour atteindre la dixième place du classement ECPP . Ce succès démontra l'impossibilité de censurer les mathématiques pures, puisque ce nombre méritait sa place dans le classement uniquement grâce à ses propriétés mathématiques.

Retour