//Bron : http://www.langenhoven.com/code/emailencrypt/standalone.js

function bereken()
{

      document.getElementById("n").innerHTML = '';
      document.getElementById("e").innerHTML = '';
      document.getElementById("n2").innerHTML = '';
      document.getElementById("d").innerHTML = '';
  
	var p=document.getElementById("p1").value;
	var q=document.getElementById("p2").value;
	

	var bb = '10'; 
	var bigp = str2bigInt(p,bb,0);
	var bigq = str2bigInt(q,bb,0);
	var bigN = mult(bigp,bigq);

	
	var tst_number=str2bigInt('17',bb,0);

	var one = str2bigInt('1',bb,0);
	var thegcd, finalE;
	finalE = bigInt2str(tst_number,bb);

	do 
	{
		var bigphi = mult(sub(bigp,'1'),sub(bigq,'1'));
		thegcd = tst_number;

		GCD_(thegcd, bigphi);

		if (!equals(thegcd,one))
		{
			tst_number = add(str2bigInt(finalE,bb,0),one);

			finalE = bigInt2str(tst_number,bb);
		}
	} while (!equals(thegcd,one));

	var bigphi = mult(sub(bigp,'1'),sub(bigq,'1'));

	var bigE = str2bigInt(finalE,bb,0);
	var bigD = inverseMod(bigE,bigphi);

	var N = bigInt2str(bigN,bb);
	var E = finalE;
	var D = bigInt2str(bigD,bb);
        
       alert ('Je publieke sleutel is   ' +  N + ':' + E + '\n Schrijf de sleutel over. \n Deze sleutel kun je aan al je klasgenootjes geven');
       alert ('Je geheime sleutel is   ' +  N + ':' + D + '\n Schrijf de sleutel over. \n Zorg dat niemand deze sleutel te weten komt');

	document.getElementById("n").innerHTML = N;
      document.getElementById("e").innerHTML = E;

	document.getElementById("n2").innerHTML = N;
	document.getElementById("d").innerHTML = D;

}



function makeKey()
{
       //Create a random AES key. It must be 32 Hex chars long
       var key = '';
       for (i=0,33;i<33;i++)
       {
               var randomnumber=Math.floor(Math.random()*16);
               if (randomnumber <= 9 ) {
                       key = key + randomnumber;
               } else if (randomnumber == 10) {
                       key = key + 'A';
               } else if (randomnumber == 11) {
                       key = key + 'B';
               } else if (randomnumber == 12) {
                       key = key + 'C';
               } else if (randomnumber == 13) {
                       key = key + 'D';
               } else if (randomnumber == 14) {
                       key = key + 'E';
               } else {
                       key = key + 'F';
               }
       }
       return key;
}

function RSAEncrypt()
{

       var plainmsg = document.getElementById("inputtext").value;

       var bb = '10'; //bigint base;

       //Generate a key for the AES encryption process
       var AESkey = makeKey();
       //GM_log("Plain AES key " + AESkey);
       //Encrypt the email

       var aes_text = aes_encrypt(AESkey, plainmsg);

       //Encrypt the key using RSA
       var plaintext = AESkey;

       //Grab the public key
       var keyspot = document.getElementById("pubkeytext");
       var key = keyspot.value;
       var keys = key.split(":");

       var keymax = keys.length;
       keymax = keymax - 1;
       var keyE = keys[keymax];
       keymax = keymax - 1;
       var keyN = keys[keymax];


       //make the keys "big"
       var bigkeyN = int2bigInt(keyN,20);
       var bigkeyE = int2bigInt(keyE,20);

       //Encrypt the text
       var etext = '';
       while (plaintext.length > 0)
       {
               var plainnum = getpnum(plaintext,5);


               //Check to see if this number is too large to encrypt
               if (greater(plainnum, bigkeyN)) {
                       alert("Je sleutels zijn te klein om veilig te kunnen encrypten/decrypten. Maak twee nieuwe sleutels aan. Kies twee grote priemgetallen voor het maken van de sleutels.");
                       return;
               }

               var ciphernum = str2bigInt('0',bb,0);
               ciphernum = powMod(plainnum, bigkeyE, bigkeyN);

               if (etext == '') {
                       etext = bigInt2str(ciphernum,bb);
               } else {
                       etext = etext.concat(';', bigInt2str(ciphernum,bb));
               }

               //Cut off the first 5 chars of the string
               plaintext = plaintext.slice(5);
       }

       //GM_log("RSA key " + etext);

       //Combine the RSA encrypted key with the AES encryption
       etext = etext + ':' + aes_text;

       //Mark the text as encrypted so that we know were to start and end with the
       //decryption process
       etext = "--- Start of mailencrypt --- " + etext + " --- End of mailencrypt ---";

       //Return the encrypted text
       //GM_log("Fully encrypted email " + etext);
       document.getElementById("outputtext").value = etext;
       return etext;

}

