Illegale Primzahl

Kann eine Zahl illegal sein?

Eine Kuriosität ist diese Primzahl auf jeden Fall.
Man nehme eine Primzahl und speichert diese Zahl binär in einer Datei. Dannach dekomprimiert man diese Datei mit gunzip und raus kommt der Source Code von DeCSS, dem Code zum Entschlüsseln einer DVD, welcher eigentlich illegel ist.
Folgende Dartellung zeigt die Primzahl als Text: (Download als Textdatei: prime.txt)
4
8565078965 7397829309 8418946942 8613770744 2087351357 9240196520 7366869851
3401047237 4469687974 3992611751 0973777701 0274475280 4905883138 4037549709
9879096539 5522701171 2157025974 6669932402 2683459661 9606034851 7424977358
4685188556 7457025712 5474999648 2194184655 7100841190 8625971694 7970799152
0048667099 7592359606 1320725973 7979936188 6063169144 7358830024 5336972781
8139147979 5551339994 9394882899 8469178361 0018259789 0103160196 1835034344
8956870538 4520853804 5842415654 8248893338 0474758711 2833959896 8522325446
0840897111 9771276941 2079586244 0547161321 0050064598 2017696177 1809478113
6220027234 4827224932 3259547234 6880029277 7649790614 8129840428 3457201463
4896854716 9082354737 8356619721 8622496943 1622716663 9390554302 4156473292
4855248991 2257394665 4862714048 2117138124 3882177176 0298412552 4464744505
5834628144 8833563190 2725319590 4392838737 6407391689 1257924055 0156208897
8716337599 9107887084 9081590975 4801928576 8451988596 3053238234 9055809203
2999603234 4711407760 1984716353 1161713078 5760848622 3637028357 0104961259
5681846785 9653331007 7017991614 6744725492 7283348691 6000647585 9174627812
1269007351 8309241530 1063028932 9566584366 2000800476 7789679843 8209079761
9859493646 3093805863 3672146969 5975027968 7712057249 9666698056 1453382074
1203159337 7030994915 2746918356 5937621022 2006812679 8273445760 9380203044
7912277498 0917955938 3871210005 8876668925 8448700470 7725524970 6044465212
7130404321 1826101035 9118647666 2963858495 0874484973 7347686142 0880529443

Du glaubst es nicht? Dann probiers einfach aus!

Folgendes kleine Progrämmchen liest die Primzahl aus der Textdatei "prime.txt" und speichert sie in der binären BigEndian Darstellung als "prime.gz". Am Ende wird dann noch "gunzip -c prime.gz" aufgerufen um die erzeugte Datei zu dekomprimieren und auf der Konsole auszugeben.

#include <QtCore>
#include <gmpxx.h>

int main(int argc, char* argv[])
{
  QFile in("prime.txt");
  if (in.open(QIODevice::ReadOnly | QIODevice::Text))
  {
    // read prime from text file
    QTextStream read(&in);
    QString sTmp = read.readAll();
    mpz_class prime((const char*)sTmp.toAscii(), 10);
    QFile out("prime.gz");
    if (out.open(QIODevice::WriteOnly | QIODevice::Unbuffered))
    {
      // store prime as binary
      QByteArray data;
      mpz_class z2e32("100000000", 16);
      // get first 32 bit
      mpz_class mod = prime % z2e32;
      unsigned int ulNumber = mod.get_ui();
      prime /= z2e32;
      do
      {
        // store value
        ulNumber = qToBigEndian(ulNumber);
        data.prepend(QByteArray((const char*)&ulNumber, 4));
        // get next 32 bit
        mod = prime % z2e32;
        ulNumber = mod.get_ui();
        prime /= z2e32;
      }
      while(prime > 0);
      // store last bytes
      if (ulNumber > 0xffffff)
      {
        ulNumber = qToBigEndian(ulNumber);
        data.prepend(QByteArray((const char*)&ulNumber, 4));
      }
      else if (ulNumber > 0xffff)
      {
        unsigned char a = ulNumber / 0x10000;
        unsigned short b = ulNumber % 0x10000;
        b = qToBigEndian(b);
        data.prepend(QByteArray((const char*)&b, 2));
        data.prepend(QByteArray((const char*)&a, 1));
      }
      else if (ulNumber > 0xff)
      {
        unsigned short b = ulNumber;
        b = qToBigEndian(b);
        data.prepend(QByteArray((const char*)&b, 2));
      }
      else
      {
        unsigned char a = ulNumber;
        data.prepend(QByteArray((const char*)&a, 1));
      }

      out.write(data);
    }  
  }
  
  // decompress prime
  QProcess::execute("gunzip -c prime.gz");

  return 0;
}

Download: prime.tar.bz2
Abhängigkeiten: Qt4, GMP (GNU Multiple Precision Arithmetic Library)
(Auf aktuellen Linux Distributionen sind diese vorhanden.)
Installation:
tar -xvjf prime.tar.bz2           # auspacken
cd prime                          
qmake                             # makefile erzeugen
make                              # kompilieren
./prime                           # programm starten

Wie ist das möglich?

Faszinierend oder? Wie so oft ist des Rätsels Lösung aber weniger spektakulär. Jede Datei, egal ob Binärdatei oder Textdatei ist am Ende nichts weiter als eine große Zahl die auf der Festplatte gespeichert wird. Der Wert 65 (dez) entpricht im ASCII Zeichensatz z.B. dem Zeichen 'A'. Mit so einer Zeichentabelle werden diese Zahlen für den Menschen lesbar gemacht.
Gunzip hat nun die Eigenschaft, Daten zu dekomprimieren bis es auf die Bytes "00 00" (hex) stößt. Das ist sozusagen das Ende der komprimierten Daten. Der Rest wird ignoriert. Um so eine Primzahl zu erzeugen, nimmt man also erst mal den DeCSS-Code und komprimiert ihn mit gzip. Diese komprimierte Datei interpretiert man jetzt als große Zahl und sucht danach eine Primzahl, welche mit diese Zahl anfängt. Die gefundene Primzahl ist natürlich etwas länger, aber diese Verlängerung ist sozusagen nur Datenmüll, welcher beim Dekomprimieren sowieso ignoriert wird.
Weiter Informationen:
[1] Das Original: 48565...29443 (1401-digits)
[2] DeCSS steganographisch versteckt.

Valid XHTML 1.0 Strict