
/* Werte und Algorithmen für aRC4 */

 Size = 256;
 var RC4_sbox = new Array (Size);

 function RC4_tausche(i, j) {
    var hlp  = 0;

    hlp = RC4_sbox[i];
    RC4_sbox[i] = RC4_sbox[j];
    RC4_sbox[j] = hlp;
 }/* RC4_tausche */

 function RC4_crypt(key, text, encrypt) {
    var i, j = 0;
    var k, t = 0;
    var rtxt = "";

    for (i=0; i<Size; i++)
        RC4_sbox[i] = i;

    for (i=0; i<Size; i++) {
        j = (j + RC4_sbox[i] + key.charCodeAt(i % key.length)) % Size;
        RC4_tausche(i, j);
    }

    for (k=0; k<text.length; k++) {
        i = (i + 1) % Size;
        j = (j + RC4_sbox[i]) % Size;
        RC4_tausche(i, j);
        t = (RC4_sbox[i]+RC4_sbox[j])%Size;
        rtxt = rtxt + String.fromCharCode(text.charCodeAt(k)^RC4_sbox[t]);
    }

    return rtxt;
 }/* RC4_crypt */

 function RC4_encrypt(key, text) {
     document.rc4.geheimtext.value = escape(RC4_crypt(key, text, 1));
 }/* RC4_encrypt */

 function RC4_decrypt(key, text) {
     document.rc4.klartext.value = RC4_crypt(key, unescape(text), 0);
 }/* RC4_decrypt */



/* Werte und Algorithmen für RSA */
 var m = 0;
 var e = 0, d = 0;
 var BlkLen = 0; /* Bitanzahl in einem Block */

