
    //	    	JavaScrypt  --  Main page support functions

    var loadTime = (new Date()).getTime();  // Save time page was loaded
    var key;	    	    	    	    // Key (byte array)
    var prng;	    	    	    	    // Pseudorandom number generator
        
    //	setKey  --  Set key from string or hexadecimal specification
    
    function setKey(clave) {
    	var s = encode_utf8(clave);
	    var i, kmd5e, kmd5o;

	    if (s.length == 1) {
	    	s += s;
	    }
	    
	    md5_init();
	    for (i = 0; i < s.length; i += 2) {
	    	md5_update(s.charCodeAt(i));
	    }
	    md5_finish();
	    kmd5e = byteArrayToHex(digestBits);
	    
	    md5_init();
	    for (i = 1; i < s.length; i += 2) {
	    	md5_update(s.charCodeAt(i));
	    }
	    md5_finish();
	    kmd5o = byteArrayToHex(digestBits);

	    var hs = kmd5e + kmd5o;
	    key =  hexToByteArray(hs);
	    hs = byteArrayToHex(key);
	}
	    
    
    function determineArmourType(s) {
    	var kt, pcg, phex, pb64, pmin;
	
	pcg = s.indexOf(codegroupSentinel);
	phex = s.indexOf(hexSentinel);
	pb64 = s.indexOf(base64sent);
	if (pcg == -1) {
	    pcg = s.length;
	}
	if (phex == -1) {
	    phex = s.length;
	}
	if (pb64 == -1) {
	    pb64 = s.length;
	}
	pmin = Math.min(pcg, Math.min(phex, pb64));
	if (pmin < s.length) {
	    if (pmin == pcg) {
	    	kt = 0;
	    } else if (pmin == phex) {
	    	kt = 1;
	    } else {
	    	kt = 2;
	    }
	} else {
    		kt = 1;
	}
	return kt;
    }
    
    
    function Decrypt_text(clave, texto) {
	   
	setKey(clave);
	var ct = new Array(), kt;
	kt = determineArmourType(texto);
	if (kt == 0) {
		ct = disarm_codegroup(texto);
	} else if (kt == 1) {
		ct = disarm_hex(texto);
	} else if (kt == 2) {
		ct = disarm_base64(texto);
	}

	var result = rijndaelDecrypt(ct, key, "CBC");
	
	var header = result.slice(0, 20);
	result = result.slice(20);
	
	/*  Extract the length of the plaintext transmitted and
	    verify its consistency with the length decoded.  Note
	    that in many cases the decrypted messages will include
	    pad bytes added to expand the plaintext to an integral
	    number of AES blocks (blockSizeInBits / 8).  */
	
	var dl = (header[16] << 24) | (header[17] << 16) | (header[18] << 8) | header[19];
    	if ((dl < 0) || (dl > result.length)) {
	    alert("Message (length " + result.length + ") truncated.  " +
	    	dl + " characters expected.");
	    //	Try to sauve qui peut by setting length to entire message
    	    dl = result.length;
	}
	
	/*  Compute MD5 signature of message body and verify
	    against signature in message.  While we're at it,
	    we assemble the plaintext result string.  Note that
	    the length is that just extracted above from the
	    message, *not* the full decrypted message text.
	    AES requires all messages to be an integral number
	    of blocks, and the message may have been padded with
	    zero bytes to fill out the last block; using the
	    length from the message header elides them from
	    both the MD5 computation and plaintext result.  */
	    
	var i, plaintext = "";
	
	md5_init();
	for (i = 0; i < dl; i++) {
	    plaintext += String.fromCharCode(result[i]);
	    md5_update(result[i]);
	}
	md5_finish();

	for (i = 0; i < digestBits.length; i++) {
	    if (digestBits[i] != header[i]) {
	    	alert("Message corrupted.  Checksum of decrypted message does not match.");
		break;
	    }
	}
	
	//  That's it; plug plaintext into the result field
	
	return decode_utf8(plaintext);
    }