function RSAdecryptText() {
       //This is called by the decrypt button and gets all the pieces
       //of the process together to call the RSA decryption process

       var bb = '10'; //bigint base;

       //Find the place where the text is stored
       var plaintext = document.getElementById("inputtext").value;

       //Grab the private key
       var keyspot = document.getElementById("privkeytext");
       var key = keyspot.value;

       //Split this key into the various components
       var keys = key.split(":");
       var keymax = keys.length;

       if(key.length==0){
   alert("Je bent vergeten een geheime sleutel in te vullen");
               return;
       }else if(plaintext.length==0){
   alert("Er is geen tekst ingevuld in het invoerveld");
               return;
       }else if(keymax==1){
   alert("Je hebt een ongeldige geheime sleutel ingevuld");
               return;
       }


       //The last value is the D component
       keymax = keymax - 1;
       var keyD = keys[keymax];
       //Second last part is the N component
       keymax = keymax - 1;
       var keyN = keys[keymax];

       //Make the keys big
       var bigkeyN = str2bigInt(keyN,bb,0);
       var bigkeyD = str2bigInt(keyD,bb,0);

       // Strip out all the "> " indendation characters from the message
       //Only strip the chars for plaintext messages
       var beforepos = 1;
       beforepos = plaintext.indexOf("<div>"); //check for html
       if (beforepos <= 0 ) {
               beforepos = 1;
               while ( beforepos > 0 ) {
                       beforepos = plaintext.indexOf(">");
                       if ( beforepos > 0 ) {
                               var afterpos = beforepos + 1;
                               plaintext = plaintext.slice(0,beforepos) + plaintext.slice(afterpos);
                       }
               }
       }


       //find the encrypted part of the email
       var beforepos = plaintext.indexOf("--- Start of mailencrypt ---");
       var afterpos = plaintext.indexOf(" --- End of mailencrypt ---");
       if ( beforepos > 0 ) {
               var beforetext = plaintext.slice(0,beforepos);
       } else {
               var beforetext = "";
       }
       if ( afterpos > 0 ) {
               var aftertext = plaintext.slice(afterpos + 27);
       } else {
               var aftertext = "";
       }
       plaintext = plaintext.slice(beforepos + 29, afterpos);

       //split the encrypted email into the key and the AES encrypted portion
       var etexts = plaintext.split(":");

       //the first text is the key which we need to decrypt using RSA
       var ptexts = etexts[0].split(";");


       var i = 0;
       var dtext = '';
       var tmptext = '';
       while ( i < ptexts.length )
       {
               //Turn the ciphertext number into a plaintext number
               var ciphernum = str2bigInt(ptexts[i],bb,0);
               if (greater(ciphernum, bigkeyN)) {
                       addmsg(ptexts[i]);
                       addmsg(bigInt2str(bigkeyN,bb));
                       alert("Je sleutels zijn te klein om veilig te kunnen encrypten/decrypten. Maak twee nieuwe sleutels aan. Kies twee grote priemgetallen voor het maken van de sleutels.");
                       return;
               }


               var plainnum = powMod(ciphernum, bigkeyD, bigkeyN);
               tmptext = bigInt2str(plainnum,'16'); //use base 16 to convert to hex
               tmptext = pad(tmptext,5);
               if (dtext == '') {
                       dtext = tmptext;
               } else {
                       dtext = dtext.concat(tmptext);
               }

               i = i + 1;
       }

       //chop off the padding at the end of the string
       dtext = dtext.slice(0,dtext.length-3);

       //Now decrypt the email body using AES
       var finaltxt = aes_decrypt(dtext, etexts[1]);
       //Place the other parts of the text back around it again
       finaltxt = beforetext + finaltxt + aftertext;
       document.getElementById("outputtext").value = finaltxt;
       return finaltxt;
       //GM_log("Decrypted email " + finaltxt);
} //RSAdecrypttext

function aes_encrypt(key, plainmsg)
{
  var w = new Array( 44 );                     // subkey information
  var state = new Array( 16 );                 // working state
  var round;
  var finalstr = "";
  var msg = "";

       //Grab the text to encrypt
       var longmsg = plainmsg;
       //GM_log("AES Unencrypted " + longmsg);

       //check the key
       if ( key[0] < 0 )
       {
               alert("Er is een probleem met een van de sleutels");
               return;
       }

       // expand the key
       key = hexTo16(key);
       w = key_expand( key );

       while (longmsg.length > 0 )
       {
               msg = longmsg.slice(0,16);
               longmsg = longmsg.slice(16);

               while (msg.length < 16) {
                       msg += " ";
               }

               msg = ascTo16(msg);

               // problems??
               if ( msg[0] < 0 )
               {
                       alert("There is a problem with the message");
                       return;
               }


               // initial state = message in columns (transposed from what we input)
               state = transpose( msg );

               state = AddRoundKey(state, w, 0);

               for( round=1; round<10; round++ )
               {
                       state = SubBytes(state, S_enc);
                       state = ShiftRows(state);
                       state = MixColumns(state);
                       // note here the spec uses 32-bit words, we are using bytes, so an extra *4
                       state = AddRoundKey(state, w, round*4*4);
               }

               SubBytes(state, S_enc);
               ShiftRows(state);
               AddRoundKey(state, w, 10*4*4);

               // process output
               AES_output = transpose( state );
               var tmpstr = format_AES_output(AES_output, "hex");
               if (finalstr == "") {
                       finalstr = tmpstr;
               } else {
                       finalstr = finalstr + "$" + tmpstr;
               }
       }

       //GM_log("AES Encrypted " + finalstr);

       return finalstr;

}//aes_encrypt