/* Initialisierung der Primzahlen. Die Größe ist sogewählt, dass mindestens */
/* ein Zeichen des Alphabetes verschlüsselt werden kann, aber dabei nicht   */
/* die maximale Größe für Ganzzahlen überschritten wird.                    */
 var Primzahlen = new Array (
                  101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157,
                  163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
                  229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
                  293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367,
                  373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439,
                  443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509,
                  521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599,
                  601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661,
                  673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751,
                  757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
                  839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919,
                  929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997
 );

 function bitLength(intZahl) {
    /* Ermittelt die Bitlänge des ganzzahligen Anteils des Übergabewertes. */
    var i = 0;

    while (intZahl > 0) {
          intZahl = Math.floor(intZahl / 2);
          i++;
    }
    return i;
 }/* bitLength */

 function RSA_crypt(basis, exponent, modulus) {
    /* Berechnet die nte-Potenz einer Zahl (basis) unter einem Modulus. */
    var sum      = 0;  /* Dient zur Kontrolle, ob der Exponent vollständig berechnet wurde.*/
    var ergebnis = 1;  /* Nimmt das Ergebnis der Berechnung auf.                           */
    var mask     = 1;  /* Maske zur Bestimmung, ob 2er-Potenz Teil des Exponenten ist.     */

    if (isFinite(modulus*modulus)) {
       while (sum < exponent) {
          if ((exponent&mask) != 0) {
             ergebnis = (ergebnis*basis) % modulus;
             sum = sum + (exponent&mask);
          }
          basis = (basis*basis) % modulus;
          mask = mask << 1;
       }
       return ergebnis;
    } else return 0;
 }/* RSA_crypt */

 function ggT(a,b) {
    /* Berechnet zunächst das kleinste gemeinsame Vielfache (kgV), um dann */
    /* aus der Umkehrung den größten gemeinsamen Teiler (ggT) zu ermitteln.*/
    var x = a;
    var y = b;

    while (x < y || x > y)
        if (x-y < 0)
           x = x + a;
        else
           y = y + b;

    return (a*b/x);
 }/* ggT */

 function PublicKey (phi) {
    /* Sucht die kleinste relativ prime Zahl zu phi = (p-1)*(q-1) ist. */
    var akT = 0; /* aktueller Teiler                        */
    var e   = 2; /* Letztlich die relative Primzahl zu phi. */

    while ((akT != 1) && (akT != -1)) {
          e = e + 1;
          if (isFinite(e*phi))
             akT = ggT(e, phi);
          else return -1;
    }

    return e;
 }/* PublicKey */

 function SecretKey (e, phi) {
    /* Sucht den Faktor für phi, um die Umkehrung der Exponention zu ermöglichen */
    var i = 0;

    do {
       i = i + 1;
       if (!isFinite(i*phi)) return -1;
    } while ((1+i*phi)%e != 0);

    return (1+i*phi)/e;
 }/* SecretKey */

 function keygen_RSA(p, q) {
    var phi = (p-1) * (q-1);

    m = p * q;
    e = PublicKey(phi);
    d = SecretKey(e, phi);
 }/* keygen_RSA */

 function RSA_keys(form) {
    /* Generierung des Schlüsselpaares für die Beispielermittlung. */
    var P = form.p.options[form.p.selectedIndex].value;
    var Q = form.q.options[form.q.selectedIndex].value;

    keygen_RSA(P, Q);

    form.n.value   = m;
    form.phi.value = (P-1)*(Q-1);
    form.e.value   = e;
    form.d.value   = d;
 }/* RSA_keys */


 function RSA_keygen(form) {
    var P, Q;

    // P = 887; Q = 997;
    /* Generierung des Schlüsselpaares für die Beispielverschlüsselung. */
    do {
       P = Primzahlen[Math.round(Math.random()*100)%Primzahlen.length];
       Q = Primzahlen[Math.round(Math.random()*100)%Primzahlen.length];
    } while (!isFinite(P*P*Q*Q));

    keygen_RSA(P, Q);
    BlkLen = bitLength(m);

    form.e.value = e + ", " + m;
    form.d.value = d + ", " + m;
    form.geheimtext.value = "";
 }/* RSA_keygen */

 function fillNull (Zeichenwert, len) {
    var temp = String(Zeichenwert);

    while (temp.length < len)
          temp = "0" + temp;
    alert(temp+"  "+parseInt(temp));
    return temp;
 }/* fillNull */

 function RSA_encode (Klartext) {
    var Chiffre  = "";

    while ((Klartext.length % Math.floor((BlkLen-1)/8)) != 0)
           Klartext = Klartext + " ";

    for (i=0; i < Klartext.length; i++) {
        tmp = Klartext.charCodeAt(i);
        j = 1;
        while (((j+1)*8) < BlkLen) {
              tmp = tmp << 8;
              tmp = tmp + Klartext.charCodeAt(i+j);
              j++;
        }
        if (j > 0) i = i + (j-1);
        Chiffre = Chiffre + String(RSA_crypt(parseInt(tmp), e, m)) + " ";
    }
    return Chiffre;
 }/* RSA_encode */


 function num_decode (Num) {
    var temp   = Num;
    var result = "";

    Num = Num >> 8;
    if (Num > 0)
       result = num_decode(Num);
    return result + String.fromCharCode(temp & 255);
 }/* num_decode */

 function RSA_decode (Geheimtext) {
    var Chiffre  = Geheimtext.split(" ");
    var Klartext = "";

    for (i=0; i < Chiffre.length; i++)
        if (Chiffre[i] != "") {
           Klarnum  = RSA_crypt(parseInt(Chiffre[i]), d, m);
           Klartext = Klartext + num_decode(Klarnum);
        }
    return Klartext;
 }/* RSA_decode */

 function kodierenRSA (form) {
    if (BlkLen == 0)
       alert("Das erzeugte Schlüsselpaar ist zu klein,\n verschlüsseln ist nicht möglich.");
    else if ((e == 0) || (m == 0))
       alert("Bitte erst ein Schlüsselpaar erzeugen.");
    else if (form.klartext.value.length == 0)
       alert("Bitte den zu verschlüsselnden Text eingeben.");
    else form.geheimtext.value = RSA_encode(form.klartext.value);
 }/* RSA_encode */

 function dekodierenRSA (form) {
    if (BlkLen == 0)
       alert("Das erzeugte Schlüsselpaar ist zu klein,\n entschlüsseln ist nicht möglich.");
    else if ((d == 0) || (m == 0))
       alert("Bitte erst ein Schlüsselpaar erzeugen.");
    else if (form.geheimtext.value.length == 0)
       alert("Bitte erst einen Chiffretext erzeugen.");
    else form.klartext.value = RSA_decode(form.geheimtext.value);
 }/* RSA_decode */