// do AES decryption
function aes_decrypt(key, bodytext)
{
  var w = new Array( 44 );                     // subkey information
  var state = new Array( 16 );                 // working state
  var round;
  var finalstr = "";
  var msg = "";

       var longmsg = " ";
  // get the message from the user
       if (bodytext == '') {
               longmsg = document.getElementById(loc).contentWindow.document.body.innerHTML;
       } else {
               longmsg = bodytext;
       }

       //check the key
       if ( key[0] < 0 )
       {
               alert("Er is een probleem met een van de sleutels");
               return;
       }

       // expand the key
       key = hexTo16(key);
       w = key_expand( key );

       var multmsg = longmsg.split("$");

       var i = 0;
       while (i < multmsg.length)
       {
               msg = hexTo16(multmsg[i]);

               // problems??
               if ( msg[0] < 0 )
               {
                       alert("There is a problem with the message")
                       return;
               }

               // initial state = message
               state = transpose( msg );

               state = AddRoundKey(state, w, 10*4*4);

               for( round=9; round>=1; round-- )
               {
                       state = InvShiftRows(state);
                       state = SubBytes(state, S_dec);
                       // note here the spec uses 32-bit words, we are using bytes, so an extra *4
                       state = AddRoundKey(state, w, round*4*4);
                       state = InvMixColumns(state);
               }

               InvShiftRows(state);
               SubBytes(state, S_dec);
               AddRoundKey(state, w, 0);

               // process output
               AES_output = transpose( state );
               var tmpstr = format_AES_output(AES_output, "asc");
               if (finalstr == "") {
                       finalstr = tmpstr;
               } else {
                       finalstr = finalstr + tmpstr;
               }

               i += 1;
       }

       //GM_log("AES Decrypted " + finalstr);

       return finalstr;
}//aes_decrypt


function mypow(base, exp)
{
       //I didn't find a regular exponentiation function in bigInt
       //so I had to put together this homegrown version
       //This function is missing some error checks, etc, but
       //it works for this purpose

       //Special checks
       if (exp < 1) {
               return str2bigInt('1','10',0);
       }
       if (exp == 1){
               return base;
       }

       var orig = base;
       var origexp = exp;

       //Precalculate some values to cut down on the number of loops
       var val2 = mult(base, base);
       var val4 = mult(val2, val2);
       var val16 = mult(val4, val4);

       var myval = val2;
       var expcount = 2;

       while (1>0)
       {
               //prevent long processes from killing the system
               if (exp > 512) {
                       alert("Exponent count " + expcount + " -> original " + origexp);
               }
               if (expcount * 2 <= origexp)
               {
                       myval = mult(myval, myval);
                       expcount = expcount * 2;
               } else {
                       var diff = origexp - expcount;
                       if (diff>=16) {
                               myval = mult(myval,val16);
                               expcount = expcount + 16;
                               continue;
                       }
                       if (diff>=4) {
                               myval = mult(myval,val4);
                               expcount = expcount + 4;
                               continue;
                       }
                       if (diff>=2) {
                               myval = mult(myval,val2);
                               expcount = expcount + 2;
                               continue;
                       }
                       if (diff==1) {
                               myval = mult(myval,orig);
                               expcount = expcount + 1;
                               continue;
                       }
                       if (diff<1) {
                               return myval;
                       }

               }
       }

}

function getpnum(ptext,n)
{
       //convert the plain text into a number
       var bb = '10'; //bigInt base
       var thenum = str2bigInt('0',bb,0);
       var hexbase = str2bigInt('16',bb,0);
       var cval, expval;
       //Grab "n" number of chars from the string to encrypt
       while (ptext.length < n) {
               ptext = ptext.concat('0');
       }

       for (i=0,n;i<n;i++)
       {
               expval = n - (i + 1);
               //Adjust the ASCII codes down so that 0 has
               //a value of 2
               var ccode = ptext.charCodeAt(i);
               //0 has an ASCII value of 48
               //9 = 57, A = 65, F = 70
               if (ccode >=48 && ccode <= 57) {
                       ccode = ccode - 48;
               } else {
                       ccode = ccode - 55;
               }

               cval = int2bigInt(ccode,0);
               var power = mypow(hexbase, expval );
               cval = mult(cval, power);
               thenum = add(thenum, cval);
       }

       return thenum;
}  //getpnum

function pad(ustr, n) {
       //Pad the ustr to make sure it is "n" chars long
       //this will catch numbers with leading zeroes
       while (ustr.length < n) {
               ustr = '0' + ustr;
       }
       return ustr;
} //pad


function clearmsg() {
 document.getElementById("msgtext").innerHTML = "";
}

function addmsg(ntext) {
 var xtext = document.getElementById("msgtext").innerHTML;
 xtext = xtext + "\n" + ntext;
 document.getElementById("msgtext").innerHTML = xtext;

}



