From 0ec3252ba570387aa681e5a0865dafa5ffd72bec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20Obernd=C3=B6rfer?= <toberndo@yarkon.de>
Date: Mon, 27 Aug 2012 14:33:48 +0200
Subject: [PATCH] Use JXG for ZIP decompression

---
 resources/openpgp.js                    | 19455 +++++++++++-----------
 resources/openpgp.min.js                |   735 +-
 src/compression/zip/zip.js              |  2178 ---
 src/compression/zlib/jsxcompressor.js   |    15 +-
 src/packet/openpgp.packet.compressed.js |    14 +-
 test/encryption.html                    |     1 -
 6 files changed, 10125 insertions(+), 12273 deletions(-)
 delete mode 100644 src/compression/zip/zip.js

diff --git a/resources/openpgp.js b/resources/openpgp.js
index 4e91f858..ad271240 100644
--- a/resources/openpgp.js
+++ b/resources/openpgp.js
@@ -16,105 +16,785 @@
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
 /**
- * Implementation of the One-Pass Signature Packets (Tag 4)
- * 
- * RFC4880 5.4:
- * The One-Pass Signature packet precedes the signed data and contains
- * enough information to allow the receiver to begin calculating any
- * hashes needed to verify the signature.  It allows the Signature
- * packet to be placed at the end of the message, so that the signer
- * can compute the entire signed message in one pass.
+ * GPG4Browsers Core interface. A single instance is hold
+ * from the beginning. To use this library call "openpgp.init()"
+ * @alias openpgp
+ * @class
+ * @classdesc Main Openpgp.js class. Use this to initiate and make all calls to this library.
  */
-function openpgp_packet_onepasssignature() {
-	this.tagType = 4;
-	this.version = null; // A one-octet version number.  The current version is 3.
-	this.type == null; 	 // A one-octet signature type.  Signature types are described in RFC4880 Section 5.2.1.
-	this.hashAlgorithm = null; 	   // A one-octet number describing the hash algorithm used. (See RFC4880 9.4)
-	this.publicKeyAlgorithm = null;	     // A one-octet number describing the public-key algorithm used. (See RFC4880 9.1)
-	this.signingKeyId = null; // An eight-octet number holding the Key ID of the signing key.
-	this.flags = null; 	//  A one-octet number holding a flag showing whether the signature is nested.  A zero value indicates that the next packet is another One-Pass Signature packet that describes another signature to be applied to the same message data.
+function _openpgp () {
+	this.tostring = "";
+	
+	/**
+	 * initializes the library:
+	 * - reading the keyring from local storage
+	 * - reading the config from local storage
+	 * @return [void]
+	 */
+	function init() {
+		this.config = new openpgp_config();
+		this.config.read();
+		this.keyring = new openpgp_keyring();
+		this.keyring.init();
+	}
+	
+	/**
+	 * reads several publicKey objects from a ascii armored
+	 * representation an returns openpgp_msg_publickey packets
+	 * @param {String} armoredText OpenPGP armored text containing
+	 * the public key(s)
+	 * @return {Array[openpgp_msg_publickey]} on error the function
+	 * returns null
+	 */
+	function read_publicKey(armoredText) {
+		var mypos = 0;
+		var publicKeys = new Array();
+		var publicKeyCount = 0;
+		var input = openpgp_encoding_deArmor(armoredText.replace(/\r/g,'')).openpgp;
+		var l = input.length;
+		while (mypos != input.length) {
+			var first_packet = openpgp_packet.read_packet(input, mypos, l);
+			// public key parser
+			if (input[mypos].charCodeAt() == 0x99 || first_packet.tagType == 6) {
+				publicKeys[publicKeyCount] = new openpgp_msg_publickey();				
+				publicKeys[publicKeyCount].header = input.substring(mypos,mypos+3);
+				if (input[mypos].charCodeAt() == 0x99) {
+					// parse the length and read a tag6 packet
+					mypos++;
+					var l = (input[mypos++].charCodeAt() << 8)
+							| input[mypos++].charCodeAt();
+					publicKeys[publicKeyCount].publicKeyPacket = new openpgp_packet_keymaterial();
+					publicKeys[publicKeyCount].publicKeyPacket.header = publicKeys[publicKeyCount].header;
+					publicKeys[publicKeyCount].publicKeyPacket.read_tag6(input, mypos, l);
+					mypos += publicKeys[publicKeyCount].publicKeyPacket.packetLength;
+					mypos += publicKeys[publicKeyCount].read_nodes(publicKeys[publicKeyCount].publicKeyPacket, input, mypos, (input.length - mypos));
+				} else {
+					publicKeys[publicKeyCount] = new openpgp_msg_publickey();
+					publicKeys[publicKeyCount].publicKeyPacket = first_packet;
+					mypos += first_packet.headerLength+first_packet.packetLength;
+					mypos += publicKeys[publicKeyCount].read_nodes(first_packet, input, mypos, input.length -mypos);
+				}
+			} else {
+				util.print_error("no public key found!");
+				return null;
+			}
+			publicKeys[publicKeyCount].data = input.substring(0,mypos);
+			publicKeyCount++;
+		}
+		return publicKeys;
+	}
+	
+	/**
+	 * reads several privateKey objects from a ascii armored
+	 * representation an returns openpgp_msg_privatekey objects
+	 * @param {String} armoredText OpenPGP armored text containing
+	 * the private key(s)
+	 * @return {Array[openpgp_msg_privatekey]} on error the function
+	 * returns null
+	 */
+	function read_privateKey(armoredText) {
+		var privateKeys = new Array();
+		var privateKeyCount = 0;
+		var mypos = 0;
+		var input = openpgp_encoding_deArmor(armoredText.replace(/\r/g,'')).openpgp;
+		var l = input.length;
+		while (mypos != input.length) {
+			var first_packet = openpgp_packet.read_packet(input, mypos, l);
+			if (first_packet.tagType == 5) {
+				privateKeys[privateKeys.length] = new openpgp_msg_privatekey();
+				mypos += first_packet.headerLength+first_packet.packetLength;
+				mypos += privateKeys[privateKeyCount].read_nodes(first_packet, input, mypos, l);
+			// other blocks	            
+			} else {
+				util.print_error('no block packet found!');
+				return null;
+			}
+			privateKeys[privateKeyCount].data = input.substring(0,mypos);
+			privateKeyCount++;
+		}
+		return privateKeys;		
+	}
 
 	/**
-	 * parsing function for a one-pass signature packet (tag 4).
-	 * @param input [string] payload of a tag 4 packet
-	 * @param position [integer] position to start reading from the input string
-	 * @param len [integer] length of the packet or the remaining length of input at position
+	 * reads message packets out of an OpenPGP armored text and
+	 * returns an array of message objects
+	 * @param {String} armoredText text to be parsed
+	 * @return {Array[openpgp_msg_message]} on error the function
+	 * returns null
+	 */
+	function read_message(armoredText) {
+		var dearmored;
+		try{
+    		dearmored = openpgp_encoding_deArmor(armoredText.replace(/\r/g,''));
+		}
+		catch(e){
+    		util.print_error('no message found!');
+    		return null;
+		}
+		var input = dearmored.openpgp;
+		var messages = new Array();
+		var messageCount = 0;
+		var mypos = 0;
+		var l = input.length;
+		while (mypos < input.length) {
+			var first_packet = openpgp_packet.read_packet(input, mypos, l);
+			// public key parser (definition from the standard:)
+			// OpenPGP Message      :- Encrypted Message | Signed Message |
+			//                         Compressed Message | Literal Message.
+			// Compressed Message   :- Compressed Data Packet.
+			// 
+			// Literal Message      :- Literal Data Packet.
+			// 
+			// ESK                  :- Public-Key Encrypted Session Key Packet |
+			//                         Symmetric-Key Encrypted Session Key Packet.
+			// 
+			// ESK Sequence         :- ESK | ESK Sequence, ESK.
+			// 
+			// Encrypted Data       :- Symmetrically Encrypted Data Packet |
+			//                         Symmetrically Encrypted Integrity Protected Data Packet
+			// 
+			// Encrypted Message    :- Encrypted Data | ESK Sequence, Encrypted Data.
+			// 
+			// One-Pass Signed Message :- One-Pass Signature Packet,
+			//                         OpenPGP Message, Corresponding Signature Packet.
+
+			// Signed Message       :- Signature Packet, OpenPGP Message |
+			//                         One-Pass Signed Message.
+			if (first_packet.tagType ==  1 ||
+			    (first_packet.tagType == 2 && first_packet.signatureType < 16) ||
+			     first_packet.tagType ==  3 ||
+				 first_packet.tagType ==  8 ||
+				 first_packet.tagType ==  9 ||
+				 first_packet.tagType == 10 ||
+				 first_packet.tagType == 11 ||
+				 first_packet.tagType == 18 ||
+				 first_packet.tagType == 19) {
+				messages[messages.length] = new openpgp_msg_message();
+				messages[messageCount].messagePacket = first_packet;
+				messages[messageCount].type = dearmored.type;
+				// Encrypted Message
+				if (first_packet.tagType == 9 ||
+				    first_packet.tagType == 1 ||
+				    first_packet.tagType == 3 ||
+				    first_packet.tagType == 18) {
+					if (first_packet.tagType == 9) {
+						util.print_error("unexpected openpgp packet");
+						break;
+					} else if (first_packet.tagType == 1) {
+						util.print_debug("session key found:\n "+first_packet.toString());
+						var issessionkey = true;
+						messages[messageCount].sessionKeys = new Array();
+						var sessionKeyCount = 0;
+						while (issessionkey) {
+							messages[messageCount].sessionKeys[sessionKeyCount] = first_packet;
+							mypos += first_packet.packetLength + first_packet.headerLength;
+							l -= (first_packet.packetLength + first_packet.headerLength);
+							first_packet = openpgp_packet.read_packet(input, mypos, l);
+							
+							if (first_packet.tagType != 1 && first_packet.tagType != 3)
+								issessionkey = false;
+							sessionKeyCount++;
+						}
+						if (first_packet.tagType == 18 || first_packet.tagType == 9) {
+							util.print_debug("encrypted data found:\n "+first_packet.toString());
+							messages[messageCount].encryptedData = first_packet;
+							mypos += first_packet.packetLength+first_packet.headerLength;
+							l -= (first_packet.packetLength+first_packet.headerLength);
+							messageCount++;
+							
+						} else {
+							util.print_debug("something is wrong: "+first_packet.tagType);
+						}
+						
+					} else if (first_packet.tagType == 18) {
+						util.print_debug("symmetric encrypted data");
+						break;
+					}
+				} else 
+					// Signed Message
+					if (first_packet.tagType == 2 && first_packet.signatureType < 3) {
+						messages[messageCount].text = dearmored.text;
+						messages[messageCount].signature = first_packet;
+						break;
+				} else 
+					// Compressed Message
+					// TODO: needs to be implemented. From a security perspective: this message is plaintext anyway.
+					if (first_packet.tagType == 8) {
+						util.print_error("A directly compressed message is currently not supported");
+						break;
+				} else
+					// Marker Packet (Obsolete Literal Packet) (Tag 10)
+					// "Such a packet MUST be ignored when received." see http://tools.ietf.org/html/rfc4880#section-5.8
+					if (first_packet.tagType == 10) {
+						// reset messages
+						messages.length = 0;
+						// continue with next packet
+						mypos += first_packet.packetLength + first_packet.headerLength;
+						l -= (first_packet.packetLength + first_packet.headerLength);
+				} else
+					// Literal Message
+					// TODO: needs to be implemented. From a security perspective: this message is plaintext anyway.
+					if (first_packet.tagType == 11) {
+						util.print_error("A direct literal message is currently not supported.");
+						break;
+				}
+			} else {
+				util.print_error('no message found!');
+				return null;
+			}
+		}
+		
+		return messages;
+	}
+	
+	/**
+	 * creates a binary string representation of an encrypted and signed message.
+	 * The message will be encrypted with the public keys specified and signed
+	 * with the specified private key.
+	 * @param {obj: [openpgp_msg_privatekey]} privatekey private key to be used to sign the message
+	 * @param {Array {obj: [openpgp_msg_publickey]}} publickeys  public keys to be used to encrypt the message 
+	 * @param {String} messagetext message text to encrypt and sign
+	 * @return {String} a binary string representation of the message which can be OpenPGP armored
+	 */
+	function write_signed_and_encrypted_message(privatekey, publickeys, messagetext) {
+		var result = "";
+		var literal = new openpgp_packet_literaldata().write_packet(messagetext.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"));
+		util.print_debug_hexstr_dump("literal_packet: |"+literal+"|\n",literal);
+		for (var i = 0; i < publickeys.length; i++) {
+			var onepasssignature = new openpgp_packet_onepasssignature();
+			var onepasssigstr = "";
+			if (i == 0)
+				onepasssigstr = onepasssignature.write_packet(1, openpgp.config.config.prefer_hash_algorithm,  privatekey, false);
+			else
+				onepasssigstr = onepasssignature.write_packet(1, openpgp.config.config.prefer_hash_algorithm,  privatekey, false);
+			util.print_debug_hexstr_dump("onepasssigstr: |"+onepasssigstr+"|\n",onepasssigstr);
+			var datasignature = new openpgp_packet_signature().write_message_signature(1, messagetext.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"), privatekey);
+			util.print_debug_hexstr_dump("datasignature: |"+datasignature.openpgp+"|\n",datasignature.openpgp);
+			if (i == 0) {
+				result = onepasssigstr+literal+datasignature.openpgp;
+			} else {
+				result = onepasssigstr+result+datasignature.openpgp;
+			}
+		}
+		
+		util.print_debug_hexstr_dump("signed packet: |"+result+"|\n",result);
+		// signatures done.. now encryption
+		var sessionkey = openpgp_crypto_generateSessionKey(openpgp.config.config.encryption_cipher); 
+		var result2 = "";
+		
+		// creating session keys for each recipient
+		for (var i = 0; i < publickeys.length; i++) {
+			var pkey = publickeys[i].getEncryptionKey();
+			if (pkey == null) {
+				util.print_error("no encryption key found! Key is for signing only.");
+				return null;
+			}
+			result2 += new openpgp_packet_encryptedsessionkey().
+					write_pub_key_packet(
+						pkey.getKeyId(),
+						pkey.MPIs,
+						pkey.publicKeyAlgorithm,
+						openpgp.config.config.encryption_cipher,
+						sessionkey);
+		}
+		if (openpgp.config.config.integrity_protect) {
+			result2 += new openpgp_packet_encryptedintegrityprotecteddata().write_packet(openpgp.config.config.encryption_cipher, sessionkey, result);
+		} else {
+			result2 += new openpgp_packet_encrypteddata().write_packet(openpgp.config.config.encryption_cipher, sessionkey, result);
+		}
+		return openpgp_encoding_armor(3,result2,null,null);
+	}
+	/**
+	 * creates a binary string representation of an encrypted message.
+	 * The message will be encrypted with the public keys specified 
+	 * @param {Array {obj: [openpgp_msg_publickey]}} publickeys public
+	 * keys to be used to encrypt the message 
+	 * @param {String} messagetext message text to encrypt
+	 * @return {String} a binary string representation of the message
+	 * which can be OpenPGP armored
+	 */
+	function write_encrypted_message(publickeys, messagetext) {
+		var result = "";
+		var literal = new openpgp_packet_literaldata().write_packet(messagetext.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"));
+		util.print_debug_hexstr_dump("literal_packet: |"+literal+"|\n",literal);
+		result = literal;
+		
+		// signatures done.. now encryption
+		var sessionkey = openpgp_crypto_generateSessionKey(openpgp.config.config.encryption_cipher); 
+		var result2 = "";
+		
+		// creating session keys for each recipient
+		for (var i = 0; i < publickeys.length; i++) {
+			var pkey = publickeys[i].getEncryptionKey();
+			if (pkey == null) {
+				util.print_error("no encryption key found! Key is for signing only.");
+				return null;
+			}
+			result2 += new openpgp_packet_encryptedsessionkey().
+					write_pub_key_packet(
+						pkey.getKeyId(),
+						pkey.MPIs,
+						pkey.publicKeyAlgorithm,
+						openpgp.config.config.encryption_cipher,
+						sessionkey);
+		}
+		if (openpgp.config.config.integrity_protect) {
+			result2 += new openpgp_packet_encryptedintegrityprotecteddata().write_packet(openpgp.config.config.encryption_cipher, sessionkey, result);
+		} else {
+			result2 += new openpgp_packet_encrypteddata().write_packet(openpgp.config.config.encryption_cipher, sessionkey, result);
+		}
+		return openpgp_encoding_armor(3,result2,null,null);
+	}
+	
+	/**
+	 * creates a binary string representation a signed message.
+	 * The message will be signed with the specified private key.
+	 * @param {obj: [openpgp_msg_privatekey]} privatekey private
+	 * key to be used to sign the message 
+	 * @param {String} messagetext message text to sign
+	 * @return {Object: text [String]}, openpgp: {String} a binary
+	 *  string representation of the message which can be OpenPGP
+	 *   armored(openpgp) and a text representation of the message (text). This can be directly used to OpenPGP armor the message
+	 */
+	function write_signed_message(privatekey, messagetext) {
+		var sig = new openpgp_packet_signature().write_message_signature(1, messagetext.replace(/\r\n/g,"\n").replace(/\n/,"\r\n"), privatekey);
+		var result = {text: messagetext.replace(/\r\n/g,"\n").replace(/\n/,"\r\n"), openpgp: sig.openpgp, hash: sig.hash};
+		return openpgp_encoding_armor(2,result, null, null)
+	}
+	
+	/**
+	 * generates a new key pair for openpgp. Beta stage. Currently only supports RSA keys, and no subkeys.
+	 * @param {int} keyType to indicate what type of key to make. RSA is 1. Follows algorithms outlined in OpenPGP.
+	 * @param {int} numBits number of bits for the key creation. (should be 1024+, generally)
+	 * @param {string} userId assumes already in form of "User Name <username@email.com>"
+	 * @return {privateKey: [openpgp_msg_privatekey], privateKeyArmored: [string], publicKeyArmored: [string]}
+	 */
+	function generate_key_pair(keyType, numBits, userId, passphrase){
+		var userIdPacket = new openpgp_packet_userid();
+		var userIdString = userIdPacket.write_packet(userId);
+		
+		var keyPair = openpgp_crypto_generateKeyPair(keyType,numBits, passphrase, openpgp.config.config.prefer_hash_algorithm, 3);
+		var privKeyString = keyPair.privateKey;
+		var privKeyPacket = new openpgp_packet_keymaterial().read_priv_key(privKeyString.string,3,privKeyString.string.length);
+		if(!privKeyPacket.decryptSecretMPIs(passphrase))
+		    util.print_error('Issue creating key. Unable to read resulting private key');
+		var privKey = new openpgp_msg_privatekey();
+		privKey.privateKeyPacket = privKeyPacket;
+		privKey.getPreferredSignatureHashAlgorithm = function(){return openpgp.config.config.prefer_hash_algorithm};//need to override this to solve catch 22 to generate signature. 8 is value for SHA256
+		
+		var publicKeyString = privKey.privateKeyPacket.publicKey.data;
+		var hashData = String.fromCharCode(0x99)+ String.fromCharCode(((publicKeyString.length) >> 8) & 0xFF) 
+			+ String.fromCharCode((publicKeyString.length) & 0xFF) +publicKeyString+String.fromCharCode(0xB4) +
+			String.fromCharCode((userId.length) >> 24) +String.fromCharCode(((userId.length) >> 16) & 0xFF) 
+			+ String.fromCharCode(((userId.length) >> 8) & 0xFF) + String.fromCharCode((userId.length) & 0xFF) + userId
+		var signature = new openpgp_packet_signature();
+		signature = signature.write_message_signature(16,hashData, privKey);
+		var publicArmored = openpgp_encoding_armor(4, keyPair.publicKey.string + userIdString + signature.openpgp );
+
+		var privArmored = openpgp_encoding_armor(5,privKeyString.string+userIdString+signature.openpgp);
+		
+		return {privateKey : privKey, privateKeyArmored: privArmored, publicKeyArmored: publicArmored}
+	}
+	
+	this.generate_key_pair = generate_key_pair;
+	this.write_signed_message = write_signed_message; 
+	this.write_signed_and_encrypted_message = write_signed_and_encrypted_message;
+	this.write_encrypted_message = write_encrypted_message;
+	this.read_message = read_message;
+	this.read_publicKey = read_publicKey;
+	this.read_privateKey = read_privateKey;
+	this.init = init;
+}
+
+var openpgp = new _openpgp();
+
+
+// GPG4Browsers - An OpenPGP implementation in javascript
+// Copyright (C) 2011 Recurity Labs GmbH
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+/**
+ * Public-Key Encrypted Session Key Packets (Tag 1)
+ * 
+ * RFC4880 5.1: A Public-Key Encrypted Session Key packet holds the session key
+ * used to encrypt a message. Zero or more Public-Key Encrypted Session Key
+ * packets and/or Symmetric-Key Encrypted Session Key packets may precede a
+ * Symmetrically Encrypted Data Packet, which holds an encrypted message. The
+ * message is encrypted with the session key, and the session key is itself
+ * encrypted and stored in the Encrypted Session Key packet(s). The
+ * Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted
+ * Session Key packet for each OpenPGP key to which the message is encrypted.
+ * The recipient of the message finds a session key that is encrypted to their
+ * public key, decrypts the session key, and then uses the session key to
+ * decrypt the message.
+ */
+function openpgp_packet_encryptedsessionkey() {
+
+	/**
+	 * parsing function for a publickey encrypted session key packet (tag 1).
+	 * 
+	 * @param input
+	 *            [string] payload of a tag 1 packet
+	 * @param position
+	 *            [integer] position to start reading from the input string
+	 * @param len
+	 *            [integer] length of the packet or the remaining length of
+	 *            input at position
 	 * @return [openpgp_packet_encrypteddata] object representation
 	 */
-	function read_packet(input, position, len) {
+	function read_pub_key_packet(input, position, len) {
+		this.tagType = 1;
 		this.packetLength = len;
 		var mypos = position;
-		// A one-octet version number.  The current version is 3.
-		this.version = input.charCodeAt(mypos++);
+		if (len < 10) {
+			util
+					.print_error("openpgp.packet.encryptedsessionkey.js\n" + 'invalid length');
+			return null;
+		}
 
-	     // A one-octet signature type.  Signature types are described in
-	     //   Section 5.2.1.
-		this.type = input.charCodeAt(mypos++);
-
-	     // A one-octet number describing the hash algorithm used.
-		this.hashAlgorithm = input.charCodeAt(mypos++);
-
-	     // A one-octet number describing the public-key algorithm used.
-		this.publicKeyAlgorithm = input.charCodeAt(mypos++);
-	     // An eight-octet number holding the Key ID of the signing key.
-		this.signingKeyId = new openpgp_type_keyid();
-		this.signingKeyId.read_packet(input,mypos);
+		this.version = input[mypos++].charCodeAt();
+		this.keyId = new openpgp_type_keyid();
+		this.keyId.read_packet(input, mypos);
 		mypos += 8;
-		
-	     // A one-octet number holding a flag showing whether the signature
-	     //   is nested.  A zero value indicates that the next packet is
-	     //   another One-Pass Signature packet that describes another
-	     //   signature to be applied to the same message data.
-		this.flags = input.charCodeAt(mypos++);
+		this.publicKeyAlgorithmUsed = input[mypos++].charCodeAt();
+
+		switch (this.publicKeyAlgorithmUsed) {
+		case 1:
+		case 2: // RSA
+			this.MPIs = new Array();
+			this.MPIs[0] = new openpgp_type_mpi();
+			this.MPIs[0].read(input, mypos, mypos - position);
+			break;
+		case 16: // Elgamal
+			this.MPIs = new Array();
+			this.MPIs[0] = new openpgp_type_mpi();
+			this.MPIs[0].read(input, mypos, mypos - position);
+			mypos += this.MPIs[0].packetLength;
+			this.MPIs[1] = new openpgp_type_mpi();
+			this.MPIs[1].read(input, mypos, mypos - position);
+			break;
+		default:
+			util.print_error("openpgp.packet.encryptedsessionkey.js\n"
+					+ "unknown public key packet algorithm type "
+					+ this.publicKeyAlgorithmType);
+			break;
+		}
 		return this;
 	}
 
 	/**
-	 * creates a string representation of a one-pass signature packet
-	 * @param type [integer] Signature types as described in RFC4880 Section 5.2.1.
-	 * @param hashalgorithm [integer] the hash algorithm used within the signature
-	 * @param privatekey [openpgp_msg_privatekey] the private key used to generate the signature
-	 * @param length [integer] length of data to be signed
-	 * @param nested [boolean] boolean showing whether the signature is nested. 
-	 *  "true" indicates that the next packet is another One-Pass Signature packet
-	 *   that describes another signature to be applied to the same message data. 
-	 * @return [String] a string representation of a one-pass signature packet
+	 * create a string representation of a tag 1 packet
+	 * 
+	 * @param publicKeyId
+	 *            [String] the public key id corresponding to publicMPIs key as
+	 *            string
+	 * @param publicMPIs
+	 *            [Array[openpgp_type_mpi]] multiprecision integer objects
+	 *            describing the public key
+	 * @param pubalgo
+	 *            [integer] the corresponding public key algorithm // See
+	 *            RFC4880 9.1
+	 * @param symmalgo
+	 *            [integer] the symmetric cipher algorithm used to encrypt the
+	 *            data within an encrypteddatapacket or
+	 *            encryptedintegrityprotecteddatapacket following this packet //
+	 *            See RFC4880 9.2
+	 * @param sessionkey
+	 *            [String] a string of randombytes representing the session key
+	 * @return [String] the string representation
 	 */
-	function write_packet(type, hashalgorithm, privatekey,length, nested) {
-		var result =""; 
-		
-		result += openpgp_packet.write_packet_header(4,13);
-		result += String.fromCharCode(3);
-		result += String.fromCharCode(type);
-		result += String.fromCharCode(hashalgorithm);
-		result += String.fromCharCode(privatekey.privateKeyPacket.publicKey.publicKeyAlgorithm);
-		result += privatekey.getKeyId();
-		if (nested)
-			result += String.fromCharCode(0);
-		else
-			result += String.fromCharCode(1);
-		
+	function write_pub_key_packet(publicKeyId, publicMPIs, pubalgo, symmalgo,
+			sessionkey) {
+		var result = String.fromCharCode(3);
+		var data = String.fromCharCode(symmalgo);
+		data += sessionkey;
+		var checksum = util.calc_checksum(sessionkey);
+		data += String.fromCharCode((checksum >> 8) & 0xFF);
+		data += String.fromCharCode((checksum) & 0xFF);
+		result += publicKeyId;
+		result += String.fromCharCode(pubalgo);
+		var mpi = new openpgp_type_mpi();
+		var mpiresult = openpgp_crypto_asymetricEncrypt(pubalgo, publicMPIs,
+				mpi.create(openpgp_encoding_eme_pkcs1_encode(data,
+						publicMPIs[0].mpiByteLength)));
+		for ( var i = 0; i < mpiresult.length; i++) {
+			result += mpiresult[i];
+		}
+		result = openpgp_packet.write_packet_header(1, result.length) + result;
 		return result;
 	}
+
+	/**
+	 * parsing function for a symmetric encrypted session key packet (tag 3).
+	 * 
+	 * @param input
+	 *            [string] payload of a tag 1 packet
+	 * @param position
+	 *            [integer] position to start reading from the input string
+	 * @param len
+	 *            [integer] length of the packet or the remaining length of
+	 *            input at position
+	 * @return [openpgp_packet_encrypteddata] object representation
+	 */
+	function read_symmetric_key_packet(input, position, len) {
+		this.tagType = 3;
+		var mypos = position;
+		// A one-octet version number. The only currently defined version is 4.
+		this.version = input[mypos++];
+
+		// A one-octet number describing the symmetric algorithm used.
+		this.symmetricKeyAlgorithmUsed = input[mypos++];
+		// A string-to-key (S2K) specifier, length as defined above.
+		this.s2k = new openpgp_type_s2k();
+		this.s2k.read(input, mypos);
+
+		// Optionally, the encrypted session key itself, which is decrypted
+		// with the string-to-key object.
+		if ((s2k.s2kLength + mypos) < len) {
+			this.encryptedSessionKey = new Array();
+			for ( var i = (mypos - position); i < len; i++) {
+				this.encryptedSessionKey[i] = input[mypos++];
+			}
+		}
+		return this;
+	}
+	/**
+	 * Decrypts the session key (only for public key encrypted session key
+	 * packets (tag 1)
+	 * 
+	 * @param msg
+	 *            [openpgp_msg_message] the message object (with member
+	 *            encryptedData
+	 * @param key
+	 *            [openpgp_msg_privatekey] private key with secMPIs unlocked
+	 * @return [String] the unencrypted session key
+	 */
+	function decrypt(msg, key) {
+		if (this.tagType == 1) {
+			var result = openpgp_crypto_asymetricDecrypt(
+					this.publicKeyAlgorithmUsed, key.publicKey.MPIs,
+					key.secMPIs, this.MPIs).toMPI();
+			var checksum = ((result.charCodeAt(result.length - 2) << 8) + result
+					.charCodeAt(result.length - 1));
+			var decoded = openpgp_encoding_eme_pkcs1_decode(result.substring(2, result.length - 2), key.publicKey.MPIs[0].getByteLength());
+			var sesskey = decoded.substring(1);
+			var algo = decoded.charCodeAt(0);
+			if (msg.encryptedData.tagType == 18)
+				return msg.encryptedData.decrypt(algo, sesskey);
+			else
+				return msg.encryptedData.decrypt_sym(algo, sesskey);
+		} else if (this.tagType == 3) {
+			util
+					.print_error("Symmetric encrypted sessionkey is not supported!");
+			return null;
+		}
+	}
+
+	/**
+	 * Creates a string representation of this object (useful for debug
+	 * purposes)
+	 * 
+	 * @return the string containing a openpgp description
+	 */
+	function toString() {
+		if (this.tagType == 1) {
+			var result = '5.1.  Public-Key Encrypted Session Key Packets (Tag 1)\n'
+					+ '    KeyId:  '
+					+ this.keyId.toString()
+					+ '\n'
+					+ '    length: '
+					+ this.packetLength
+					+ '\n'
+					+ '    version:'
+					+ this.version
+					+ '\n'
+					+ '    pubAlgUs:'
+					+ this.publicKeyAlgorithmUsed + '\n';
+			for ( var i = 0; i < this.MPIs.length; i++) {
+				result += this.MPIs[i].toString();
+			}
+			return result;
+		} else
+			return '5.3 Symmetric-Key Encrypted Session Key Packets (Tag 3)\n'
+					+ '    KeyId:  ' + this.keyId.toString() + '\n'
+					+ '    length: ' + this.packetLength + '\n'
+					+ '    version:' + this.version + '\n' + '    symKeyA:'
+					+ this.symmetricKeyAlgorithmUsed + '\n' + '    s2k:    '
+					+ this.s2k + '\n';
+	}
+
+	this.read_pub_key_packet = read_pub_key_packet;
+	this.read_symmetric_key_packet = read_symmetric_key_packet;
+	this.write_pub_key_packet = write_pub_key_packet;
+	this.toString = toString;
+	this.decrypt = decrypt;
+};
+
+// GPG4Browsers - An OpenPGP implementation in javascript
+// Copyright (C) 2011 Recurity Labs GmbH
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+/** 
+ *  The User Attribute packet is a variation of the User ID packet.  It
+ *  is capable of storing more types of data than the User ID packet,
+ *  which is limited to text.  Like the User ID packet, a User Attribute
+ *  packet may be certified by the key owner ("self-signed") or any other
+ *  key owner who cares to certify it.  Except as noted, a User Attribute
+ *  packet may be used anywhere that a User ID packet may be used.
+ *
+ *  While User Attribute packets are not a required part of the OpenPGP
+ *  standard, implementations SHOULD provide at least enough
+ *  compatibility to properly handle a certification signature on the
+ *  User Attribute packet.  A simple way to do this is by treating the
+ *  User Attribute packet as a User ID packet with opaque contents, but
+ *  an implementation may use any method desired.
+ */
+function openpgp_packet_userattribute() {
+	this.tagType = 17;
+	this.certificationSignatures = new Array();
+	this.certificationRevocationSignatures = new Array();
+	this.revocationSignatures = new Array();
+	this.parentNode = null;
+
+	/**
+	 * parsing function for a user attribute packet (tag 17).
+	 * @param input [string] payload of a tag 17 packet
+	 * @param position [integer] position to start reading from the input string
+	 * @param len [integer] length of the packet or the remaining length of input at position
+	 * @return [openpgp_packet_encrypteddata] object representation
+	 */
+	function read_packet (input, position, len) {
+		var total_len = 0;
+		this.packetLength = len;
+		this.userattributes = new Array();
+		var count = 0;
+		var mypos = position;
+		while (len != total_len) {
+			var current_len = 0;
+			// 4.2.2.1. One-Octet Lengths
+			if (input[mypos].charCodeAt() < 192) {
+				packet_length = input[mypos++].charCodeAt();
+				current_len = 1;
+			// 4.2.2.2. Two-Octet Lengths
+			} else if (input[mypos].charCodeAt() >= 192 && input[mypos].charCodeAt() < 224) {
+				packet_length = ((input[mypos++].charCodeAt() - 192) << 8)
+					+ (input[mypos++].charCodeAt()) + 192;
+				current_len = 2;
+			// 4.2.2.4. Partial Body Lengths
+			} else if (input[mypos].charCodeAt() > 223 && input[mypos].charCodeAt() < 255) {
+				packet_length = 1 << (input[mypos++].charCodeAt() & 0x1F);
+				current_len = 1;
+			// 4.2.2.3. Five-Octet Lengths
+			} else {
+				current_len = 5;
+				mypos++;
+				packet_length = (input[mypos++].charCodeAt() << 24) | (input[mypos++].charCodeAt() << 16)
+					| (input[mypos++].charCodeAt() << 8) | input[mypos++].charCodeAt();
+			}
+			
+			var subpackettype = input[mypos++].charCodeAt();
+			packet_length--;
+			current_len++;
+			this.userattributes[count] = new Array();
+			this.userattributes[count] = input.substring(mypos, mypos + packet_length);
+			mypos += packet_length;
+			total_len += current_len+packet_length;
+		}
+		this.packetLength = mypos - position;
+		return this;
+	}
 	
 	/**
 	 * generates debug output (pretty print)
-	 * @return String which gives some information about the one-pass signature packet
+	 * @return String which gives some information about the user attribute packet
 	 */
 	function toString() {
-		return '5.4.  One-Pass Signature Packets (Tag 4)\n'+
-			   '    length: '+this.packetLength+'\n'+
-			   '    type:   '+this.type+'\n'+
-			   '    keyID:  '+this.signingKeyId.toString()+'\n'+
-			   '    hashA:  '+this.hashAlgorithm+'\n'+
-			   '    pubKeyA:'+this.publicKeyAlgorithm+'\n'+
-			   '    flags:  '+this.flags+'\n'+
-			   '    version:'+this.version+'\n';
+		var result = '5.12.  User Attribute Packet (Tag 17)\n'+
+		             '    AttributePackets: (count = '+this.userattributes.length+')\n';
+		for (var i = 0; i < this.userattributes.length; i++) {
+			result += '    ('+this.userattributes[i].length+') bytes: ['+util.hexidump(this.userattributes[i])+']\n'; 
+		}
+		return result;
+	}
+	
+	/**
+	 * Continue parsing packets belonging to the user attribute packet such as signatures
+	 * @param parent_node [openpgp_*] the parent object
+	 * @param input [String] input string to read the packet(s) from
+	 * @param position [integer] start position for the parser
+	 * @param len [integer] length of the packet(s) or remaining length of input
+	 * @return [integer] length of nodes read
+	 */
+	function read_nodes(parent_node, input, position, len) {
+		
+		this.parentNode = parent_node;
+		var exit = false;
+		var pos = position;
+		var l = len;
+		while (input.length != pos) {
+			var result = openpgp_packet.read_packet(input, pos, l);
+			if (result == null) {
+				util.print_error("openpgp.packet.userattribute.js\n"+'[user_attr] parsing ends here @:' + pos + " l:" + l);
+				break;
+			} else {
+				switch (result.tagType) {
+				case 2: // Signature Packet
+					if (result.signatureType > 15
+							&& result.signatureType < 20) // certification
+						// //
+						// signature
+						this.certificationSignatures[this.certificationSignatures.length] = result;
+					else if (result.signatureType == 32) // certification revocation signature
+						this.certificationRevocationSignatures[this.certificationRevocationSignatures.length] = result;
+					pos += result.packetLength + result.headerLength;
+					l = len - (pos - position);
+					break;
+				default:
+					this.data = input;
+					this.position = position - parent_node.packetLength;
+					this.len = pos - position;
+					return this.len;
+					break;
+				}
+			}
+		}
+		this.data = input;
+		this.position = position - parent_node.packetLength;
+		this.len = pos - position;
+		return this.len;
+
 	}
 	
 	this.read_packet = read_packet;
+	this.read_nodes = read_nodes;
 	this.toString = toString;
-	this.write_packet = write_packet;
+	
 };// GPG4Browsers - An OpenPGP implementation in javascript
 // Copyright (C) 2011 Recurity Labs GmbH
 // 
@@ -133,22 +813,26 @@ function openpgp_packet_onepasssignature() {
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
 /**
- * Implementation of the strange "Marker packet" (Tag 10)
+ * Implementation of the Symmetrically Encrypted Data Packet (Tag 9)
  * 
- * RFC4880 5.8: An experimental version of PGP used this packet as the Literal
- * packet, but no released version of PGP generated Literal packets with this
- * tag. With PGP 5.x, this packet has been reassigned and is reserved for use as
- * the Marker packet.
- * 
- * Such a packet MUST be ignored when received.
+ * RFC4880 5.7: The Symmetrically Encrypted Data packet contains data encrypted
+ * with a symmetric-key algorithm. When it has been decrypted, it contains other
+ * packets (usually a literal data packet or compressed data packet, but in
+ * theory other Symmetrically Encrypted Data packets or sequences of packets
+ * that form whole OpenPGP messages).
  */
-function openpgp_packet_marker() {
-	this.tagType = 10;
+
+function openpgp_packet_encrypteddata() {
+	this.tagType = 9;
+	this.packetLength = null;
+	this.encryptedData = null;
+	this.decryptedData = null;
+
 	/**
-	 * parsing function for a literal data packet (tag 10).
+	 * parsing function for the packet.
 	 * 
 	 * @param input
-	 *            [string] payload of a tag 10 packet
+	 *            [string] payload of a tag 9 packet
 	 * @param position
 	 *            [integer] position to start reading from the input string
 	 * @param len
@@ -157,28 +841,65 @@ function openpgp_packet_marker() {
 	 * @return [openpgp_packet_encrypteddata] object representation
 	 */
 	function read_packet(input, position, len) {
-		this.packetLength = 3;
-		if (input[position].charCodeAt() == 0x50 && // P
-				input[position + 1].charCodeAt() == 0x47 && // G
-				input[position + 2].charCodeAt() == 0x50) // P
-			return this;
-		// marker packet does not contain "PGP"
-		return null;
+		var mypos = position;
+		this.packetLength = len;
+		// - Encrypted data, the output of the selected symmetric-key cipher
+		// operating in OpenPGP's variant of Cipher Feedback (CFB) mode.
+		this.encryptedData = input.substring(position, position + len);
+		return this;
 	}
 
 	/**
-	 * Generates Debug output
+	 * symmetrically decrypt the packet data
 	 * 
-	 * @return String which gives some information about the keymaterial
+	 * @param symmetric_algorithm_type
+	 *            [integer] symmetric key algorithm to use // See RFC4880 9.2
+	 * @param key
+	 *            [String] key as string with the corresponding length to the
+	 *            algorithm
+	 * @return the decrypted data;
 	 */
-	function toString() {
-		return "5.8.  Marker Packet (Obsolete Literal Packet) (Tag 10)\n"
-				+ "     packet reads: \"PGP\"\n";
+	function decrypt_sym(symmetric_algorithm_type, key) {
+		this.decryptedData = openpgp_crypto_symmetricDecrypt(
+				symmetric_algorithm_type, key, this.encryptedData, true);
+		util.print_debug("openpgp.packet.encryptedintegrityprotecteddata.js\n"+
+				"data: "+util.hexstrdump(this.decryptedData));
+		return this.decryptedData;
 	}
 
-	this.read_packet = read_packet;
+	/**
+	 * Creates a string representation of the packet
+	 * 
+	 * @param algo
+	 *            [Integer] symmetric key algorithm to use // See RFC4880 9.2
+	 * @param key
+	 *            [String] key as string with the corresponding length to the
+	 *            algorithm
+	 * @param data
+	 *            [String] data to be
+	 * @return [String] string-representation of the packet
+	 */
+	function write_packet(algo, key, data) {
+		var result = "";
+		result += openpgp_crypto_symmetricEncrypt(
+				openpgp_crypto_getPrefixRandom(algo), algo, key, data, true);
+		result = openpgp_packet.write_packet_header(9, result.length) + result;
+		return result;
+	}
+
+	function toString() {
+		return '5.7.  Symmetrically Encrypted Data Packet (Tag 9)\n'
+				+ '    length:  ' + this.packetLength + '\n'
+				+ '    Used symmetric algorithm: ' + this.algorithmType + '\n'
+				+ '    encrypted data: Bytes ['
+				+ util.hexstrdump(this.encryptedData) + ']\n';
+	}
+	this.decrypt_sym = decrypt_sym;
 	this.toString = toString;
-}// GPG4Browsers - An OpenPGP implementation in javascript
+	this.read_packet = read_packet;
+	this.write_packet = write_packet;
+};
+// GPG4Browsers - An OpenPGP implementation in javascript
 // Copyright (C) 2011 Recurity Labs GmbH
 // 
 // This library is free software; you can redistribute it and/or
@@ -950,1738 +1671,6 @@ function openpgp_packet_signature() {
 // License along with this library; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
-/**
- * Implementation of the Sym. Encrypted Integrity Protected Data Packet (Tag 18)
- * 
- * RFC4880 5.13: The Symmetrically Encrypted Integrity Protected Data packet is
- * a variant of the Symmetrically Encrypted Data packet. It is a new feature
- * created for OpenPGP that addresses the problem of detecting a modification to
- * encrypted data. It is used in combination with a Modification Detection Code
- * packet.
- */
-
-function openpgp_packet_encryptedintegrityprotecteddata() {
-	this.tagType = 18;
-	this.version = null; // integer == 1
-	this.packetLength = null; // integer
-	this.encryptedData = null; // string
-	this.decrytpedData = null; // string
-	this.hash = null; // string
-	/**
-	 * parsing function for the packet.
-	 * 
-	 * @param input
-	 *            [string] payload of a tag 18 packet
-	 * @param position
-	 *            [integer] position to start reading from the input string
-	 * @param len
-	 *            [integer] length of the packet or the remaining length of
-	 *            input at position
-	 * @return [openpgp_packet_encryptedintegrityprotecteddata] object
-	 *         representation
-	 */
-	function read_packet(input, position, len) {
-		this.packetLength = len;
-		// - A one-octet version number. The only currently defined value is
-		// 1.
-		this.version = input[position].charCodeAt();
-		if (this.version != 1) {
-			util
-					.print_error('openpgp.packet.encryptedintegrityprotecteddata.js\nunknown encrypted integrity protected data packet version: '
-							+ this.version
-							+ " , @ "
-							+ position
-							+ "hex:"
-							+ util.hexstrdump(input));
-			return null;
-		}
-		// - Encrypted data, the output of the selected symmetric-key cipher
-		//   operating in Cipher Feedback mode with shift amount equal to the
-		//   block size of the cipher (CFB-n where n is the block size).
-		this.encryptedData = input.substring(position + 1, position + 1 + len);
-		util.print_debug("openpgp.packet.encryptedintegrityprotecteddata.js\n"
-				+ this.toString());
-		return this;
-	}
-
-	/**
-	 * Creates a string representation of a Sym. Encrypted Integrity Protected
-	 * Data Packet (tag 18) (see RFC4880 5.13)
-	 * 
-	 * @param symmetric_algorithm
-	 *            [integer] the selected symmetric encryption algorithm to be
-	 *            used
-	 * @param key
-	 *            [String] the key of cipher blocksize length to be used
-	 * @param data
-	 *            plaintext data to be encrypted within the packet
-	 * @return a string representation of the packet
-	 */
-	function write_packet(symmetric_algorithm, key, data) {
-
-		var prefixrandom = openpgp_crypto_getPrefixRandom(symmetric_algorithm);
-		var prefix = prefixrandom
-				+ prefixrandom.charAt(prefixrandom.length - 2)
-				+ prefixrandom.charAt(prefixrandom.length - 1);
-		var tohash = data;
-		tohash += String.fromCharCode(0xD3);
-		tohash += String.fromCharCode(0x14);
-		util.print_debug_hexstr_dump("data to be hashed:"
-				, prefix + tohash);
-		tohash += str_sha1(prefix + tohash);
-		util.print_debug_hexstr_dump("hash:"
-				, tohash.substring(tohash.length - 20,
-						tohash.length));
-		var result = openpgp_crypto_symmetricEncrypt(prefixrandom,
-				symmetric_algorithm, key, tohash, false).substring(0,
-				prefix.length + tohash.length);
-		var header = openpgp_packet.write_packet_header(18, result.length + 1)
-				+ String.fromCharCode(1);
-		this.encryptedData = result;
-		return header + result;
-	}
-
-	/**
-	 * Decrypts the encrypted data contained in this object read_packet must
-	 * have been called before
-	 * 
-	 * @param symmetric_algorithm_type
-	 *            [integer] the selected symmetric encryption algorithm to be
-	 *            used
-	 * @param key
-	 *            [String] the key of cipher blocksize length to be used
-	 * @return the decrypted data of this packet
-	 */
-	function decrypt(symmetric_algorithm_type, key) {
-		this.decryptedData = openpgp_crypto_symmetricDecrypt(
-				symmetric_algorithm_type, key, this.encryptedData, false);
-		// there must be a modification detection code packet as the
-		// last packet and everything gets hashed except the hash itself
-		this.hash = str_sha1(openpgp_crypto_MDCSystemBytes(
-				symmetric_algorithm_type, key, this.encryptedData)
-				+ this.decryptedData.substring(0,
-						this.decryptedData.length - 20));
-		util.print_debug_hexstr_dump("calc hash = ", this.hash);
-		if (this.hash == this.decryptedData.substring(
-				this.decryptedData.length - 20, this.decryptedData.length))
-			return this.decryptedData;
-		else
-			util
-					.print_error("Decryption stopped: discovered a modification of encrypted data.");
-		return null;
-	}
-
-	function toString() {
-	    var data = '';
-	    if(openpgp.config.debug)
-	        data = '    data: Bytes ['
-				+ util.hexstrdump(this.encryptedData) + ']';
-	    
-		return '5.13.  Sym. Encrypted Integrity Protected Data Packet (Tag 18)\n'
-				+ '    length:  '
-				+ this.packetLength
-				+ '\n'
-				+ '    version: '
-				+ this.version
-				+ '\n'
-				+ data;
-	}
-
-	this.write_packet = write_packet;
-	this.read_packet = read_packet;
-	this.toString = toString;
-	this.decrypt = decrypt;
-};
-// GPG4Browsers - An OpenPGP implementation in javascript
-// Copyright (C) 2011 Recurity Labs GmbH
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-/**
- * Implementation of the Modification Detection Code Packet (Tag 19)
- * 
- * RFC4880 5.14: The Modification Detection Code packet contains a SHA-1 hash of
- * plaintext data, which is used to detect message modification. It is only used
- * with a Symmetrically Encrypted Integrity Protected Data packet. The
- * Modification Detection Code packet MUST be the last packet in the plaintext
- * data that is encrypted in the Symmetrically Encrypted Integrity Protected
- * Data packet, and MUST appear in no other place.
- */
-
-function openpgp_packet_modificationdetectioncode() {
-	this.tagType = 19;
-	this.hash = null;
-	/**
-	 * parsing function for a modification detection code packet (tag 19).
-	 * 
-	 * @param input
-	 *            [String] payload of a tag 19 packet
-	 * @param position
-	 *            [Integer] position to start reading from the input string
-	 * @param len
-	 *            [Integer] length of the packet or the remaining length of
-	 *            input at position
-	 * @return [openpgp_packet_encrypteddata] object representation
-	 */
-	function read_packet(input, position, len) {
-		this.packetLength = len;
-
-		if (len != 20) {
-			util
-					.print_error("openpgp.packet.modificationdetectioncode.js\n"
-							+ 'invalid length for a modification detection code packet!'
-							+ len);
-			return null;
-		}
-		// - A 20-octet SHA-1 hash of the preceding plaintext data of the
-		// Symmetrically Encrypted Integrity Protected Data packet,
-		// including prefix data, the tag octet, and length octet of the
-		// Modification Detection Code packet.
-		this.hash = input.substring(position, position + 20);
-		return this;
-	}
-
-	/*
-	 * this packet is created within the encryptedintegrityprotected packet
-	 * function write_packet(data) { }
-	 */
-
-	/**
-	 * generates debug output (pretty print)
-	 * 
-	 * @return String which gives some information about the modification
-	 *         detection code
-	 */
-	function toString() {
-		return '5.14 Modification detection code packet\n' + '    bytes ('
-				+ this.hash.length + '): [' + util.hexstrdump(this.hash) + ']';
-	}
-	this.read_packet = read_packet;
-	this.toString = toString;
-};
-// GPG4Browsers - An OpenPGP implementation in javascript
-// Copyright (C) 2011 Recurity Labs GmbH
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-/**
- * A User ID packet consists of UTF-8 text that is intended to represent
- * the name and email address of the key holder.  By convention, it
- * includes an RFC 2822 [RFC2822] mail name-addr, but there are no
- * restrictions on its content.  The packet length in the header
- * specifies the length of the User ID. 
- */
-
-function openpgp_packet_userid() {
-	this.tagType = 13;
-	this.certificationSignatures = new Array();
-	this.certificationRevocationSignatures = new Array();
-	this.revocationSignatures = new Array();
-	this.parentNode = null;
-
-	/**
-	 * parsing function for a user id packet (tag 13).
-	 * @param input [string] payload of a tag 13 packet
-	 * @param position [integer] position to start reading from the input string
-	 * @param len [integer] length of the packet or the remaining length of input at position
-	 * @return [openpgp_packet_encrypteddata] object representation
-	 */
-	function read_packet(input, position, len) {
-		this.text = '';
-		this.packetLength = len;
-
-		for ( var i = 0; i < len; i++) {
-			this.text += input[position + i];
-		}
-		return this;
-	}
-
-	/**
-	 * creates a string representation of the user id packet
-	 * @param user_id [String] the user id as string ("John Doe <john.doe@mail.us")
-	 * @return [String] string representation
-	 */
-	function write_packet(user_id) {
-		this.text = user_id;
-		var result = openpgp_packet.write_packet_header(13,this.text.length);
-		result += this.text;
-		return result;
-	}
-
-	/**
-	 * Continue parsing packets belonging to the userid packet such as signatures
-	 * @param parent_node [openpgp_*] the parent object
-	 * @param input [String] input string to read the packet(s) from
-	 * @param position [integer] start position for the parser
-	 * @param len [integer] length of the packet(s) or remaining length of input
-	 * @return [integer] length of nodes read
-	 */
-	function read_nodes(parent_node, input, position, len) {
-		if (parent_node.tagType == 6) { // public key
-			this.parentNode = parent_node;
-			var pos = position;
-			var l = len;
-			while (input.length != pos) {
-				var result = openpgp_packet.read_packet(input, pos, l - (pos - position));
-				if (result == null) {
-					util.print_error('[user_id] parsing ends here @:' + pos + " l:" + l);
-					break;
-				} else {
-					
-					pos += result.packetLength + result.headerLength;
-					l = input.length - pos;
-					switch (result.tagType) {
-					case 2: // Signature Packet
-						if (result.signatureType > 15
-								&& result.signatureType < 20) { // certification
-							// //
-							// signature
-							this.certificationSignatures[this.certificationSignatures.length] = result;
-							break;
-						} else if (result.signatureType == 48) {// certification revocation signature
-							this.certificationRevocationSignatures[this.certificationRevocationSignatures.length] = result;
-							break;
-						} else if (result.signatureType == 24) { // omg. standalone signature 
-							this.certificationSignatures[this.certificationSignatures.length] = result;
-							break;
-						} else {
-							util.debug("unknown sig t: "+result.signatureType+"@"+(pos - (result.packetLength + result.headerLength)));
-						}
-					default:
-						this.data = input;
-						this.position = position - parent_node.packetLength;
-						this.len = pos - position -(result.headerLength + result.packetLength);
-						return this.len;
-					}
-				}
-			}
-			this.data = input;
-			this.position = position - parent_node.packetLength;
-			this.len = pos - position -(result.headerLength + result.packetLength);
-			return this.len;
-		} else if (parent_node.tagType == 5) { // secret Key
-			this.parentNode = parent_node;
-			var exit = false;
-			var pos = position;
-			while (input.length != pos) {
-				var result = openpgp_packet.read_packet(input, pos, l - (pos - position));
-				if (result == null) {
-					util.print_error('parsing ends here @:' + pos + " l:" + l);
-					break;
-				} else {
-					pos += result.packetLength + result.headerLength;
-					l = input.length - pos;
-					switch (result.tagType) {
-					case 2: // Signature Packet certification signature
-						if (result.signatureType > 15
-								&& result.signatureType < 20)
-							this.certificationSignatures[this.certificationSignatures.length] = result;
-						// certification revocation signature
-						else if (result.signatureType == 48)
-							this.certificationRevocationSignatures[this.certificationRevocationSignatures.length] = result;
-					default:
-						this.data = input;
-						this.position = position - parent_node.packetLength;
-						this.len = pos - position -(result.headerLength + result.packetLength);
-						return this.len;
-					}
-				}
-			}
-		} else {
-			util.print_error("unknown parent node for a userId packet "+parent_node.tagType);
-		}
-	}
-	
-	/**
-	 * generates debug output (pretty print)
-	 * @return String which gives some information about the user id packet
-	 */
-	function toString() {
-		var result = '     5.11.  User ID Packet (Tag 13)\n' + '    text ('
-				+ this.text.length + '): "' + this.text.replace("<", "&lt;")
-				+ '"\n';
-		result +="certification signatures:\n";
-		for (var i = 0; i < this.certificationSignatures.length; i++) {
-			result += "        "+this.certificationSignatures[i].toString();
-		}
-		result +="certification revocation signatures:\n";
-		for (var i = 0; i < this.certificationRevocationSignatures.length; i++) {
-			result += "        "+this.certificationRevocationSignatures[i].toString();
-		}
-		return result;
-	}
-
-	/**
-	 * lookup function to find certification revocation signatures
-	 * @param keyId string containing the key id of the issuer of this signature
-	 * @return a CertificationRevocationSignature if found; otherwise null
-	 */
-	function hasCertificationRevocationSignature(keyId) {
-		for (var i = 0; i < this.certificationRevocationSignatures.length; i++) {
-			if ((this.certificationRevocationSignatures[i].version == 3 &&
-				 this.certificationRevocationSignatures[i].keyId == keyId) ||
-				(this.certificationRevocationSignatures[i].version == 4 &&
-				 this.certificationRevocationSignatures[i].issuerKeyId == keyId))
-				return this.certificationRevocationSignatures[i];
-		}
-		return null;
-	}
-
-	/**
-	 * Verifies all certification signatures. This method does not consider possible revocation signatures.
-	 * @param publicKeyPacket the top level key material
-	 * @return an array of integers corresponding to the array of certification signatures. The meaning of each integer is the following:
-	 * 0 = bad signature
-	 * 1 = signature expired
-	 * 2 = issuer key not available
-	 * 3 = revoked
-	 * 4 = signature valid
-	 * 5 = signature by key owner expired
-	 * 6 = signature by key owner revoked
-	 */
-	function verifyCertificationSignatures(publicKeyPacket) {
-		result = new Array();
-		for (var i = 0 ; i < this.certificationSignatures.length; i++) {
-			// A certification signature (type 0x10 through 0x13) hashes the User
-			// ID being bound to the key into the hash context after the above
-			// data.  A V3 certification hashes the contents of the User ID or
-			// attribute packet packet, without any header.  A V4 certification
-			// hashes the constant 0xB4 for User ID certifications or the constant
-			// 0xD1 for User Attribute certifications, followed by a four-octet
-			// number giving the length of the User ID or User Attribute data, and
-			// then the User ID or User Attribute data.
-
-			if (this.certificationSignatures[i].version == 4) {
-				if (this.certificationSignatures[i].signatureExpirationTime != null &&
-						this.certificationSignatures[i].signatureExpirationTime != null &&
-						this.certificationSignatures[i].signatureExpirationTime != 0 &&
-						!this.certificationSignatures[i].signatureNeverExpires &&
-						new Date(this.certificationSignatures[i].creationTime.getTime() +(this.certificationSignatures[i].signatureExpirationTime*1000)) < new Date()) {
-					if (this.certificationSignatures[i].issuerKeyId == publicKeyPacket.getKeyId())
-						result[i] = 5;
-					else
-						result[i] = 1;
-					continue;
-				}
-				if (this.certificationSignatures[i].issuerKeyId == null) {
-					result[i] = 0;
-					continue;
-				}
-				var issuerPublicKey = openpgp.keyring.getPublicKeysForKeyId(this.certificationSignatures[i].issuerKeyId);
-				if (issuerPublicKey == null || issuerPublicKey.length == 0) {
-					result[i] = 2;
-					continue;
-				}
-				// TODO: try to verify all returned issuer public keys (key ids are not unique!)
-				var issuerPublicKey = issuerPublicKey[0];
-				var signingKey = issuerPublicKey.obj.getSigningKey();
-				if (signingKey == null) {
-					result[i] = 0;
-					continue;
-				}
-				var revocation = this.hasCertificationRevocationSignature(this.certificationSignatures[i].issuerKeyId);
-				if (revocation != null && revocation.creationTime > 
-					this.certificationSignatures[i].creationTime) {
-					var signaturedata = String.fromCharCode(0x99)+ publicKeyPacket.header.substring(1)+
-					publicKeyPacket.data+String.fromCharCode(0xB4)+
-					String.fromCharCode((this.text.length >> 24) & 0xFF)+
-					String.fromCharCode((this.text.length >> 16) & 0xFF)+
-					String.fromCharCode((this.text.length >>  8) & 0xFF)+
-					String.fromCharCode((this.text.length) & 0xFF)+
-					this.text;
-					if (revocation.verify(signaturedata, signingKey)) {
-						if (this.certificationSignatures[i].issuerKeyId == publicKeyPacket.getKeyId())
-							result[i] = 6;
-						else
-							result[i] = 3;
-						continue;
-					}
-				}
-				var signaturedata = String.fromCharCode(0x99)+ publicKeyPacket.header.substring(1)+
-						publicKeyPacket.data+String.fromCharCode(0xB4)+
-						String.fromCharCode((this.text.length >> 24) & 0xFF)+
-						String.fromCharCode((this.text.length >> 16) & 0xFF)+
-						String.fromCharCode((this.text.length >>  8) & 0xFF)+
-						String.fromCharCode((this.text.length) & 0xFF)+
-						this.text;
-				if (this.certificationSignatures[i].verify(signaturedata, signingKey)) {
-					result[i] = 4;
-				} else
-				result[i] = 0;
-			} else if (this.certificationSignatures[i].version == 3) {
-				if (this.certificationSignatures[i].keyId == null) {
-					result[i] = 0;
-					continue;
-				}
-				var issuerPublicKey = openpgp.keyring.getPublicKeysForKeyId(this.certificationSignatures[i].keyId);
-				if (issuerPublicKey == null || issuerPublicKey.length == 0) {
-					result[i] = 2;
-					continue;
-				}
-				issuerPublicKey = issuerPublicKey[0];
-				var signingKey = publicKey.obj.getSigningKey();
-				if (signingKey == null) {
-					result[i] = 0;
-					continue;
-				}
-				var revocation = this.hasCertificationRevocationSignature(this.certificationSignatures[i].keyId);
-				if (revocation != null && revocation.creationTime > 
-					this.certificationSignatures[i].creationTime) {
-					var signaturedata = String.fromCharCode(0x99)+ this.publicKeyPacket.header.substring(1)+
-					this.publicKeyPacket.data+this.text;
-					if (revocation.verify(signaturedata, signingKey)) {
-						if (revocation.keyId == publicKeyPacket.getKeyId())
-							result[i] = 6;
-						else
-							result[i] = 3;
-						continue;
-					}
-				}
-				var signaturedata = String.fromCharCode(0x99)+ publicKeyPacket.header.substring(1)+
-					publicKeyPacket.data+this.text;
-				if (this.certificationSignatures[i].verify(signaturedata, signingKey)) {
-					result[i] = 4;
-				} else 
-				result[i] = 0;
-			} else {
-				result[i] = 0;
-			}
-		}
-		return result;
-	}
-
-	/**
-	 * verifies the signatures of the user id
-	 * @return 0 if the userid is valid; 1 = userid expired; 2 = userid revoked
-	 */
-	function verify(publicKeyPacket) {
-		var result = this.verifyCertificationSignatures(publicKeyPacket);
-		if (result.indexOf(6) != -1)
-			return 2;
-		if (result.indexOf(5) != -1)
-			return 1;
-		return 0;
-	}
-
-	// TODO: implementation missing
-	function addCertification(publicKeyPacket, privateKeyPacket) {
-		
-	}
-
-	// TODO: implementation missing
-	function revokeCertification(publicKeyPacket, privateKeyPacket) {
-		
-	}
-
-	this.hasCertificationRevocationSignature = hasCertificationRevocationSignature;
-	this.verifyCertificationSignatures = verifyCertificationSignatures;
-	this.verify = verify;
-	this.read_packet = read_packet;
-	this.write_packet = write_packet;
-	this.toString = toString;
-	this.read_nodes = read_nodes;
-}
-// GPG4Browsers - An OpenPGP implementation in javascript
-// Copyright (C) 2011 Recurity Labs GmbH
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-/**
- * Public-Key Encrypted Session Key Packets (Tag 1)
- * 
- * RFC4880 5.1: A Public-Key Encrypted Session Key packet holds the session key
- * used to encrypt a message. Zero or more Public-Key Encrypted Session Key
- * packets and/or Symmetric-Key Encrypted Session Key packets may precede a
- * Symmetrically Encrypted Data Packet, which holds an encrypted message. The
- * message is encrypted with the session key, and the session key is itself
- * encrypted and stored in the Encrypted Session Key packet(s). The
- * Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted
- * Session Key packet for each OpenPGP key to which the message is encrypted.
- * The recipient of the message finds a session key that is encrypted to their
- * public key, decrypts the session key, and then uses the session key to
- * decrypt the message.
- */
-function openpgp_packet_encryptedsessionkey() {
-
-	/**
-	 * parsing function for a publickey encrypted session key packet (tag 1).
-	 * 
-	 * @param input
-	 *            [string] payload of a tag 1 packet
-	 * @param position
-	 *            [integer] position to start reading from the input string
-	 * @param len
-	 *            [integer] length of the packet or the remaining length of
-	 *            input at position
-	 * @return [openpgp_packet_encrypteddata] object representation
-	 */
-	function read_pub_key_packet(input, position, len) {
-		this.tagType = 1;
-		this.packetLength = len;
-		var mypos = position;
-		if (len < 10) {
-			util
-					.print_error("openpgp.packet.encryptedsessionkey.js\n" + 'invalid length');
-			return null;
-		}
-
-		this.version = input[mypos++].charCodeAt();
-		this.keyId = new openpgp_type_keyid();
-		this.keyId.read_packet(input, mypos);
-		mypos += 8;
-		this.publicKeyAlgorithmUsed = input[mypos++].charCodeAt();
-
-		switch (this.publicKeyAlgorithmUsed) {
-		case 1:
-		case 2: // RSA
-			this.MPIs = new Array();
-			this.MPIs[0] = new openpgp_type_mpi();
-			this.MPIs[0].read(input, mypos, mypos - position);
-			break;
-		case 16: // Elgamal
-			this.MPIs = new Array();
-			this.MPIs[0] = new openpgp_type_mpi();
-			this.MPIs[0].read(input, mypos, mypos - position);
-			mypos += this.MPIs[0].packetLength;
-			this.MPIs[1] = new openpgp_type_mpi();
-			this.MPIs[1].read(input, mypos, mypos - position);
-			break;
-		default:
-			util.print_error("openpgp.packet.encryptedsessionkey.js\n"
-					+ "unknown public key packet algorithm type "
-					+ this.publicKeyAlgorithmType);
-			break;
-		}
-		return this;
-	}
-
-	/**
-	 * create a string representation of a tag 1 packet
-	 * 
-	 * @param publicKeyId
-	 *            [String] the public key id corresponding to publicMPIs key as
-	 *            string
-	 * @param publicMPIs
-	 *            [Array[openpgp_type_mpi]] multiprecision integer objects
-	 *            describing the public key
-	 * @param pubalgo
-	 *            [integer] the corresponding public key algorithm // See
-	 *            RFC4880 9.1
-	 * @param symmalgo
-	 *            [integer] the symmetric cipher algorithm used to encrypt the
-	 *            data within an encrypteddatapacket or
-	 *            encryptedintegrityprotecteddatapacket following this packet //
-	 *            See RFC4880 9.2
-	 * @param sessionkey
-	 *            [String] a string of randombytes representing the session key
-	 * @return [String] the string representation
-	 */
-	function write_pub_key_packet(publicKeyId, publicMPIs, pubalgo, symmalgo,
-			sessionkey) {
-		var result = String.fromCharCode(3);
-		var data = String.fromCharCode(symmalgo);
-		data += sessionkey;
-		var checksum = util.calc_checksum(sessionkey);
-		data += String.fromCharCode((checksum >> 8) & 0xFF);
-		data += String.fromCharCode((checksum) & 0xFF);
-		result += publicKeyId;
-		result += String.fromCharCode(pubalgo);
-		var mpi = new openpgp_type_mpi();
-		var mpiresult = openpgp_crypto_asymetricEncrypt(pubalgo, publicMPIs,
-				mpi.create(openpgp_encoding_eme_pkcs1_encode(data,
-						publicMPIs[0].mpiByteLength)));
-		for ( var i = 0; i < mpiresult.length; i++) {
-			result += mpiresult[i];
-		}
-		result = openpgp_packet.write_packet_header(1, result.length) + result;
-		return result;
-	}
-
-	/**
-	 * parsing function for a symmetric encrypted session key packet (tag 3).
-	 * 
-	 * @param input
-	 *            [string] payload of a tag 1 packet
-	 * @param position
-	 *            [integer] position to start reading from the input string
-	 * @param len
-	 *            [integer] length of the packet or the remaining length of
-	 *            input at position
-	 * @return [openpgp_packet_encrypteddata] object representation
-	 */
-	function read_symmetric_key_packet(input, position, len) {
-		this.tagType = 3;
-		var mypos = position;
-		// A one-octet version number. The only currently defined version is 4.
-		this.version = input[mypos++];
-
-		// A one-octet number describing the symmetric algorithm used.
-		this.symmetricKeyAlgorithmUsed = input[mypos++];
-		// A string-to-key (S2K) specifier, length as defined above.
-		this.s2k = new openpgp_type_s2k();
-		this.s2k.read(input, mypos);
-
-		// Optionally, the encrypted session key itself, which is decrypted
-		// with the string-to-key object.
-		if ((s2k.s2kLength + mypos) < len) {
-			this.encryptedSessionKey = new Array();
-			for ( var i = (mypos - position); i < len; i++) {
-				this.encryptedSessionKey[i] = input[mypos++];
-			}
-		}
-		return this;
-	}
-	/**
-	 * Decrypts the session key (only for public key encrypted session key
-	 * packets (tag 1)
-	 * 
-	 * @param msg
-	 *            [openpgp_msg_message] the message object (with member
-	 *            encryptedData
-	 * @param key
-	 *            [openpgp_msg_privatekey] private key with secMPIs unlocked
-	 * @return [String] the unencrypted session key
-	 */
-	function decrypt(msg, key) {
-		if (this.tagType == 1) {
-			var result = openpgp_crypto_asymetricDecrypt(
-					this.publicKeyAlgorithmUsed, key.publicKey.MPIs,
-					key.secMPIs, this.MPIs).toMPI();
-			var checksum = ((result.charCodeAt(result.length - 2) << 8) + result
-					.charCodeAt(result.length - 1));
-			var decoded = openpgp_encoding_eme_pkcs1_decode(result.substring(2, result.length - 2), key.publicKey.MPIs[0].getByteLength());
-			var sesskey = decoded.substring(1);
-			var algo = decoded.charCodeAt(0);
-			if (msg.encryptedData.tagType == 18)
-				return msg.encryptedData.decrypt(algo, sesskey);
-			else
-				return msg.encryptedData.decrypt_sym(algo, sesskey);
-		} else if (this.tagType == 3) {
-			util
-					.print_error("Symmetric encrypted sessionkey is not supported!");
-			return null;
-		}
-	}
-
-	/**
-	 * Creates a string representation of this object (useful for debug
-	 * purposes)
-	 * 
-	 * @return the string containing a openpgp description
-	 */
-	function toString() {
-		if (this.tagType == 1) {
-			var result = '5.1.  Public-Key Encrypted Session Key Packets (Tag 1)\n'
-					+ '    KeyId:  '
-					+ this.keyId.toString()
-					+ '\n'
-					+ '    length: '
-					+ this.packetLength
-					+ '\n'
-					+ '    version:'
-					+ this.version
-					+ '\n'
-					+ '    pubAlgUs:'
-					+ this.publicKeyAlgorithmUsed + '\n';
-			for ( var i = 0; i < this.MPIs.length; i++) {
-				result += this.MPIs[i].toString();
-			}
-			return result;
-		} else
-			return '5.3 Symmetric-Key Encrypted Session Key Packets (Tag 3)\n'
-					+ '    KeyId:  ' + this.keyId.toString() + '\n'
-					+ '    length: ' + this.packetLength + '\n'
-					+ '    version:' + this.version + '\n' + '    symKeyA:'
-					+ this.symmetricKeyAlgorithmUsed + '\n' + '    s2k:    '
-					+ this.s2k + '\n';
-	}
-
-	this.read_pub_key_packet = read_pub_key_packet;
-	this.read_symmetric_key_packet = read_symmetric_key_packet;
-	this.write_pub_key_packet = write_pub_key_packet;
-	this.toString = toString;
-	this.decrypt = decrypt;
-};
-
-// GPG4Browsers - An OpenPGP implementation in javascript
-// Copyright (C) 2011 Recurity Labs GmbH
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-/**
- * Implementation of the Literal Data Packet (Tag 11)
- * 
- * RFC4880 5.9: A Literal Data packet contains the body of a message; data that
- * is not to be further interpreted.
- */
-function openpgp_packet_literaldata() {
-	this.tagType = 11;
-
-	/**
-	 * parsing function for a literal data packet (tag 11).
-	 * 
-	 * @param input
-	 *            [string] payload of a tag 11 packet
-	 * @param position
-	 *            [integer] position to start reading from the input string
-	 * @param len
-	 *            [integer] length of the packet or the remaining length of
-	 *            input at position
-	 * @return [openpgp_packet_encrypteddata] object representation
-	 */
-	function read_packet(input, position, len) {
-		this.packetLength = len;
-		// - A one-octet field that describes how the data is formatted.
-
-		this.format = input[position];
-		this.filename = input.substr(position + 2, input
-				.charCodeAt(position + 1));
-		this.date = new Date(parseInt(input.substr(position + 2
-				+ input.charCodeAt(position + 1), 4)) * 1000);
-		this.data = input.substring(position + 6
-				+ input.charCodeAt(position + 1));
-		return this;
-	}
-
-	/**
-	 * Creates a string representation of the packet
-	 * 
-	 * @param data
-	 *            [String] the data to be inserted as body
-	 * @return [String] string-representation of the packet
-	 */
-	function write_packet(data) {
-		data = data.replace(/\r\n/g, "\n").replace(/\n/g, "\r\n");
-		this.filename = "msg.txt";
-		this.date = new Date();
-		this.format = 't';
-		var result = openpgp_packet.write_packet_header(11, data.length + 6
-				+ this.filename.length);
-		result += this.format;
-		result += String.fromCharCode(this.filename.length);
-		result += this.filename;
-		result += String
-				.fromCharCode((Math.round(this.date.getTime() / 1000) >> 24) & 0xFF);
-		result += String
-				.fromCharCode((Math.round(this.date.getTime() / 1000) >> 16) & 0xFF);
-		result += String
-				.fromCharCode((Math.round(this.date.getTime() / 1000) >> 8) & 0xFF);
-		result += String
-				.fromCharCode(Math.round(this.date.getTime() / 1000) & 0xFF);
-		result += data;
-		this.data = data;
-		return result;
-	}
-
-	/**
-	 * generates debug output (pretty print)
-	 * 
-	 * @return String which gives some information about the keymaterial
-	 */
-	function toString() {
-		return '5.9.  Literal Data Packet (Tag 11)\n' + '    length: '
-				+ this.packetLength + '\n' + '    format: ' + this.format
-				+ '\n' + '    filename:' + this.filename + '\n'
-				+ '    date:   ' + this.date + '\n' + '    data:  |'
-				+ this.data + '|\n' + '    rdata: |' + this.real_data + '|\n';
-	}
-
-	this.read_packet = read_packet;
-	this.toString = toString;
-	this.write_packet = write_packet;
-}
-// GPG4Browsers - An OpenPGP implementation in javascript
-// Copyright (C) 2011 Recurity Labs GmbH
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-/**
- * Implementation of the Symmetrically Encrypted Data Packet (Tag 9)
- * 
- * RFC4880 5.7: The Symmetrically Encrypted Data packet contains data encrypted
- * with a symmetric-key algorithm. When it has been decrypted, it contains other
- * packets (usually a literal data packet or compressed data packet, but in
- * theory other Symmetrically Encrypted Data packets or sequences of packets
- * that form whole OpenPGP messages).
- */
-
-function openpgp_packet_encrypteddata() {
-	this.tagType = 9;
-	this.packetLength = null;
-	this.encryptedData = null;
-	this.decryptedData = null;
-
-	/**
-	 * parsing function for the packet.
-	 * 
-	 * @param input
-	 *            [string] payload of a tag 9 packet
-	 * @param position
-	 *            [integer] position to start reading from the input string
-	 * @param len
-	 *            [integer] length of the packet or the remaining length of
-	 *            input at position
-	 * @return [openpgp_packet_encrypteddata] object representation
-	 */
-	function read_packet(input, position, len) {
-		var mypos = position;
-		this.packetLength = len;
-		// - Encrypted data, the output of the selected symmetric-key cipher
-		// operating in OpenPGP's variant of Cipher Feedback (CFB) mode.
-		this.encryptedData = input.substring(position, position + len);
-		return this;
-	}
-
-	/**
-	 * symmetrically decrypt the packet data
-	 * 
-	 * @param symmetric_algorithm_type
-	 *            [integer] symmetric key algorithm to use // See RFC4880 9.2
-	 * @param key
-	 *            [String] key as string with the corresponding length to the
-	 *            algorithm
-	 * @return the decrypted data;
-	 */
-	function decrypt_sym(symmetric_algorithm_type, key) {
-		this.decryptedData = openpgp_crypto_symmetricDecrypt(
-				symmetric_algorithm_type, key, this.encryptedData, true);
-		util.print_debug("openpgp.packet.encryptedintegrityprotecteddata.js\n"+
-				"data: "+util.hexstrdump(this.decryptedData));
-		return this.decryptedData;
-	}
-
-	/**
-	 * Creates a string representation of the packet
-	 * 
-	 * @param algo
-	 *            [Integer] symmetric key algorithm to use // See RFC4880 9.2
-	 * @param key
-	 *            [String] key as string with the corresponding length to the
-	 *            algorithm
-	 * @param data
-	 *            [String] data to be
-	 * @return [String] string-representation of the packet
-	 */
-	function write_packet(algo, key, data) {
-		var result = "";
-		result += openpgp_crypto_symmetricEncrypt(
-				openpgp_crypto_getPrefixRandom(algo), algo, key, data, true);
-		result = openpgp_packet.write_packet_header(9, result.length) + result;
-		return result;
-	}
-
-	function toString() {
-		return '5.7.  Symmetrically Encrypted Data Packet (Tag 9)\n'
-				+ '    length:  ' + this.packetLength + '\n'
-				+ '    Used symmetric algorithm: ' + this.algorithmType + '\n'
-				+ '    encrypted data: Bytes ['
-				+ util.hexstrdump(this.encryptedData) + ']\n';
-	}
-	this.decrypt_sym = decrypt_sym;
-	this.toString = toString;
-	this.read_packet = read_packet;
-	this.write_packet = write_packet;
-};
-// GPG4Browsers - An OpenPGP implementation in javascript
-// Copyright (C) 2011 Recurity Labs GmbH
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-/** 
- *  The User Attribute packet is a variation of the User ID packet.  It
- *  is capable of storing more types of data than the User ID packet,
- *  which is limited to text.  Like the User ID packet, a User Attribute
- *  packet may be certified by the key owner ("self-signed") or any other
- *  key owner who cares to certify it.  Except as noted, a User Attribute
- *  packet may be used anywhere that a User ID packet may be used.
- *
- *  While User Attribute packets are not a required part of the OpenPGP
- *  standard, implementations SHOULD provide at least enough
- *  compatibility to properly handle a certification signature on the
- *  User Attribute packet.  A simple way to do this is by treating the
- *  User Attribute packet as a User ID packet with opaque contents, but
- *  an implementation may use any method desired.
- */
-function openpgp_packet_userattribute() {
-	this.tagType = 17;
-	this.certificationSignatures = new Array();
-	this.certificationRevocationSignatures = new Array();
-	this.revocationSignatures = new Array();
-	this.parentNode = null;
-
-	/**
-	 * parsing function for a user attribute packet (tag 17).
-	 * @param input [string] payload of a tag 17 packet
-	 * @param position [integer] position to start reading from the input string
-	 * @param len [integer] length of the packet or the remaining length of input at position
-	 * @return [openpgp_packet_encrypteddata] object representation
-	 */
-	function read_packet (input, position, len) {
-		var total_len = 0;
-		this.packetLength = len;
-		this.userattributes = new Array();
-		var count = 0;
-		var mypos = position;
-		while (len != total_len) {
-			var current_len = 0;
-			// 4.2.2.1. One-Octet Lengths
-			if (input[mypos].charCodeAt() < 192) {
-				packet_length = input[mypos++].charCodeAt();
-				current_len = 1;
-			// 4.2.2.2. Two-Octet Lengths
-			} else if (input[mypos].charCodeAt() >= 192 && input[mypos].charCodeAt() < 224) {
-				packet_length = ((input[mypos++].charCodeAt() - 192) << 8)
-					+ (input[mypos++].charCodeAt()) + 192;
-				current_len = 2;
-			// 4.2.2.4. Partial Body Lengths
-			} else if (input[mypos].charCodeAt() > 223 && input[mypos].charCodeAt() < 255) {
-				packet_length = 1 << (input[mypos++].charCodeAt() & 0x1F);
-				current_len = 1;
-			// 4.2.2.3. Five-Octet Lengths
-			} else {
-				current_len = 5;
-				mypos++;
-				packet_length = (input[mypos++].charCodeAt() << 24) | (input[mypos++].charCodeAt() << 16)
-					| (input[mypos++].charCodeAt() << 8) | input[mypos++].charCodeAt();
-			}
-			
-			var subpackettype = input[mypos++].charCodeAt();
-			packet_length--;
-			current_len++;
-			this.userattributes[count] = new Array();
-			this.userattributes[count] = input.substring(mypos, mypos + packet_length);
-			mypos += packet_length;
-			total_len += current_len+packet_length;
-		}
-		this.packetLength = mypos - position;
-		return this;
-	}
-	
-	/**
-	 * generates debug output (pretty print)
-	 * @return String which gives some information about the user attribute packet
-	 */
-	function toString() {
-		var result = '5.12.  User Attribute Packet (Tag 17)\n'+
-		             '    AttributePackets: (count = '+this.userattributes.length+')\n';
-		for (var i = 0; i < this.userattributes.length; i++) {
-			result += '    ('+this.userattributes[i].length+') bytes: ['+util.hexidump(this.userattributes[i])+']\n'; 
-		}
-		return result;
-	}
-	
-	/**
-	 * Continue parsing packets belonging to the user attribute packet such as signatures
-	 * @param parent_node [openpgp_*] the parent object
-	 * @param input [String] input string to read the packet(s) from
-	 * @param position [integer] start position for the parser
-	 * @param len [integer] length of the packet(s) or remaining length of input
-	 * @return [integer] length of nodes read
-	 */
-	function read_nodes(parent_node, input, position, len) {
-		
-		this.parentNode = parent_node;
-		var exit = false;
-		var pos = position;
-		var l = len;
-		while (input.length != pos) {
-			var result = openpgp_packet.read_packet(input, pos, l);
-			if (result == null) {
-				util.print_error("openpgp.packet.userattribute.js\n"+'[user_attr] parsing ends here @:' + pos + " l:" + l);
-				break;
-			} else {
-				switch (result.tagType) {
-				case 2: // Signature Packet
-					if (result.signatureType > 15
-							&& result.signatureType < 20) // certification
-						// //
-						// signature
-						this.certificationSignatures[this.certificationSignatures.length] = result;
-					else if (result.signatureType == 32) // certification revocation signature
-						this.certificationRevocationSignatures[this.certificationRevocationSignatures.length] = result;
-					pos += result.packetLength + result.headerLength;
-					l = len - (pos - position);
-					break;
-				default:
-					this.data = input;
-					this.position = position - parent_node.packetLength;
-					this.len = pos - position;
-					return this.len;
-					break;
-				}
-			}
-		}
-		this.data = input;
-		this.position = position - parent_node.packetLength;
-		this.len = pos - position;
-		return this.len;
-
-	}
-	
-	this.read_packet = read_packet;
-	this.read_nodes = read_nodes;
-	this.toString = toString;
-	
-};// GPG4Browsers - An OpenPGP implementation in javascript
-// Copyright (C) 2011 Recurity Labs GmbH
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-function _openpgp_packet() {
-	/**
-	 * Encodes a given integer of length to the openpgp length specifier to a
-	 * string
-	 * 
-	 * @param length
-	 *            [Integer] of the length to encode
-	 * @return string with openpgp length representation
-	 */
-	function encode_length(length) {
-		result = "";
-		if (length < 192) {
-			result += String.fromCharCode(length);
-		} else if (length > 191 && length < 8384) {
-			/*
-			 * let a = (total data packet length) - 192 let bc = two octet
-			 * representation of a let d = b + 192
-			 */
-			result += String.fromCharCode(((length - 192) >> 8) + 192);
-			result += String.fromCharCode((length - 192) & 0xFF);
-		} else {
-			result += String.fromCharCode(255);
-			result += String.fromCharCode((length >> 24) & 0xFF);
-			result += String.fromCharCode((length >> 16) & 0xFF);
-			result += String.fromCharCode((length >> 8) & 0xFF);
-			result += String.fromCharCode(length & 0xFF);
-		}
-		return result;
-	}
-	this.encode_length = encode_length;
-
-	/**
-	 * Writes a packet header version 4 with the given tag_type and length to a
-	 * string
-	 * 
-	 * @param tag_type
-	 *            integer of tag type
-	 * @param length
-	 *            integer length of the payload
-	 * @return string of the header
-	 */
-	function write_packet_header(tag_type, length) {
-		/* we're only generating v4 packet headers here */
-		var result = "";
-		result += String.fromCharCode(0xC0 | tag_type);
-		result += encode_length(length);
-		return result;
-	}
-
-	/**
-	 * Writes a packet header Version 3 with the given tag_type and length to a
-	 * string
-	 * 
-	 * @param tag_type
-	 *            integer of tag type
-	 * @param length
-	 *            integer length of the payload
-	 * @return string of the header
-	 */
-	function write_old_packet_header(tag_type, length) {
-		var result = "";
-		if (length < 256) {
-			result += String.fromCharCode(0x80 | (tag_type << 2));
-			result += String.fromCharCode(length);
-		} else if (length < 65536) {
-			result += String.fromCharCode(0x80 | (tag_type << 2) | 1);
-			result += String.fromCharCode(length >> 8);
-			result += String.fromCharCode(length & 0xFF);
-		} else {
-			result += String.fromCharCode(0x80 | (tag_type << 2) | 2);
-			result += String.fromCharCode((length >> 24) & 0xFF);
-			result += String.fromCharCode((length >> 16) & 0xFF);
-			result += String.fromCharCode((length >> 8) & 0xFF);
-			result += String.fromCharCode(length & 0xFF);
-		}
-		return result;
-	}
-	this.write_old_packet_header = write_old_packet_header;
-	this.write_packet_header = write_packet_header;
-	/**
-	 * Generic static Packet Parser function
-	 * 
-	 * @param input
-	 *            [String] input stream as string
-	 * @param position
-	 *            [integer] position to start parsing
-	 * @param len
-	 *            [integer] length of the input from position on
-	 * @return [openpgp_packet_*] returns a parsed openpgp_packet
-	 */
-	function read_packet(input, position, len) {
-		// some sanity checks
-		if (input == null || input.length <= position
-				|| input.substring(position).length < 2
-				|| (input[position].charCodeAt() & 0x80) == 0) {
-			util
-					.print_error("Error during parsing. This message / key is propably not containing a valid OpenPGP format.");
-			return null;
-		}
-		var mypos = position;
-		var tag = -1;
-		var format = -1;
-
-		format = 0; // 0 = old format; 1 = new format
-		if ((input[mypos].charCodeAt() & 0x40) != 0) {
-			format = 1;
-		}
-
-		var packet_length_type;
-		if (format) {
-			// new format header
-			tag = input[mypos].charCodeAt() & 0x3F; // bit 5-0
-		} else {
-			// old format header
-			tag = (input[mypos].charCodeAt() & 0x3F) >> 2; // bit 5-2
-			packet_length_type = input[mypos].charCodeAt() & 0x03; // bit 1-0
-		}
-
-		// header octet parsing done
-		mypos++;
-
-		// parsed length from length field
-		var len = 0;
-		var bodydata = null;
-
-		// used for partial body lengths
-		var real_packet_length = -1;
-		if (!format) {
-			// 4.2.1. Old Format Packet Lengths
-			switch (packet_length_type) {
-			case 0: // The packet has a one-octet length. The header is 2 octets
-				// long.
-				packet_length = input[mypos++].charCodeAt();
-				break;
-			case 1: // The packet has a two-octet length. The header is 3 octets
-				// long.
-				packet_length = (input[mypos++].charCodeAt() << 8)
-						| input[mypos++].charCodeAt();
-				break;
-			case 2: // The packet has a four-octet length. The header is 5
-				// octets long.
-				packet_length = (input[mypos++].charCodeAt() << 24)
-						| (input[mypos++].charCodeAt() << 16)
-						| (input[mypos++].charCodeAt() << 8)
-						| input[mypos++].charCodeAt();
-				break;
-			default:
-				// 3 - The packet is of indeterminate length. The header is 1
-				// octet long, and the implementation must determine how long
-				// the packet is. If the packet is in a file, this means that
-				// the packet extends until the end of the file. In general, 
-				// an implementation SHOULD NOT use indeterminate-length 
-				// packets except where the end of the data will be clear 
-				// from the context, and even then it is better to use a 
-				// definite length, or a new format header. The new format 
-				// headers described below have a mechanism for precisely
-				// encoding data of indeterminate length.
-			}
-
-		} else // 4.2.2. New Format Packet Lengths
-		{
-
-			// 4.2.2.1. One-Octet Lengths
-			if (input[mypos].charCodeAt() < 192) {
-				packet_length = input[mypos++].charCodeAt();
-				util.print_debug("1 byte length:" + packet_length);
-				// 4.2.2.2. Two-Octet Lengths
-			} else if (input[mypos].charCodeAt() >= 192
-					&& input[mypos].charCodeAt() < 224) {
-				packet_length = ((input[mypos++].charCodeAt() - 192) << 8)
-						+ (input[mypos++].charCodeAt()) + 192;
-				util.print_debug("2 byte length:" + packet_length);
-				// 4.2.2.4. Partial Body Lengths
-			} else if (input[mypos].charCodeAt() > 223
-					&& input[mypos].charCodeAt() < 255) {
-				packet_length = 1 << (input[mypos++].charCodeAt() & 0x1F);
-				util.print_debug("4 byte length:" + packet_length);
-				// EEEK, we're reading the full data here...
-				var mypos2 = mypos + packet_length;
-				bodydata = input.substring(mypos, mypos + packet_length);
-				while (true) {
-					if (input[mypos2].charCodeAt() < 192) {
-						var tmplen = input[mypos2++].charCodeAt();
-						packet_length += tmplen;
-						bodydata += input.substring(mypos2, mypos2 + tmplen);
-						mypos2 += tmplen;
-						break;
-					} else if (input[mypos2].charCodeAt() >= 192
-							&& input[mypos2].charCodeAt() < 224) {
-						var tmplen = ((input[mypos2++].charCodeAt() - 192) << 8)
-								+ (input[mypos2++].charCodeAt()) + 192;
-						packet_length += tmplen;
-						bodydata += input.substring(mypos2, mypos2 + tmplen);
-						mypos2 += tmplen;
-						break;
-					} else if (input[mypos2].charCodeAt() > 223
-							&& input[mypos2].charCodeAt() < 255) {
-						var tmplen = 1 << (input[mypos2++].charCodeAt() & 0x1F);
-						packet_length += tmplen;
-						bodydata += input.substring(mypos2, mypos2 + tmplen);
-						mypos2 += tmplen;
-					} else {
-						mypos2++;
-						var tmplen = (input[mypos2++].charCodeAt() << 24)
-								| (input[mypos2++].charCodeAt() << 16)
-								| (input[mypos2++].charCodeAt() << 8)
-								| input[mypos2++].charCodeAt();
-						bodydata += input.substring(mypos2, mypos2 + tmplen);
-						packet_length += tmplen;
-						mypos2 += tmplen;
-						break;
-					}
-				}
-				real_packet_length = mypos2;
-				// 4.2.2.3. Five-Octet Lengths
-			} else {
-				mypos++;
-				packet_length = (input[mypos++].charCodeAt() << 24)
-						| (input[mypos++].charCodeAt() << 16)
-						| (input[mypos++].charCodeAt() << 8)
-						| input[mypos++].charCodeAt();
-			}
-		}
-
-		// if there was'nt a partial body length: use the specified
-		// packet_length
-		if (real_packet_length == -1) {
-			real_packet_length = packet_length;
-		}
-
-		if (bodydata == null) {
-			bodydata = input.substring(mypos, mypos + real_packet_length);
-		}
-
-		// alert('tag type: '+this.tag+' length: '+packet_length);
-		var version = 1; // (old format; 2= new format)
-		// if (input[mypos++].charCodeAt() > 15)
-		// version = 2;
-
-		switch (tag) {
-		case 0: // Reserved - a packet tag MUST NOT have this value
-			break;
-		case 1: // Public-Key Encrypted Session Key Packet
-			var result = new openpgp_packet_encryptedsessionkey();
-			if (result.read_pub_key_packet(bodydata, 0, packet_length) != null) {
-				result.headerLength = mypos - position;
-				result.packetLength = real_packet_length;
-				return result;
-			}
-			break;
-		case 2: // Signature Packet
-			var result = new openpgp_packet_signature();
-			if (result.read_packet(bodydata, 0, packet_length) != null) {
-				result.headerLength = mypos - position;
-				result.packetLength = real_packet_length;
-				return result;
-			}
-			break;
-		case 3: // Symmetric-Key Encrypted Session Key Packet
-			var result = new openpgp_packet_encryptedsessionkey();
-			if (result.read_symmetric_key_packet(bodydata, 0, packet_length) != null) {
-				result.headerLength = mypos - position;
-				result.packetLength = real_packet_length;
-				return result;
-			}
-			break;
-		case 4: // One-Pass Signature Packet
-			var result = new openpgp_packet_onepasssignature();
-			if (result.read_packet(bodydata, 0, packet_length)) {
-				result.headerLength = mypos - position;
-				result.packetLength = real_packet_length;
-				return result;
-			}
-			break;
-		case 5: // Secret-Key Packet
-			var result = new openpgp_packet_keymaterial();
-			result.header = input.substring(position, mypos);
-			if (result.read_tag5(bodydata, 0, packet_length) != null) {
-				result.headerLength = mypos - position;
-				result.packetLength = real_packet_length;
-				return result;
-			}
-			break;
-		case 6: // Public-Key Packet
-			var result = new openpgp_packet_keymaterial();
-			result.header = input.substring(position, mypos);
-			if (result.read_tag6(bodydata, 0, packet_length) != null) {
-				result.headerLength = mypos - position;
-				result.packetLength = real_packet_length;
-				return result;
-			}
-			break;
-		case 7: // Secret-Subkey Packet
-			var result = new openpgp_packet_keymaterial();
-			if (result.read_tag7(bodydata, 0, packet_length) != null) {
-				result.headerLength = mypos - position;
-				result.packetLength = real_packet_length;
-				return result;
-			}
-			break;
-		case 8: // Compressed Data Packet
-			var result = new openpgp_packet_compressed();
-			if (result.read_packet(bodydata, 0, packet_length) != null) {
-				result.headerLength = mypos - position;
-				result.packetLength = real_packet_length;
-				return result;
-			}
-			break;
-		case 9: // Symmetrically Encrypted Data Packet
-			var result = new openpgp_packet_encrypteddata();
-			if (result.read_packet(bodydata, 0, packet_length) != null) {
-				result.headerLength = mypos - position;
-				result.packetLength = real_packet_length;
-				return result;
-			}
-			break;
-		case 10: // Marker Packet = PGP (0x50, 0x47, 0x50)
-			var result = new openpgp_packet_marker();
-			if (result.read_packet(bodydata, 0, packet_length) != null) {
-				result.headerLength = mypos - position;
-				result.packetLength = real_packet_length;
-				return result;
-			}
-			break;
-		case 11: // Literal Data Packet
-			var result = new openpgp_packet_literaldata();
-			if (result.read_packet(bodydata, 0, packet_length) != null) {
-				result.headerLength = mypos - position;
-				result.header = input.substring(position, mypos);
-				result.packetLength = real_packet_length;
-				return result;
-			}
-			break;
-		case 12: // Trust Packet
-			// TODO: to be implemented
-			break;
-		case 13: // User ID Packet
-			var result = new openpgp_packet_userid();
-			if (result.read_packet(bodydata, 0, packet_length) != null) {
-				result.headerLength = mypos - position;
-				result.packetLength = real_packet_length;
-				return result;
-			}
-			break;
-		case 14: // Public-Subkey Packet
-			var result = new openpgp_packet_keymaterial();
-			result.header = input.substring(position, mypos);
-			if (result.read_tag14(bodydata, 0, packet_length) != null) {
-				result.headerLength = mypos - position;
-				result.packetLength = real_packet_length;
-				return result;
-			}
-			break;
-		case 17: // User Attribute Packet
-			var result = new openpgp_packet_userattribute();
-			if (result.read_packet(bodydata, 0, packet_length) != null) {
-				result.headerLength = mypos - position;
-				result.packetLength = real_packet_length;
-				return result;
-			}
-			break;
-		case 18: // Sym. Encrypted and Integrity Protected Data Packet
-			var result = new openpgp_packet_encryptedintegrityprotecteddata();
-			if (result.read_packet(bodydata, 0, packet_length) != null) {
-				result.headerLength = mypos - position;
-				result.packetLength = real_packet_length;
-				return result;
-			}
-			break;
-		case 19: // Modification Detection Code Packet
-			var result = new openpgp_packet_modificationdetectioncode();
-			if (result.read_packet(bodydata, 0, packet_length) != null) {
-				result.headerLength = mypos - position;
-				result.packetLength = real_packet_length;
-				return result;
-			}
-			break;
-		default:
-			util.print_error("openpgp.packet.js\n"
-					+ "[ERROR] openpgp_packet: failed to parse packet @:"
-					+ mypos + "\nchar:'"
-					+ util.hexstrdump(input.substring(mypos)) + "'\ninput:"
-					+ util.hexstrdump(input));
-			return null;
-			break;
-		}
-	}
-
-	this.read_packet = read_packet;
-}
-
-var openpgp_packet = new _openpgp_packet();
-// GPG4Browsers - An OpenPGP implementation in javascript
-// Copyright (C) 2011 Recurity Labs GmbH
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-/**
- * Implementation of the Compressed Data Packet (Tag 8)
- * 
- * RFC4880 5.6:
- * The Compressed Data packet contains compressed data.  Typically, this
- * packet is found as the contents of an encrypted packet, or following
- * a Signature or One-Pass Signature packet, and contains a literal data
- * packet.
- */   
-function openpgp_packet_compressed() {
-	this.tagType = 8;
-	
-	/**
-	 * parsing function for the packet.
-	 * @param input [string] payload of a tag 8 packet
-	 * @param position [integer] position to start reading from the input string
-	 * @param len [integer] length of the packet or the remaining length of input at position
-	 * @return [openpgp_packet_compressed] object representation
-	 */
-	function read_packet (input, position, len) {
-		this.packetLength = len;
-		var mypos = position;
-		// One octet that gives the algorithm used to compress the packet.
-		this.type = input.charCodeAt(mypos++);
-		// Compressed data, which makes up the remainder of the packet.
-		this.compressedData = input.substring(position+1, position+len);
-		return this;
-	}
-	/**
-	 * decompression method for decompressing the compressed data
-	 * read by read_packet
-	 * @return [String] the decompressed data
-	 */
-	function decompress() {
-		if (this.decompressedData != null)
-			return this.decompressedData;
-
-		if (this.type == null)
-			return null;
-
-		switch (this.type) {
-		case 0: // - Uncompressed
-			this.decompressedData = this.compressedData;
-			break;
-		case 1: // - ZIP [RFC1951]
-            var inflater = new zip.Inflater();
-            var output = inflater.append(util.str2Uint8Array(this.compressedData));
-            var outputString = util.Uint8Array2str(output);
-            var packet = openpgp_packet.read_packet(outputString,0,outputString.length);
-            util.print_info('Decompressed packet [Type 1-ZIP]: ' + packet);
-            this.decompressedData = packet.data;
-			break;
-		case 2: // - ZLIB [RFC1950]
-			var compressionMethod = this.compressedData.charCodeAt(0) % 0x10; //RFC 1950. Bits 0-3 Compression Method
-			//Bits 4-7 RFC 1950 are LZ77 Window. Generally this value is 7 == 32k window size.
-			//2nd Byte in RFC 1950 is for "FLAGs" Allows for a Dictionary (how is this defined). Basic checksum, and compression level.
-			if (compressionMethod == 8) { //CM 8 is for DEFLATE, RFC 1951
-				// remove 4 bytes ADLER32 checksum from the end
-				var compData = this.compressedData.substring(0, this.compressedData.length - 4);
-				var radix = s2r(compData).replace(/\n/g,"");
-				var outputString = JXG.decompress(radix);
-				//TODO check ADLER32 checksum
-				var packet = openpgp_packet.read_packet(outputString, 0, outputString.length);
-				util.print_info('Decompressed packet [Type 2-ZLIB]: ' + packet);
-				this.decompressedData = packet.data;
-			} else {
-				util.print_error("Compression algorithm ZLIB only supports DEFLATE compression method.");
-			}
-			break;
-		case 3: //  - BZip2 [BZ2]
-			// TODO: need to implement this
-			util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");
-			break;
-		default:
-			util.print_error("Compression algorithm unknown :"+this.type);
-			break;
-		}
-		util.print_debug("decompressed:"+util.hexstrdump(this.decompressedData));
-		return this.decompressedData; 
-	}
-
-	/**
-	 * Compress the packet data (member decompressedData)
-	 * @param type [integer] algorithm to be used // See RFC 4880 9.3
-	 * @param data [String] data to be compressed
-	 * @return [String] The compressed data stored in attribute compressedData
-	 */
-	function compress(type, data) {
-		this.type = type;
-		this.decompressedData = data;
-		switch (this.type) {
-		case 0: // - Uncompressed
-			this.compressedData = this.decompressedData;
-			break;
-		case 1: // - ZIP [RFC1951]
-			util.print_error("Compression algorithm ZIP [RFC1951] is not implemented.");
-			break;
-		case 2: // - ZLIB [RFC1950]
-			// TODO: need to implement this
-			util.print_error("Compression algorithm ZLIB [RFC1950] is not implemented.");
-			break;
-		case 3: //  - BZip2 [BZ2]
-			// TODO: need to implement this
-			util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");
-			break;
-		default:
-			util.print_error("Compression algorithm unknown :"+this.type);
-			break;
-		}
-		this.packetLength = this.compressedData.length +1;
-		return this.compressedData; 
-	}
-	
-	/**
-	 * creates a string representation of the packet
-	 * @param algorithm [integer] algorithm to be used // See RFC 4880 9.3
-	 * @param data [String] data to be compressed
-	 * @return [String] string-representation of the packet
-	 */
-	function write_packet(algorithm, data) {
-		this.decompressedData = data;
-		if (algorithm == null) {
-			this.type = 1;
-		}
-		var result = String.fromCharCode(this.type)+this.compress(this.type);
-		return openpgp_packet.write_packet_header(8, result.length)+result;
-	}
-	
-	/**
-	 * pretty printing the packet (useful for debug purposes)
-	 * @return [String]
-	 */
-	function toString() {
-		return '5.6.  Compressed Data Packet (Tag 8)\n'+
-		   '    length:  '+this.packetLength+'\n'+
-			   '    Compression Algorithm = '+this.type+'\n'+
-		       '    Compressed Data: Byte ['+util.hexstrdump(this.compressedData)+']\n';
-	}
-	
-	this.read_packet = read_packet;
-	this.toString = toString;
-	this.compress = compress;
-	this.decompress = decompress;
-	this.write_packet = write_packet;
-};
-// GPG4Browsers - An OpenPGP implementation in javascript
-// Copyright (C) 2011 Recurity Labs GmbH
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
 /**
  * Implementation of the Key Material Packet (Tag 5,6,7,14)
  *   
@@ -3468,3657 +2457,6 @@ function openpgp_packet_keymaterial() {
 	this.write_private_key = write_private_key;
 	this.write_public_key = write_public_key;
 }
-/**
- * A fast MD5 JavaScript implementation
- * Copyright (c) 2012 Joseph Myers
- * http://www.myersdaily.org/joseph/javascript/md5-text.html
- *
- * Permission to use, copy, modify, and distribute this software
- * and its documentation for any purposes and without
- * fee is hereby granted provided that this copyright notice
- * appears in all copies.
- *
- * Of course, this soft is provided "as is" without express or implied
- * warranty of any kind.
- */
-
-function MD5(entree) {
-	var hex = md5(entree);
-	var bin = util.hex2bin(hex);
-	return bin;
-}
-
-function md5cycle(x, k) {
-var a = x[0], b = x[1], c = x[2], d = x[3];
-
-a = ff(a, b, c, d, k[0], 7, -680876936);
-d = ff(d, a, b, c, k[1], 12, -389564586);
-c = ff(c, d, a, b, k[2], 17,  606105819);
-b = ff(b, c, d, a, k[3], 22, -1044525330);
-a = ff(a, b, c, d, k[4], 7, -176418897);
-d = ff(d, a, b, c, k[5], 12,  1200080426);
-c = ff(c, d, a, b, k[6], 17, -1473231341);
-b = ff(b, c, d, a, k[7], 22, -45705983);
-a = ff(a, b, c, d, k[8], 7,  1770035416);
-d = ff(d, a, b, c, k[9], 12, -1958414417);
-c = ff(c, d, a, b, k[10], 17, -42063);
-b = ff(b, c, d, a, k[11], 22, -1990404162);
-a = ff(a, b, c, d, k[12], 7,  1804603682);
-d = ff(d, a, b, c, k[13], 12, -40341101);
-c = ff(c, d, a, b, k[14], 17, -1502002290);
-b = ff(b, c, d, a, k[15], 22,  1236535329);
-
-a = gg(a, b, c, d, k[1], 5, -165796510);
-d = gg(d, a, b, c, k[6], 9, -1069501632);
-c = gg(c, d, a, b, k[11], 14,  643717713);
-b = gg(b, c, d, a, k[0], 20, -373897302);
-a = gg(a, b, c, d, k[5], 5, -701558691);
-d = gg(d, a, b, c, k[10], 9,  38016083);
-c = gg(c, d, a, b, k[15], 14, -660478335);
-b = gg(b, c, d, a, k[4], 20, -405537848);
-a = gg(a, b, c, d, k[9], 5,  568446438);
-d = gg(d, a, b, c, k[14], 9, -1019803690);
-c = gg(c, d, a, b, k[3], 14, -187363961);
-b = gg(b, c, d, a, k[8], 20,  1163531501);
-a = gg(a, b, c, d, k[13], 5, -1444681467);
-d = gg(d, a, b, c, k[2], 9, -51403784);
-c = gg(c, d, a, b, k[7], 14,  1735328473);
-b = gg(b, c, d, a, k[12], 20, -1926607734);
-
-a = hh(a, b, c, d, k[5], 4, -378558);
-d = hh(d, a, b, c, k[8], 11, -2022574463);
-c = hh(c, d, a, b, k[11], 16,  1839030562);
-b = hh(b, c, d, a, k[14], 23, -35309556);
-a = hh(a, b, c, d, k[1], 4, -1530992060);
-d = hh(d, a, b, c, k[4], 11,  1272893353);
-c = hh(c, d, a, b, k[7], 16, -155497632);
-b = hh(b, c, d, a, k[10], 23, -1094730640);
-a = hh(a, b, c, d, k[13], 4,  681279174);
-d = hh(d, a, b, c, k[0], 11, -358537222);
-c = hh(c, d, a, b, k[3], 16, -722521979);
-b = hh(b, c, d, a, k[6], 23,  76029189);
-a = hh(a, b, c, d, k[9], 4, -640364487);
-d = hh(d, a, b, c, k[12], 11, -421815835);
-c = hh(c, d, a, b, k[15], 16,  530742520);
-b = hh(b, c, d, a, k[2], 23, -995338651);
-
-a = ii(a, b, c, d, k[0], 6, -198630844);
-d = ii(d, a, b, c, k[7], 10,  1126891415);
-c = ii(c, d, a, b, k[14], 15, -1416354905);
-b = ii(b, c, d, a, k[5], 21, -57434055);
-a = ii(a, b, c, d, k[12], 6,  1700485571);
-d = ii(d, a, b, c, k[3], 10, -1894986606);
-c = ii(c, d, a, b, k[10], 15, -1051523);
-b = ii(b, c, d, a, k[1], 21, -2054922799);
-a = ii(a, b, c, d, k[8], 6,  1873313359);
-d = ii(d, a, b, c, k[15], 10, -30611744);
-c = ii(c, d, a, b, k[6], 15, -1560198380);
-b = ii(b, c, d, a, k[13], 21,  1309151649);
-a = ii(a, b, c, d, k[4], 6, -145523070);
-d = ii(d, a, b, c, k[11], 10, -1120210379);
-c = ii(c, d, a, b, k[2], 15,  718787259);
-b = ii(b, c, d, a, k[9], 21, -343485551);
-
-x[0] = add32(a, x[0]);
-x[1] = add32(b, x[1]);
-x[2] = add32(c, x[2]);
-x[3] = add32(d, x[3]);
-
-}
-
-function cmn(q, a, b, x, s, t) {
-a = add32(add32(a, q), add32(x, t));
-return add32((a << s) | (a >>> (32 - s)), b);
-}
-
-function ff(a, b, c, d, x, s, t) {
-return cmn((b & c) | ((~b) & d), a, b, x, s, t);
-}
-
-function gg(a, b, c, d, x, s, t) {
-return cmn((b & d) | (c & (~d)), a, b, x, s, t);
-}
-
-function hh(a, b, c, d, x, s, t) {
-return cmn(b ^ c ^ d, a, b, x, s, t);
-}
-
-function ii(a, b, c, d, x, s, t) {
-return cmn(c ^ (b | (~d)), a, b, x, s, t);
-}
-
-function md51(s) {
-txt = '';
-var n = s.length,
-state = [1732584193, -271733879, -1732584194, 271733878], i;
-for (i=64; i<=s.length; i+=64) {
-md5cycle(state, md5blk(s.substring(i-64, i)));
-}
-s = s.substring(i-64);
-var tail = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
-for (i=0; i<s.length; i++)
-tail[i>>2] |= s.charCodeAt(i) << ((i%4) << 3);
-tail[i>>2] |= 0x80 << ((i%4) << 3);
-if (i > 55) {
-md5cycle(state, tail);
-for (i=0; i<16; i++) tail[i] = 0;
-}
-tail[14] = n*8;
-md5cycle(state, tail);
-return state;
-}
-
-/* there needs to be support for Unicode here,
- * unless we pretend that we can redefine the MD-5
- * algorithm for multi-byte characters (perhaps
- * by adding every four 16-bit characters and
- * shortening the sum to 32 bits). Otherwise
- * I suggest performing MD-5 as if every character
- * was two bytes--e.g., 0040 0025 = @%--but then
- * how will an ordinary MD-5 sum be matched?
- * There is no way to standardize text to something
- * like UTF-8 before transformation; speed cost is
- * utterly prohibitive. The JavaScript standard
- * itself needs to look at this: it should start
- * providing access to strings as preformed UTF-8
- * 8-bit unsigned value arrays.
- */
-function md5blk(s) { /* I figured global was faster.   */
-var md5blks = [], i; /* Andy King said do it this way. */
-for (i=0; i<64; i+=4) {
-md5blks[i>>2] = s.charCodeAt(i)
-+ (s.charCodeAt(i+1) << 8)
-+ (s.charCodeAt(i+2) << 16)
-+ (s.charCodeAt(i+3) << 24);
-}
-return md5blks;
-}
-
-var hex_chr = '0123456789abcdef'.split('');
-
-function rhex(n)
-{
-var s='', j=0;
-for(; j<4; j++)
-s += hex_chr[(n >> (j * 8 + 4)) & 0x0F]
-+ hex_chr[(n >> (j * 8)) & 0x0F];
-return s;
-}
-
-function hex(x) {
-for (var i=0; i<x.length; i++)
-x[i] = rhex(x[i]);
-return x.join('');
-}
-
-function md5(s) {
-return hex(md51(s));
-}
-
-/* this function is much faster,
-so if possible we use it. Some IEs
-are the only ones I know of that
-need the idiotic second function,
-generated by an if clause.  */
-
-function add32(a, b) {
-return (a + b) & 0xFFFFFFFF;
-}
-
-if (md5('hello') != '5d41402abc4b2a76b9719d911017c592') {
-function add32(x, y) {
-var lsw = (x & 0xFFFF) + (y & 0xFFFF),
-msw = (x >> 16) + (y >> 16) + (lsw >> 16);
-return (msw << 16) | (lsw & 0xFFFF);
-}
-}
-/* A JavaScript implementation of the SHA family of hashes, as defined in FIPS 
- * PUB 180-2 as well as the corresponding HMAC implementation as defined in
- * FIPS PUB 198a
- *
- * Version 1.3 Copyright Brian Turek 2008-2010
- * Distributed under the BSD License
- * See http://jssha.sourceforge.net/ for more information
- *
- * Several functions taken from Paul Johnson
- */
-
-/* Modified by Recurity Labs GmbH
- * 
- * This code has been slightly modified direct string output:
- * - bin2bstr has been added
- * - following wrappers of this library have been added:
- *   - str_sha1
- *   - str_sha256
- *   - str_sha224
- *   - str_sha384
- *   - str_sha512
- */
-
-var jsSHA = (function () {
-	
-	/*
-	 * Configurable variables. Defaults typically work
-	 */
-	/* Number of Bits Per character (8 for ASCII, 16 for Unicode) */
-	var charSize = 8, 
-	/* base-64 pad character. "=" for strict RFC compliance */
-	b64pad = "", 
-	/* hex output format. 0 - lowercase; 1 - uppercase */
-	hexCase = 0, 
-
-	/*
-	 * Int_64 is a object for 2 32-bit numbers emulating a 64-bit number
-	 *
-	 * @constructor
-	 * @param {Number} msint_32 The most significant 32-bits of a 64-bit number
-	 * @param {Number} lsint_32 The least significant 32-bits of a 64-bit number
-	 */
-	Int_64 = function (msint_32, lsint_32)
-	{
-		this.highOrder = msint_32;
-		this.lowOrder = lsint_32;
-	},
-
-	/*
-	 * Convert a string to an array of big-endian words
-	 * If charSize is ASCII, characters >255 have their hi-byte silently
-	 * ignored.
-	 *
-	 * @param {String} str String to be converted to binary representation
-	 * @return Integer array representation of the parameter
-	 */
-	str2binb = function (str)
-	{
-		var bin = [], mask = (1 << charSize) - 1,
-			length = str.length * charSize, i;
-
-		for (i = 0; i < length; i += charSize)
-		{
-			bin[i >> 5] |= (str.charCodeAt(i / charSize) & mask) <<
-				(32 - charSize - (i % 32));
-		}
-
-		return bin;
-	},
-
-	/*
-	 * Convert a hex string to an array of big-endian words
-	 *
-	 * @param {String} str String to be converted to binary representation
-	 * @return Integer array representation of the parameter
-	 */
-	hex2binb = function (str)
-	{
-		var bin = [], length = str.length, i, num;
-
-		for (i = 0; i < length; i += 2)
-		{
-			num = parseInt(str.substr(i, 2), 16);
-			if (!isNaN(num))
-			{
-				bin[i >> 3] |= num << (24 - (4 * (i % 8)));
-			}
-			else
-			{
-				return "INVALID HEX STRING";
-			}
-		}
-
-		return bin;
-	},
-
-	/*
-	 * Convert an array of big-endian words to a hex string.
-	 *
-	 * @private
-	 * @param {Array} binarray Array of integers to be converted to hexidecimal
-	 *	 representation
-	 * @return Hexidecimal representation of the parameter in String form
-	 */
-	binb2hex = function (binarray)
-	{
-		var hex_tab = (hexCase) ? "0123456789ABCDEF" : "0123456789abcdef",
-			str = "", length = binarray.length * 4, i, srcByte;
-
-		for (i = 0; i < length; i += 1)
-		{
-			srcByte = binarray[i >> 2] >> ((3 - (i % 4)) * 8);
-			str += hex_tab.charAt((srcByte >> 4) & 0xF) +
-				hex_tab.charAt(srcByte & 0xF);
-		}
-
-		return str;
-	},
-
-	/*
-	 * Convert an array of big-endian words to a base-64 string
-	 *
-	 * @private
-	 * @param {Array} binarray Array of integers to be converted to base-64
-	 *	 representation
-	 * @return Base-64 encoded representation of the parameter in String form
-	 */
-	binb2b64 = function (binarray)
-	{
-		var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +
-			"0123456789+/", str = "", length = binarray.length * 4, i, j,
-			triplet;
-
-		for (i = 0; i < length; i += 3)
-		{
-			triplet = (((binarray[i >> 2] >> 8 * (3 - i % 4)) & 0xFF) << 16) |
-				(((binarray[i + 1 >> 2] >> 8 * (3 - (i + 1) % 4)) & 0xFF) << 8) |
-				((binarray[i + 2 >> 2] >> 8 * (3 - (i + 2) % 4)) & 0xFF);
-			for (j = 0; j < 4; j += 1)
-			{
-				if (i * 8 + j * 6 <= binarray.length * 32)
-				{
-					str += tab.charAt((triplet >> 6 * (3 - j)) & 0x3F);
-				}
-				else
-				{
-					str += b64pad;
-				}
-			}
-		}
-		return str;
-	},
-
-	/*
-	 * Convert an array of big-endian words to a string
-	 */
-	binb2str = function (bin)
-	{
-	  var str = "";
-	  var mask = (1 << 8) - 1;
-	  for(var i = 0; i < bin.length * 32; i += 8)
-	    str += String.fromCharCode((bin[i>>5] >>> (24 - i%32)) & mask);
-	  return str;
-	},
-	/*
-	 * The 32-bit implementation of circular rotate left
-	 *
-	 * @private
-	 * @param {Number} x The 32-bit integer argument
-	 * @param {Number} n The number of bits to shift
-	 * @return The x shifted circularly by n bits
-	 */
-	rotl_32 = function (x, n)
-	{
-		return (x << n) | (x >>> (32 - n));
-	},
-
-	/*
-	 * The 32-bit implementation of circular rotate right
-	 *
-	 * @private
-	 * @param {Number} x The 32-bit integer argument
-	 * @param {Number} n The number of bits to shift
-	 * @return The x shifted circularly by n bits
-	 */
-	rotr_32 = function (x, n)
-	{
-		return (x >>> n) | (x << (32 - n));
-	},
-
-	/*
-	 * The 64-bit implementation of circular rotate right
-	 *
-	 * @private
-	 * @param {Int_64} x The 64-bit integer argument
-	 * @param {Number} n The number of bits to shift
-	 * @return The x shifted circularly by n bits
-	 */
-	rotr_64 = function (x, n)
-	{
-		if (n <= 32)
-		{
-			return new Int_64(
-					(x.highOrder >>> n) | (x.lowOrder << (32 - n)),
-					(x.lowOrder >>> n) | (x.highOrder << (32 - n))
-				);
-		}
-		else
-		{
-			return new Int_64(
-					(x.lowOrder >>> n) | (x.highOrder << (32 - n)),
-					(x.highOrder >>> n) | (x.lowOrder << (32 - n))
-				);
-		}
-	},
-
-	/*
-	 * The 32-bit implementation of shift right
-	 *
-	 * @private
-	 * @param {Number} x The 32-bit integer argument
-	 * @param {Number} n The number of bits to shift
-	 * @return The x shifted by n bits
-	 */
-	shr_32 = function (x, n)
-	{
-		return x >>> n;
-	},
-
-	/*
-	 * The 64-bit implementation of shift right
-	 *
-	 * @private
-	 * @param {Int_64} x The 64-bit integer argument
-	 * @param {Number} n The number of bits to shift
-	 * @return The x shifted by n bits
-	 */
-	shr_64 = function (x, n)
-	{
-		if (n <= 32)
-		{
-			return new Int_64(
-					x.highOrder >>> n,
-					x.lowOrder >>> n | (x.highOrder << (32 - n))
-				);
-		}
-		else
-		{
-			return new Int_64(
-					0,
-					x.highOrder << (32 - n)
-				);
-		}
-	},
-
-	/*
-	 * The 32-bit implementation of the NIST specified Parity function
-	 *
-	 * @private
-	 * @param {Number} x The first 32-bit integer argument
-	 * @param {Number} y The second 32-bit integer argument
-	 * @param {Number} z The third 32-bit integer argument
-	 * @return The NIST specified output of the function
-	 */
-	parity_32 = function (x, y, z)
-	{
-		return x ^ y ^ z;
-	},
-
-	/*
-	 * The 32-bit implementation of the NIST specified Ch function
-	 *
-	 * @private
-	 * @param {Number} x The first 32-bit integer argument
-	 * @param {Number} y The second 32-bit integer argument
-	 * @param {Number} z The third 32-bit integer argument
-	 * @return The NIST specified output of the function
-	 */
-	ch_32 = function (x, y, z)
-	{
-		return (x & y) ^ (~x & z);
-	},
-
-	/*
-	 * The 64-bit implementation of the NIST specified Ch function
-	 *
-	 * @private
-	 * @param {Int_64} x The first 64-bit integer argument
-	 * @param {Int_64} y The second 64-bit integer argument
-	 * @param {Int_64} z The third 64-bit integer argument
-	 * @return The NIST specified output of the function
-	 */
-	ch_64 = function (x, y, z)
-	{
-		return new Int_64(
-				(x.highOrder & y.highOrder) ^ (~x.highOrder & z.highOrder),
-				(x.lowOrder & y.lowOrder) ^ (~x.lowOrder & z.lowOrder)
-			);
-	},
-
-	/*
-	 * The 32-bit implementation of the NIST specified Maj function
-	 *
-	 * @private
-	 * @param {Number} x The first 32-bit integer argument
-	 * @param {Number} y The second 32-bit integer argument
-	 * @param {Number} z The third 32-bit integer argument
-	 * @return The NIST specified output of the function
-	 */
-	maj_32 = function (x, y, z)
-	{
-		return (x & y) ^ (x & z) ^ (y & z);
-	},
-
-	/*
-	 * The 64-bit implementation of the NIST specified Maj function
-	 *
-	 * @private
-	 * @param {Int_64} x The first 64-bit integer argument
-	 * @param {Int_64} y The second 64-bit integer argument
-	 * @param {Int_64} z The third 64-bit integer argument
-	 * @return The NIST specified output of the function
-	 */
-	maj_64 = function (x, y, z)
-	{
-		return new Int_64(
-				(x.highOrder & y.highOrder) ^
-				(x.highOrder & z.highOrder) ^
-				(y.highOrder & z.highOrder),
-				(x.lowOrder & y.lowOrder) ^
-				(x.lowOrder & z.lowOrder) ^
-				(y.lowOrder & z.lowOrder)
-			);
-	},
-
-	/*
-	 * The 32-bit implementation of the NIST specified Sigma0 function
-	 *
-	 * @private
-	 * @param {Number} x The 32-bit integer argument
-	 * @return The NIST specified output of the function
-	 */
-	sigma0_32 = function (x)
-	{
-		return rotr_32(x, 2) ^ rotr_32(x, 13) ^ rotr_32(x, 22);
-	},
-
-	/*
-	 * The 64-bit implementation of the NIST specified Sigma0 function
-	 *
-	 * @private
-	 * @param {Int_64} x The 64-bit integer argument
-	 * @return The NIST specified output of the function
-	 */
-	sigma0_64 = function (x)
-	{
-		var rotr28 = rotr_64(x, 28), rotr34 = rotr_64(x, 34),
-			rotr39 = rotr_64(x, 39);
-
-		return new Int_64(
-				rotr28.highOrder ^ rotr34.highOrder ^ rotr39.highOrder,
-				rotr28.lowOrder ^ rotr34.lowOrder ^ rotr39.lowOrder);
-	},
-
-	/*
-	 * The 32-bit implementation of the NIST specified Sigma1 function
-	 *
-	 * @private
-	 * @param {Number} x The 32-bit integer argument
-	 * @return The NIST specified output of the function
-	 */
-	sigma1_32 = function (x)
-	{
-		return rotr_32(x, 6) ^ rotr_32(x, 11) ^ rotr_32(x, 25);
-	},
-
-	/*
-	 * The 64-bit implementation of the NIST specified Sigma1 function
-	 *
-	 * @private
-	 * @param {Int_64} x The 64-bit integer argument
-	 * @return The NIST specified output of the function
-	 */
-	sigma1_64 = function (x)
-	{
-		var rotr14 = rotr_64(x, 14), rotr18 = rotr_64(x, 18),
-			rotr41 = rotr_64(x, 41);
-
-		return new Int_64(
-				rotr14.highOrder ^ rotr18.highOrder ^ rotr41.highOrder,
-				rotr14.lowOrder ^ rotr18.lowOrder ^ rotr41.lowOrder);
-	},
-
-	/*
-	 * The 32-bit implementation of the NIST specified Gamma0 function
-	 *
-	 * @private
-	 * @param {Number} x The 32-bit integer argument
-	 * @return The NIST specified output of the function
-	 */
-	gamma0_32 = function (x)
-	{
-		return rotr_32(x, 7) ^ rotr_32(x, 18) ^ shr_32(x, 3);
-	},
-
-	/*
-	 * The 64-bit implementation of the NIST specified Gamma0 function
-	 *
-	 * @private
-	 * @param {Int_64} x The 64-bit integer argument
-	 * @return The NIST specified output of the function
-	 */
-	gamma0_64 = function (x)
-	{
-		var rotr1 = rotr_64(x, 1), rotr8 = rotr_64(x, 8), shr7 = shr_64(x, 7);
-
-		return new Int_64(
-				rotr1.highOrder ^ rotr8.highOrder ^ shr7.highOrder,
-				rotr1.lowOrder ^ rotr8.lowOrder ^ shr7.lowOrder
-			);
-	},
-
-	/*
-	 * The 32-bit implementation of the NIST specified Gamma1 function
-	 *
-	 * @private
-	 * @param {Number} x The 32-bit integer argument
-	 * @return The NIST specified output of the function
-	 */
-	gamma1_32 = function (x)
-	{
-		return rotr_32(x, 17) ^ rotr_32(x, 19) ^ shr_32(x, 10);
-	},
-
-	/*
-	 * The 64-bit implementation of the NIST specified Gamma1 function
-	 *
-	 * @private
-	 * @param {Int_64} x The 64-bit integer argument
-	 * @return The NIST specified output of the function
-	 */
-	gamma1_64 = function (x)
-	{
-		var rotr19 = rotr_64(x, 19), rotr61 = rotr_64(x, 61),
-			shr6 = shr_64(x, 6);
-
-		return new Int_64(
-				rotr19.highOrder ^ rotr61.highOrder ^ shr6.highOrder,
-				rotr19.lowOrder ^ rotr61.lowOrder ^ shr6.lowOrder
-			);
-	},
-
-	/*
-	 * Add two 32-bit integers, wrapping at 2^32. This uses 16-bit operations
-	 * internally to work around bugs in some JS interpreters.
-	 *
-	 * @private
-	 * @param {Number} x The first 32-bit integer argument to be added
-	 * @param {Number} y The second 32-bit integer argument to be added
-	 * @return The sum of x + y
-	 */
-	safeAdd_32_2 = function (x, y)
-	{
-		var lsw = (x & 0xFFFF) + (y & 0xFFFF),
-			msw = (x >>> 16) + (y >>> 16) + (lsw >>> 16);
-
-		return ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
-	},
-
-	/*
-	 * Add four 32-bit integers, wrapping at 2^32. This uses 16-bit operations
-	 * internally to work around bugs in some JS interpreters.
-	 *
-	 * @private
-	 * @param {Number} a The first 32-bit integer argument to be added
-	 * @param {Number} b The second 32-bit integer argument to be added
-	 * @param {Number} c The third 32-bit integer argument to be added
-	 * @param {Number} d The fourth 32-bit integer argument to be added
-	 * @return The sum of a + b + c + d
-	 */
-	safeAdd_32_4 = function (a, b, c, d)
-	{
-		var lsw = (a & 0xFFFF) + (b & 0xFFFF) + (c & 0xFFFF) + (d & 0xFFFF),
-			msw = (a >>> 16) + (b >>> 16) + (c >>> 16) + (d >>> 16) +
-				(lsw >>> 16);
-
-		return ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
-	},
-
-	/*
-	 * Add five 32-bit integers, wrapping at 2^32. This uses 16-bit operations
-	 * internally to work around bugs in some JS interpreters.
-	 *
-	 * @private
-	 * @param {Number} a The first 32-bit integer argument to be added
-	 * @param {Number} b The second 32-bit integer argument to be added
-	 * @param {Number} c The third 32-bit integer argument to be added
-	 * @param {Number} d The fourth 32-bit integer argument to be added
-	 * @param {Number} e The fifth 32-bit integer argument to be added
-	 * @return The sum of a + b + c + d + e
-	 */
-	safeAdd_32_5 = function (a, b, c, d, e)
-	{
-		var lsw = (a & 0xFFFF) + (b & 0xFFFF) + (c & 0xFFFF) + (d & 0xFFFF) +
-				(e & 0xFFFF),
-			msw = (a >>> 16) + (b >>> 16) + (c >>> 16) + (d >>> 16) +
-				(e >>> 16) + (lsw >>> 16);
-
-		return ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
-	},
-
-	/*
-	 * Add two 64-bit integers, wrapping at 2^64. This uses 16-bit operations
-	 * internally to work around bugs in some JS interpreters.
-	 *
-	 * @private
-	 * @param {Int_64} x The first 64-bit integer argument to be added
-	 * @param {Int_64} y The second 64-bit integer argument to be added
-	 * @return The sum of x + y
-	 */
-	safeAdd_64_2 = function (x, y)
-	{
-		var lsw, msw, lowOrder, highOrder;
-
-		lsw = (x.lowOrder & 0xFFFF) + (y.lowOrder & 0xFFFF);
-		msw = (x.lowOrder >>> 16) + (y.lowOrder >>> 16) + (lsw >>> 16);
-		lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
-
-		lsw = (x.highOrder & 0xFFFF) + (y.highOrder & 0xFFFF) + (msw >>> 16);
-		msw = (x.highOrder >>> 16) + (y.highOrder >>> 16) + (lsw >>> 16);
-		highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
-
-		return new Int_64(highOrder, lowOrder);
-	},
-
-	/*
-	 * Add four 64-bit integers, wrapping at 2^64. This uses 16-bit operations
-	 * internally to work around bugs in some JS interpreters.
-	 *
-	 * @private
-	 * @param {Int_64} a The first 64-bit integer argument to be added
-	 * @param {Int_64} b The second 64-bit integer argument to be added
-	 * @param {Int_64} c The third 64-bit integer argument to be added
-	 * @param {Int_64} d The fouth 64-bit integer argument to be added
-	 * @return The sum of a + b + c + d
-	 */
-	safeAdd_64_4 = function (a, b, c, d)
-	{
-		var lsw, msw, lowOrder, highOrder;
-
-		lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) +
-			(c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF);
-		msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) +
-			(c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (lsw >>> 16);
-		lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
-
-		lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) +
-			(c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (msw >>> 16);
-		msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) +
-			(c.highOrder >>> 16) + (d.highOrder >>> 16) + (lsw >>> 16);
-		highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
-
-		return new Int_64(highOrder, lowOrder);
-	},
-
-	/*
-	 * Add five 64-bit integers, wrapping at 2^64. This uses 16-bit operations
-	 * internally to work around bugs in some JS interpreters.
-	 *
-	 * @private
-	 * @param {Int_64} a The first 64-bit integer argument to be added
-	 * @param {Int_64} b The second 64-bit integer argument to be added
-	 * @param {Int_64} c The third 64-bit integer argument to be added
-	 * @param {Int_64} d The fouth 64-bit integer argument to be added
-	 * @param {Int_64} e The fouth 64-bit integer argument to be added
-	 * @return The sum of a + b + c + d + e
-	 */
-	safeAdd_64_5 = function (a, b, c, d, e)
-	{
-		var lsw, msw, lowOrder, highOrder;
-
-		lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) +
-			(c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF) +
-			(e.lowOrder & 0xFFFF);
-		msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) +
-			(c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (e.lowOrder >>> 16) +
-			(lsw >>> 16);
-		lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
-
-		lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) +
-			(c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) +
-			(e.highOrder & 0xFFFF) + (msw >>> 16);
-		msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) +
-			(c.highOrder >>> 16) + (d.highOrder >>> 16) +
-			(e.highOrder >>> 16) + (lsw >>> 16);
-		highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
-
-		return new Int_64(highOrder, lowOrder);
-	},
-
-	/*
-	 * Calculates the SHA-1 hash of the string set at instantiation
-	 *
-	 * @private
-	 * @param {Array} message The binary array representation of the string to
-	 *	 hash
-	 * @param {Number} messageLen The number of bits in the message
-	 * @return The array of integers representing the SHA-1 hash of message
-	 */
-	coreSHA1 = function (message, messageLen)
-	{
-		var W = [], a, b, c, d, e, T, ch = ch_32, parity = parity_32,
-			maj = maj_32, rotl = rotl_32, safeAdd_2 = safeAdd_32_2, i, t,
-			safeAdd_5 = safeAdd_32_5, appendedMessageLength,
-			H = [
-				0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0
-			],
-			K = [
-				0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999,
-				0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999,
-				0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999,
-				0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999,
-				0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999,
-				0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1,
-				0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1,
-				0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1,
-				0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1,
-				0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1,
-				0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc,
-				0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc,
-				0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc,
-				0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc,
-				0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc,
-				0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6,
-				0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6,
-				0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6,
-				0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6,
-				0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6
-			];
-
-		/* Append '1' at the end of the binary string */
-		message[messageLen >> 5] |= 0x80 << (24 - (messageLen % 32));
-		/* Append length of binary string in the position such that the new
-		length is a multiple of 512.  Logic does not work for even multiples
-		of 512 but there can never be even multiples of 512 */
-		message[(((messageLen + 65) >> 9) << 4) + 15] = messageLen;
-
-		appendedMessageLength = message.length;
-
-		for (i = 0; i < appendedMessageLength; i += 16)
-		{
-			a = H[0];
-			b = H[1];
-			c = H[2];
-			d = H[3];
-			e = H[4];
-
-			for (t = 0; t < 80; t += 1)
-			{
-				if (t < 16)
-				{
-					W[t] = message[t + i];
-				}
-				else
-				{
-					W[t] = rotl(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1);
-				}
-
-				if (t < 20)
-				{
-					T = safeAdd_5(rotl(a, 5), ch(b, c, d), e, K[t], W[t]);
-				}
-				else if (t < 40)
-				{
-					T = safeAdd_5(rotl(a, 5), parity(b, c, d), e, K[t], W[t]);
-				}
-				else if (t < 60)
-				{
-					T = safeAdd_5(rotl(a, 5), maj(b, c, d), e, K[t], W[t]);
-				} else {
-					T = safeAdd_5(rotl(a, 5), parity(b, c, d), e, K[t], W[t]);
-				}
-
-				e = d;
-				d = c;
-				c = rotl(b, 30);
-				b = a;
-				a = T;
-			}
-
-			H[0] = safeAdd_2(a, H[0]);
-			H[1] = safeAdd_2(b, H[1]);
-			H[2] = safeAdd_2(c, H[2]);
-			H[3] = safeAdd_2(d, H[3]);
-			H[4] = safeAdd_2(e, H[4]);
-		}
-
-		return H;
-	},
-
-	/*
-	 * Calculates the desired SHA-2 hash of the string set at instantiation
-	 *
-	 * @private
-	 * @param {Array} The binary array representation of the string to hash
-	 * @param {Number} The number of bits in message
-	 * @param {String} variant The desired SHA-2 variant
-	 * @return The array of integers representing the SHA-2 hash of message
-	 */
-	coreSHA2 = function (message, messageLen, variant)
-	{
-		var a, b, c, d, e, f, g, h, T1, T2, H, numRounds, lengthPosition, i, t,
-			binaryStringInc, binaryStringMult, safeAdd_2, safeAdd_4, safeAdd_5,
-			gamma0, gamma1, sigma0, sigma1, ch, maj, Int, K, W = [],
-			appendedMessageLength;
-
-		/* Set up the various function handles and variable for the specific 
-		 * variant */
-		if (variant === "SHA-224" || variant === "SHA-256")
-		{
-			/* 32-bit variant */
-			numRounds = 64;
-			lengthPosition = (((messageLen + 65) >> 9) << 4) + 15;
-			binaryStringInc = 16;
-			binaryStringMult = 1;
-			Int = Number;
-			safeAdd_2 = safeAdd_32_2;
-			safeAdd_4 = safeAdd_32_4;
-			safeAdd_5 = safeAdd_32_5;
-			gamma0 = gamma0_32;
-			gamma1 = gamma1_32;
-			sigma0 = sigma0_32;
-			sigma1 = sigma1_32;
-			maj = maj_32;
-			ch = ch_32;
-			K = [
-					0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
-					0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
-					0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
-					0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
-					0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
-					0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
-					0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
-					0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
-					0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
-					0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
-					0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
-					0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
-					0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
-					0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
-					0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
-					0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
-				];
-
-			if (variant === "SHA-224")
-			{
-				H = [
-						0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
-						0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
-					];
-			}
-			else
-			{
-				H = [
-						0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
-						0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
-					];
-			}
-		}
-		else if (variant === "SHA-384" || variant === "SHA-512")
-		{
-			/* 64-bit variant */
-			numRounds = 80;
-			lengthPosition = (((messageLen + 128) >> 10) << 5) + 31;
-			binaryStringInc = 32;
-			binaryStringMult = 2;
-			Int = Int_64;
-			safeAdd_2 = safeAdd_64_2;
-			safeAdd_4 = safeAdd_64_4;
-			safeAdd_5 = safeAdd_64_5;
-			gamma0 = gamma0_64;
-			gamma1 = gamma1_64;
-			sigma0 = sigma0_64;
-			sigma1 = sigma1_64;
-			maj = maj_64;
-			ch = ch_64;
-
-			K = [
-				new Int(0x428a2f98, 0xd728ae22), new Int(0x71374491, 0x23ef65cd),
-				new Int(0xb5c0fbcf, 0xec4d3b2f), new Int(0xe9b5dba5, 0x8189dbbc),
-				new Int(0x3956c25b, 0xf348b538), new Int(0x59f111f1, 0xb605d019),
-				new Int(0x923f82a4, 0xaf194f9b), new Int(0xab1c5ed5, 0xda6d8118),
-				new Int(0xd807aa98, 0xa3030242), new Int(0x12835b01, 0x45706fbe),
-				new Int(0x243185be, 0x4ee4b28c), new Int(0x550c7dc3, 0xd5ffb4e2),
-				new Int(0x72be5d74, 0xf27b896f), new Int(0x80deb1fe, 0x3b1696b1),
-				new Int(0x9bdc06a7, 0x25c71235), new Int(0xc19bf174, 0xcf692694),
-				new Int(0xe49b69c1, 0x9ef14ad2), new Int(0xefbe4786, 0x384f25e3),
-				new Int(0x0fc19dc6, 0x8b8cd5b5), new Int(0x240ca1cc, 0x77ac9c65),
-				new Int(0x2de92c6f, 0x592b0275), new Int(0x4a7484aa, 0x6ea6e483),
-				new Int(0x5cb0a9dc, 0xbd41fbd4), new Int(0x76f988da, 0x831153b5),
-				new Int(0x983e5152, 0xee66dfab), new Int(0xa831c66d, 0x2db43210),
-				new Int(0xb00327c8, 0x98fb213f), new Int(0xbf597fc7, 0xbeef0ee4),
-				new Int(0xc6e00bf3, 0x3da88fc2), new Int(0xd5a79147, 0x930aa725),
-				new Int(0x06ca6351, 0xe003826f), new Int(0x14292967, 0x0a0e6e70),
-				new Int(0x27b70a85, 0x46d22ffc), new Int(0x2e1b2138, 0x5c26c926),
-				new Int(0x4d2c6dfc, 0x5ac42aed), new Int(0x53380d13, 0x9d95b3df),
-				new Int(0x650a7354, 0x8baf63de), new Int(0x766a0abb, 0x3c77b2a8),
-				new Int(0x81c2c92e, 0x47edaee6), new Int(0x92722c85, 0x1482353b),
-				new Int(0xa2bfe8a1, 0x4cf10364), new Int(0xa81a664b, 0xbc423001),
-				new Int(0xc24b8b70, 0xd0f89791), new Int(0xc76c51a3, 0x0654be30),
-				new Int(0xd192e819, 0xd6ef5218), new Int(0xd6990624, 0x5565a910),
-				new Int(0xf40e3585, 0x5771202a), new Int(0x106aa070, 0x32bbd1b8),
-				new Int(0x19a4c116, 0xb8d2d0c8), new Int(0x1e376c08, 0x5141ab53),
-				new Int(0x2748774c, 0xdf8eeb99), new Int(0x34b0bcb5, 0xe19b48a8),
-				new Int(0x391c0cb3, 0xc5c95a63), new Int(0x4ed8aa4a, 0xe3418acb),
-				new Int(0x5b9cca4f, 0x7763e373), new Int(0x682e6ff3, 0xd6b2b8a3),
-				new Int(0x748f82ee, 0x5defb2fc), new Int(0x78a5636f, 0x43172f60),
-				new Int(0x84c87814, 0xa1f0ab72), new Int(0x8cc70208, 0x1a6439ec),
-				new Int(0x90befffa, 0x23631e28), new Int(0xa4506ceb, 0xde82bde9),
-				new Int(0xbef9a3f7, 0xb2c67915), new Int(0xc67178f2, 0xe372532b),
-				new Int(0xca273ece, 0xea26619c), new Int(0xd186b8c7, 0x21c0c207),
-				new Int(0xeada7dd6, 0xcde0eb1e), new Int(0xf57d4f7f, 0xee6ed178),
-				new Int(0x06f067aa, 0x72176fba), new Int(0x0a637dc5, 0xa2c898a6),
-				new Int(0x113f9804, 0xbef90dae), new Int(0x1b710b35, 0x131c471b),
-				new Int(0x28db77f5, 0x23047d84), new Int(0x32caab7b, 0x40c72493),
-				new Int(0x3c9ebe0a, 0x15c9bebc), new Int(0x431d67c4, 0x9c100d4c),
-				new Int(0x4cc5d4be, 0xcb3e42b6), new Int(0x597f299c, 0xfc657e2a),
-				new Int(0x5fcb6fab, 0x3ad6faec), new Int(0x6c44198c, 0x4a475817)
-			];
-
-			if (variant === "SHA-384")
-			{
-				H = [
-					new Int(0xcbbb9d5d, 0xc1059ed8), new Int(0x0629a292a, 0x367cd507),
-					new Int(0x9159015a, 0x3070dd17), new Int(0x0152fecd8, 0xf70e5939),
-					new Int(0x67332667, 0xffc00b31), new Int(0x98eb44a87, 0x68581511),
-					new Int(0xdb0c2e0d, 0x64f98fa7), new Int(0x047b5481d, 0xbefa4fa4)
-				];
-			}
-			else
-			{
-				H = [
-					new Int(0x6a09e667, 0xf3bcc908), new Int(0xbb67ae85, 0x84caa73b),
-					new Int(0x3c6ef372, 0xfe94f82b), new Int(0xa54ff53a, 0x5f1d36f1),
-					new Int(0x510e527f, 0xade682d1), new Int(0x9b05688c, 0x2b3e6c1f),
-					new Int(0x1f83d9ab, 0xfb41bd6b), new Int(0x5be0cd19, 0x137e2179)
-				];
-			}
-		}
-
-		/* Append '1' at the end of the binary string */
-		message[messageLen >> 5] |= 0x80 << (24 - messageLen % 32);
-		/* Append length of binary string in the position such that the new
-		 * length is correct */
-		message[lengthPosition] = messageLen;
-
-		appendedMessageLength = message.length;
-
-		for (i = 0; i < appendedMessageLength; i += binaryStringInc)
-		{
-			a = H[0];
-			b = H[1];
-			c = H[2];
-			d = H[3];
-			e = H[4];
-			f = H[5];
-			g = H[6];
-			h = H[7];
-
-			for (t = 0; t < numRounds; t += 1)
-			{
-				if (t < 16)
-				{
-					/* Bit of a hack - for 32-bit, the second term is ignored */
-					W[t] = new Int(message[t * binaryStringMult + i],
-							message[t * binaryStringMult + i + 1]);
-				}
-				else
-				{
-					W[t] = safeAdd_4(
-							gamma1(W[t - 2]), W[t - 7],
-							gamma0(W[t - 15]), W[t - 16]
-						);
-				}
-
-				T1 = safeAdd_5(h, sigma1(e), ch(e, f, g), K[t], W[t]);
-				T2 = safeAdd_2(sigma0(a), maj(a, b, c));
-				h = g;
-				g = f;
-				f = e;
-				e = safeAdd_2(d, T1);
-				d = c;
-				c = b;
-				b = a;
-				a = safeAdd_2(T1, T2);
-			}
-
-			H[0] = safeAdd_2(a, H[0]);
-			H[1] = safeAdd_2(b, H[1]);
-			H[2] = safeAdd_2(c, H[2]);
-			H[3] = safeAdd_2(d, H[3]);
-			H[4] = safeAdd_2(e, H[4]);
-			H[5] = safeAdd_2(f, H[5]);
-			H[6] = safeAdd_2(g, H[6]);
-			H[7] = safeAdd_2(h, H[7]);
-		}
-
-		switch (variant)
-		{
-		case "SHA-224":
-			return	[
-				H[0], H[1], H[2], H[3],
-				H[4], H[5], H[6]
-			];
-		case "SHA-256":
-			return H;
-		case "SHA-384":
-			return [
-				H[0].highOrder, H[0].lowOrder,
-				H[1].highOrder, H[1].lowOrder,
-				H[2].highOrder, H[2].lowOrder,
-				H[3].highOrder, H[3].lowOrder,
-				H[4].highOrder, H[4].lowOrder,
-				H[5].highOrder, H[5].lowOrder
-			];
-		case "SHA-512":
-			return [
-				H[0].highOrder, H[0].lowOrder,
-				H[1].highOrder, H[1].lowOrder,
-				H[2].highOrder, H[2].lowOrder,
-				H[3].highOrder, H[3].lowOrder,
-				H[4].highOrder, H[4].lowOrder,
-				H[5].highOrder, H[5].lowOrder,
-				H[6].highOrder, H[6].lowOrder,
-				H[7].highOrder, H[7].lowOrder
-			];
-		default:
-			/* This should never be reached */
-			return []; 
-		}
-	},
-
-	/*
-	 * jsSHA is the workhorse of the library.  Instantiate it with the string to
-	 * be hashed as the parameter
-	 *
-	 * @constructor
-	 * @param {String} srcString The string to be hashed
-	 * @param {String} inputFormat The format of srcString, ASCII or HEX
-	 */
-	jsSHA = function (srcString, inputFormat)
-	{
-
-		this.sha1 = null;
-		this.sha224 = null;
-		this.sha256 = null;
-		this.sha384 = null;
-		this.sha512 = null;
-
-		this.strBinLen = null;
-		this.strToHash = null;
-
-		/* Convert the input string into the correct type */
-		if ("HEX" === inputFormat)
-		{
-			if (0 !== (srcString.length % 2))
-			{
-				return "TEXT MUST BE IN BYTE INCREMENTS";
-			}
-			this.strBinLen = srcString.length * 4;
-			this.strToHash = hex2binb(srcString);
-		}
-		else if (("ASCII" === inputFormat) ||
-			 ('undefined' === typeof(inputFormat)))
-		{
-			this.strBinLen = srcString.length * charSize;
-			this.strToHash = str2binb(srcString);
-		}
-		else
-		{
-			return "UNKNOWN TEXT INPUT TYPE";
-		}
-	};
-
-	jsSHA.prototype = {
-		/*
-		 * Returns the desired SHA hash of the string specified at instantiation
-		 * using the specified parameters
-		 *
-		 * @param {String} variant The desired SHA variant (SHA-1, SHA-224,
-		 *	 SHA-256, SHA-384, or SHA-512)
-		 * @param {String} format The desired output formatting (B64 or HEX)
-		 * @return The string representation of the hash in the format specified
-		 */
-		getHash : function (variant, format)
-		{
-			var formatFunc = null, message = this.strToHash.slice();
-
-			switch (format)
-			{
-			case "HEX":
-				formatFunc = binb2hex;
-				break;
-			case "B64":
-				formatFunc = binb2b64;
-				break;
-			case "ASCII":
-				formatFunc = binb2str;
-				break;
-			default:
-				return "FORMAT NOT RECOGNIZED";
-			}
-
-			switch (variant)
-			{
-			case "SHA-1":
-				if (null === this.sha1)
-				{
-					this.sha1 = coreSHA1(message, this.strBinLen);
-				}
-				return formatFunc(this.sha1);
-			case "SHA-224":
-				if (null === this.sha224)
-				{
-					this.sha224 = coreSHA2(message, this.strBinLen, variant);
-				}
-				return formatFunc(this.sha224);
-			case "SHA-256":
-				if (null === this.sha256)
-				{
-					this.sha256 = coreSHA2(message, this.strBinLen, variant);
-				}
-				return formatFunc(this.sha256);
-			case "SHA-384":
-				if (null === this.sha384)
-				{
-					this.sha384 = coreSHA2(message, this.strBinLen, variant);
-				}
-				return formatFunc(this.sha384);
-			case "SHA-512":
-				if (null === this.sha512)
-				{
-					this.sha512 = coreSHA2(message, this.strBinLen, variant);
-				}
-				return formatFunc(this.sha512);
-			default:
-				return "HASH NOT RECOGNIZED";
-			}
-		},
-
-		/*
-		 * Returns the desired HMAC of the string specified at instantiation
-		 * using the key and variant param.
-		 *
-		 * @param {String} key The key used to calculate the HMAC
-		 * @param {String} inputFormat The format of key, ASCII or HEX
-		 * @param {String} variant The desired SHA variant (SHA-1, SHA-224,
-		 *	 SHA-256, SHA-384, or SHA-512)
-		 * @param {String} outputFormat The desired output formatting
-		 *	 (B64 or HEX)
-		 * @return The string representation of the hash in the format specified
-		 */
-		getHMAC : function (key, inputFormat, variant, outputFormat)
-		{
-			var formatFunc, keyToUse, blockByteSize, blockBitSize, i,
-				retVal, lastArrayIndex, keyBinLen, hashBitSize,
-				keyWithIPad = [], keyWithOPad = [];
-
-			/* Validate the output format selection */
-			switch (outputFormat)
-			{
-			case "HEX":
-				formatFunc = binb2hex;
-				break;
-			case "B64":
-				formatFunc = binb2b64;
-				break;
-			case "ASCII":
-				formatFunc = binb2str;
-				break;
-			default:
-				return "FORMAT NOT RECOGNIZED";
-			}
-
-			/* Validate the hash variant selection and set needed variables */
-			switch (variant)
-			{
-			case "SHA-1":
-				blockByteSize = 64;
-				hashBitSize = 160;
-				break;
-			case "SHA-224":
-				blockByteSize = 64;
-				hashBitSize = 224;
-				break;
-			case "SHA-256":
-				blockByteSize = 64;
-				hashBitSize = 256;
-				break;
-			case "SHA-384":
-				blockByteSize = 128;
-				hashBitSize = 384;
-				break;
-			case "SHA-512":
-				blockByteSize = 128;
-				hashBitSize = 512;
-				break;
-			default:
-				return "HASH NOT RECOGNIZED";
-			}
-
-			/* Validate input format selection */
-			if ("HEX" === inputFormat)
-			{
-				/* Nibbles must come in pairs */
-				if (0 !== (key.length % 2))
-				{
-					return "KEY MUST BE IN BYTE INCREMENTS";
-				}
-				keyToUse = hex2binb(key);
-				keyBinLen = key.length * 4;
-			}
-			else if ("ASCII" === inputFormat)
-			{
-				keyToUse = str2binb(key);
-				keyBinLen = key.length * charSize;
-			}
-			else
-			{
-				return "UNKNOWN KEY INPUT TYPE";
-			}
-
-			/* These are used multiple times, calculate and store them */
-			blockBitSize = blockByteSize * 8;
-			lastArrayIndex = (blockByteSize / 4) - 1;
-
-			/* Figure out what to do with the key based on its size relative to
-			 * the hash's block size */
-			if (blockByteSize < (keyBinLen / 8))
-			{
-				if ("SHA-1" === variant)
-				{
-					keyToUse = coreSHA1(keyToUse, keyBinLen);
-				}
-				else
-				{
-					keyToUse = coreSHA2(keyToUse, keyBinLen, variant);
-				}
-				/* For all variants, the block size is bigger than the output
-				 * size so there will never be a useful byte at the end of the
-				 * string */
-				keyToUse[lastArrayIndex] &= 0xFFFFFF00;
-			}
-			else if (blockByteSize > (keyBinLen / 8))
-			{
-				/* If the blockByteSize is greater than the key length, there
-				 * will always be at LEAST one "useless" byte at the end of the
-				 * string */
-				keyToUse[lastArrayIndex] &= 0xFFFFFF00;
-			}
-
-			/* Create ipad and opad */
-			for (i = 0; i <= lastArrayIndex; i += 1)
-			{
-				keyWithIPad[i] = keyToUse[i] ^ 0x36363636;
-				keyWithOPad[i] = keyToUse[i] ^ 0x5C5C5C5C;
-			}
-
-			/* Calculate the HMAC */
-			if ("SHA-1" === variant)
-			{
-				retVal = coreSHA1(
-							keyWithIPad.concat(this.strToHash),
-							blockBitSize + this.strBinLen);
-				retVal = coreSHA1(
-							keyWithOPad.concat(retVal),
-							blockBitSize + hashBitSize);
-			}
-			else
-			{
-				retVal = coreSHA2(
-							keyWithIPad.concat(this.strToHash),
-							blockBitSize + this.strBinLen, variant);
-				retVal = coreSHA2(
-							keyWithOPad.concat(retVal),
-							blockBitSize + hashBitSize, variant);
-			}
-
-			return (formatFunc(retVal));
-		}
-	};
-
-	return jsSHA;
-}());
-
-function str_sha1(str) {
-	var shaObj = new jsSHA(str, "ASCII");
-	return shaObj.getHash("SHA-1", "ASCII");
-}
-
-function str_sha224(str) {
-	var shaObj = new jsSHA(str, "ASCII");
-	return shaObj.getHash("SHA-224", "ASCII");
-}
-
-function str_sha256(str) {
-	var shaObj = new jsSHA(str, "ASCII");
-	return shaObj.getHash("SHA-256", "ASCII");
-}
-
-
-function str_sha384(str) {
-	var shaObj = new jsSHA(str, "ASCII");
-	return shaObj.getHash("SHA-384", "ASCII");
-
-}
-
-function str_sha512(str) {
-	var shaObj = new jsSHA(str, "ASCII");
-	return shaObj.getHash("SHA-512", "ASCII");
-}
-/*
- * CryptoMX Tools
- * Copyright (C) 2004 - 2006 Derek Buitenhuis
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-/* Modified by Recurity Labs GmbH
- */
-
-var RMDsize   = 160;
-var X = new Array();
-
-function ROL(x, n)
-{
-  return new Number ((x << n) | ( x >>> (32 - n)));
-}
-
-function F(x, y, z)
-{
-  return new Number(x ^ y ^ z);
-}
-
-function G(x, y, z)
-{
-  return new Number((x & y) | (~x & z));
-}
-
-function H(x, y, z)
-{
-  return new Number((x | ~y) ^ z);
-}
-
-function I(x, y, z)
-{
-  return new Number((x & z) | (y & ~z));
-}
-
-function J(x, y, z)
-{
-  return new Number(x ^ (y | ~z));
-}
-
-function mixOneRound(a, b, c, d, e, x, s, roundNumber)
-{
-  switch (roundNumber)
-  {
-    case 0 : a += F(b, c, d) + x + 0x00000000; break;
-    case 1 : a += G(b, c, d) + x + 0x5a827999; break;
-    case 2 : a += H(b, c, d) + x + 0x6ed9eba1; break;
-    case 3 : a += I(b, c, d) + x + 0x8f1bbcdc; break;
-    case 4 : a += J(b, c, d) + x + 0xa953fd4e; break;
-    case 5 : a += J(b, c, d) + x + 0x50a28be6; break;
-    case 6 : a += I(b, c, d) + x + 0x5c4dd124; break;
-    case 7 : a += H(b, c, d) + x + 0x6d703ef3; break;
-    case 8 : a += G(b, c, d) + x + 0x7a6d76e9; break;
-    case 9 : a += F(b, c, d) + x + 0x00000000; break;
-    
-    default : document.write("Bogus round number"); break;
-  }  
-  
-  a = ROL(a, s) + e;
-  c = ROL(c, 10);
-
-  a &= 0xffffffff;
-  b &= 0xffffffff;
-  c &= 0xffffffff;
-  d &= 0xffffffff;
-  e &= 0xffffffff;
-
-  var retBlock = new Array();
-  retBlock[0] = a;
-  retBlock[1] = b;
-  retBlock[2] = c;
-  retBlock[3] = d;
-  retBlock[4] = e;
-  retBlock[5] = x;
-  retBlock[6] = s;
-
-  return retBlock;
-}
-
-function MDinit (MDbuf)
-{
-  MDbuf[0] = 0x67452301;
-  MDbuf[1] = 0xefcdab89;
-  MDbuf[2] = 0x98badcfe;
-  MDbuf[3] = 0x10325476;
-  MDbuf[4] = 0xc3d2e1f0;
-}
-
-var ROLs = [
-  [11, 14, 15, 12,  5,  8,  7,  9, 11, 13, 14, 15,  6,  7,  9,  8],
-  [ 7,  6,  8, 13, 11,  9,  7, 15,  7, 12, 15,  9, 11,  7, 13, 12],
-  [11, 13,  6,  7, 14,  9, 13, 15, 14,  8, 13,  6,  5, 12,  7,  5],
-  [11, 12, 14, 15, 14, 15,  9,  8,  9, 14,  5,  6,  8,  6,  5, 12],
-  [ 9, 15,  5, 11,  6,  8, 13, 12,  5, 12, 13, 14, 11,  8,  5,  6],
-  [ 8,  9,  9, 11, 13, 15, 15,  5,  7,  7,  8, 11, 14, 14, 12,  6],
-  [ 9, 13, 15,  7, 12,  8,  9, 11,  7,  7, 12,  7,  6, 15, 13, 11],
-  [ 9,  7, 15, 11,  8,  6,  6, 14, 12, 13,  5, 14, 13, 13,  7,  5],
-  [15,  5,  8, 11, 14, 14,  6, 14,  6,  9, 12,  9, 12,  5, 15,  8],
-  [ 8,  5, 12,  9, 12,  5, 14,  6,  8, 13,  6,  5, 15, 13, 11, 11]
-];
-
-var indexes = [
-  [ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15],
-  [ 7,  4, 13,  1, 10,  6, 15,  3, 12,  0,  9,  5,  2, 14, 11,  8],
-  [ 3, 10, 14,  4,  9, 15,  8,  1,  2,  7,  0,  6, 13, 11,  5, 12],
-  [ 1,  9, 11, 10,  0,  8, 12,  4, 13,  3,  7, 15, 14,  5,  6,  2],
-  [ 4,  0,  5,  9,  7, 12,  2, 10, 14,  1,  3,  8, 11,  6, 15, 13],
-  [ 5, 14,  7,  0,  9,  2, 11,  4, 13,  6, 15,  8,  1, 10,  3, 12],
-  [ 6, 11,  3,  7,  0, 13,  5, 10, 14, 15,  8, 12,  4,  9,  1,  2],
-  [15,  5,  1,  3,  7, 14,  6,  9, 11,  8, 12,  2, 10,  0,  4, 13],
-  [ 8,  6,  4,  1,  3, 11, 15,  0,  5, 12,  2, 13,  9,  7, 10, 14],
-  [12, 15, 10,  4,  1,  5,  8,  7,  6,  2, 13, 14,  0,  3,  9, 11]
-];
-
-function compress (MDbuf, X)
-{
-  blockA = new Array();
-  blockB = new Array();
-
-  var retBlock;
-
-  for (var i=0; i < 5; i++)
-  {
-    blockA[i] = new Number(MDbuf[i]);
-    blockB[i] = new Number(MDbuf[i]);
-  }
-
-  var step = 0;
-  for (var j = 0; j < 5; j++)
-  {
-    for (var i = 0; i < 16; i++)
-    {
-      retBlock = mixOneRound(
-        blockA[(step+0) % 5],
-        blockA[(step+1) % 5],   
-        blockA[(step+2) % 5],   
-        blockA[(step+3) % 5],   
-        blockA[(step+4) % 5],  
-        X[indexes[j][i]], 
-        ROLs[j][i],
-        j
-      );
-
-      blockA[(step+0) % 5] = retBlock[0];
-      blockA[(step+1) % 5] = retBlock[1];
-      blockA[(step+2) % 5] = retBlock[2];
-      blockA[(step+3) % 5] = retBlock[3];
-      blockA[(step+4) % 5] = retBlock[4];
-
-      step += 4;
-    }
-  }
-
-  step = 0;
-  for (var j = 5; j < 10; j++)
-  {
-    for (var i = 0; i < 16; i++)
-    {  
-      retBlock = mixOneRound(
-        blockB[(step+0) % 5], 
-        blockB[(step+1) % 5], 
-        blockB[(step+2) % 5], 
-        blockB[(step+3) % 5], 
-        blockB[(step+4) % 5],  
-        X[indexes[j][i]], 
-        ROLs[j][i],
-        j
-      );
-
-      blockB[(step+0) % 5] = retBlock[0];
-      blockB[(step+1) % 5] = retBlock[1];
-      blockB[(step+2) % 5] = retBlock[2];
-      blockB[(step+3) % 5] = retBlock[3];
-      blockB[(step+4) % 5] = retBlock[4];
-
-      step += 4;
-    }
-  }
-
-  blockB[3] += blockA[2] + MDbuf[1];
-  MDbuf[1]  = MDbuf[2] + blockA[3] + blockB[4];
-  MDbuf[2]  = MDbuf[3] + blockA[4] + blockB[0];
-  MDbuf[3]  = MDbuf[4] + blockA[0] + blockB[1];
-  MDbuf[4]  = MDbuf[0] + blockA[1] + blockB[2];
-  MDbuf[0]  = blockB[3];
-}
-
-function zeroX(X)
-{
-  for (var i = 0; i < 16; i++) { X[i] = 0; }
-}
-
-function MDfinish (MDbuf, strptr, lswlen, mswlen)
-{
-  var X = new Array(16);
-  zeroX(X);
-
-  var j = 0;
-  for (var i=0; i < (lswlen & 63); i++)
-  {
-    X[i >>> 2] ^= (strptr.charCodeAt(j++) & 255) << (8 * (i & 3));
-  }
-
-  X[(lswlen >>> 2) & 15] ^= 1 << (8 * (lswlen & 3) + 7);
-
-  if ((lswlen & 63) > 55)
-  {
-    compress(MDbuf, X);
-    var X = new Array(16);
-    zeroX(X);
-  }
-
-  X[14] = lswlen << 3;
-  X[15] = (lswlen >>> 29) | (mswlen << 3);
-
-  compress(MDbuf, X);
-}
-
-function BYTES_TO_DWORD(fourChars)
-{
-  var tmp  = (fourChars.charCodeAt(3) & 255) << 24;
-  tmp   |= (fourChars.charCodeAt(2) & 255) << 16;
-  tmp   |= (fourChars.charCodeAt(1) & 255) << 8;
-  tmp   |= (fourChars.charCodeAt(0) & 255);  
-
-  return tmp;
-}
-
-function RMD(message)
-{
-  var MDbuf   = new Array(RMDsize / 32);
-  var hashcode   = new Array(RMDsize / 8);
-  var length;  
-  var nbytes;
-
-  MDinit(MDbuf);
-  length = message.length;
-
-  var X = new Array(16);
-  zeroX(X);
-
-  var j=0;
-  for (var nbytes=length; nbytes > 63; nbytes -= 64)
-  {
-    for (var i=0; i < 16; i++)
-    {
-      X[i] = BYTES_TO_DWORD(message.substr(j, 4));
-      j += 4;
-    }
-    compress(MDbuf, X);
-  }
-
-  MDfinish(MDbuf, message.substr(j), length, 0);
-
-  for (var i=0; i < RMDsize / 8; i += 4)
-  {
-    hashcode[i]   =  MDbuf[i >>> 2]   & 255;
-    hashcode[i+1] = (MDbuf[i >>> 2] >>> 8)   & 255;
-    hashcode[i+2] = (MDbuf[i >>> 2] >>> 16) & 255;
-    hashcode[i+3] = (MDbuf[i >>> 2] >>> 24) & 255;
-  }
-
-  return hashcode;
-}
-
-
-function RMDstring(message)
-{
-  var hashcode = RMD(message);
-  var retString = "";
-
-  for (var i=0; i < RMDsize/8; i++)
-  {
-    retString += String.fromCharCode(hashcode[i]);
-  }  
-
-  return retString;  
-}/* Modified by Recurity Labs GmbH 
- * 
- * Originally written by nklein software (nklein.com)
- */
-
-/* 
- * Javascript implementation based on Bruce Schneier's reference implementation.
- *
- *
- * The constructor doesn't do much of anything.  It's just here
- * so we can start defining properties and methods and such.
- */
-function Blowfish() {
-};
-
-/*
- * Declare the block size so that protocols know what size
- * Initialization Vector (IV) they will need.
- */
-Blowfish.prototype.BLOCKSIZE = 8;
-
-/*
- * These are the default SBOXES.
- */
-Blowfish.prototype.SBOXES = [
-    [
-	0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
-	0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
-	0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
-	0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
-	0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
-	0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
-	0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
-	0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
-	0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
-	0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
-	0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
-	0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
-	0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
-	0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
-	0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
-	0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
-	0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
-	0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
-	0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
-	0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
-	0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
-	0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
-	0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
-	0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
-	0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
-	0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
-	0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
-	0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
-	0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
-	0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
-	0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
-	0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
-	0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
-	0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
-	0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
-	0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
-	0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
-	0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
-	0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
-	0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
-	0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
-	0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
-	0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
-    ], [
-	0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
-	0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
-	0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
-	0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
-	0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
-	0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
-	0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
-	0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
-	0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
-	0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
-	0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
-	0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
-	0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
-	0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
-	0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
-	0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
-	0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
-	0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
-	0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
-	0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
-	0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
-	0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
-	0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
-	0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
-	0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
-	0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
-	0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
-	0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
-	0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
-	0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
-	0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
-	0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
-	0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
-	0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
-	0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
-	0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
-	0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
-	0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
-	0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
-	0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
-	0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
-	0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
-	0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
-    ], [
-	0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
-	0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
-	0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
-	0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
-	0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
-	0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
-	0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
-	0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
-	0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
-	0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
-	0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
-	0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
-	0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
-	0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
-	0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
-	0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
-	0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
-	0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
-	0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
-	0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
-	0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
-	0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
-	0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
-	0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
-	0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
-	0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
-	0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
-	0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
-	0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
-	0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
-	0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
-	0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
-	0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
-	0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
-	0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
-	0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
-	0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
-	0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
-	0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
-	0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
-	0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
-	0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
-	0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
-    ], [
-	0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
-	0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
-	0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
-	0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
-	0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
-	0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
-	0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
-	0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
-	0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
-	0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
-	0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
-	0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
-	0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
-	0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
-	0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
-	0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
-	0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
-	0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
-	0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
-	0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
-	0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
-	0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
-	0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
-	0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
-	0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
-	0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
-	0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
-	0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
-	0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
-	0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
-	0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
-	0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
-	0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
-	0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
-	0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
-	0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
-	0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
-	0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
-	0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
-	0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
-	0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
-	0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
-	0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
-    ]
-];
-
-//*
-//* This is the default PARRAY
-//*
-Blowfish.prototype.PARRAY = [
-    0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
-    0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
-    0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b
-];
-
-//*
-//* This is the number of rounds the cipher will go
-//*
-Blowfish.prototype.NN = 16;
-
-//*
-//* This function is needed to get rid of problems
-//* with the high-bit getting set.  If we don't do
-//* this, then sometimes ( aa & 0x00FFFFFFFF ) is not
-//* equal to ( bb & 0x00FFFFFFFF ) even when they
-//* agree bit-for-bit for the first 32 bits.
-//*
-Blowfish.prototype._clean = function( xx ) {
-    if ( xx < 0 ) {
-	var yy = xx & 0x7FFFFFFF;
-	xx = yy + 0x80000000;
-    }
-    return xx;
-};
-
-//*
-//* This is the mixing function that uses the sboxes
-//*
-Blowfish.prototype._F = function ( xx ) {
-    var aa;
-    var bb;
-    var cc;
-    var dd;
-    var yy;
-
-    dd = xx & 0x00FF;
-    xx >>>= 8;
-    cc = xx & 0x00FF;
-    xx >>>= 8;
-    bb = xx & 0x00FF;
-    xx >>>= 8;
-    aa = xx & 0x00FF;
-
-    yy = this.sboxes[ 0 ][ aa ] + this.sboxes[ 1 ][ bb ];
-    yy = yy ^ this.sboxes[ 2 ][ cc ];
-    yy = yy + this.sboxes[ 3 ][ dd ];
-
-    return yy;
-};
-
-//*
-//* This method takes an array with two values, left and right
-//* and does NN rounds of Blowfish on them.
-//*
-Blowfish.prototype._encrypt_block = function ( vals ) {
-    var dataL = vals[ 0 ];
-    var dataR = vals[ 1 ];
-
-    var ii;
-
-    for ( ii=0; ii < this.NN; ++ii ) {
-	dataL = dataL ^ this.parray[ ii ];
-	dataR = this._F( dataL ) ^ dataR;
-
-	var tmp = dataL;
-	dataL = dataR;
-	dataR = tmp;
-    }
-
-    dataL = dataL ^ this.parray[ this.NN + 0 ];
-    dataR = dataR ^ this.parray[ this.NN + 1 ];
-
-    vals[ 0 ] = this._clean( dataR );
-    vals[ 1 ] = this._clean( dataL );
-};
-
-//*
-//* This method takes a vector of numbers and turns them
-//* into long words so that they can be processed by the
-//* real algorithm.
-//*
-//* Maybe I should make the real algorithm above take a vector
-//* instead.  That will involve more looping, but it won't require
-//* the F() method to deconstruct the vector.
-//*
-Blowfish.prototype.encrypt_block = function ( vector ) {
-    var ii;
-    var vals = [ 0, 0 ];
-    var off  = this.BLOCKSIZE/2;
-    for ( ii = 0; ii < this.BLOCKSIZE/2; ++ii ) {
-	vals[0] = ( vals[0] << 8 ) | ( vector[ ii + 0   ] & 0x00FF );
-	vals[1] = ( vals[1] << 8 ) | ( vector[ ii + off ] & 0x00FF );
-    }
-
-    this._encrypt_block( vals );
-
-    var ret = [ ];
-    for ( ii = 0; ii < this.BLOCKSIZE/2; ++ii ) {
-	ret[ ii + 0   ] = ( vals[ 0 ] >>> (24 - 8*(ii)) & 0x00FF );
-	ret[ ii + off ] = ( vals[ 1 ] >>> (24 - 8*(ii)) & 0x00FF );
-	// vals[ 0 ] = ( vals[ 0 ] >>> 8 );
-	// vals[ 1 ] = ( vals[ 1 ] >>> 8 );
-    }
-
-    return ret;
-};
-
-//*
-//* This method takes an array with two values, left and right
-//* and undoes NN rounds of Blowfish on them.
-//*
-Blowfish.prototype._decrypt_block = function ( vals ) {
-    var dataL = vals[ 0 ];
-    var dataR = vals[ 1 ];
-
-    var ii;
-
-    for ( ii=this.NN+1; ii > 1; --ii ) {
-	dataL = dataL ^ this.parray[ ii ];
-	dataR = this._F( dataL ) ^ dataR;
-
-	var tmp = dataL;
-	dataL = dataR;
-	dataR = tmp;
-    }
-
-    dataL = dataL ^ this.parray[ 1 ];
-    dataR = dataR ^ this.parray[ 0 ];
-
-    vals[ 0 ] = this._clean( dataR );
-    vals[ 1 ] = this._clean( dataL );
-};
-
-//*
-//* This method takes a key array and initializes the
-//* sboxes and parray for this encryption.
-//*
-Blowfish.prototype.init = function ( key ) {
-    var ii;
-    var jj = 0;
-
-    this.parray = [];
-    for ( ii=0; ii < this.NN + 2; ++ii ) {
-	var data = 0x00000000;
-	var kk;
-	for ( kk=0; kk < 4; ++kk ) {
-	    data = ( data << 8 ) | ( key[ jj ] & 0x00FF );
-	    if ( ++jj >= key.length ) {
-		jj = 0;
-	    }
-	}
-	this.parray[ ii ] = this.PARRAY[ ii ] ^ data;
-    }
-
-    this.sboxes = [];
-    for ( ii=0; ii < 4; ++ii ) {
-	this.sboxes[ ii ] = [];
-	for ( jj=0; jj < 256; ++jj ) {
-	    this.sboxes[ ii ][ jj ] = this.SBOXES[ ii ][ jj ];
-	}
-    }
-
-    var vals = [ 0x00000000, 0x00000000 ];
-
-    for ( ii=0; ii < this.NN+2; ii += 2 ) {
-	this._encrypt_block( vals );
-	this.parray[ ii + 0 ] = vals[ 0 ];
-	this.parray[ ii + 1 ] = vals[ 1 ];
-    }
-
-    for ( ii=0; ii < 4; ++ii ) {
-	for ( jj=0; jj < 256; jj += 2 ) {
-	    this._encrypt_block( vals );
-	    this.sboxes[ ii ][ jj + 0 ] = vals[ 0 ];
-	    this.sboxes[ ii ][ jj + 1 ] = vals[ 1 ];
-	}
-    }
-};
-
-// added by Recurity Labs
-function BFencrypt(block,key) {
-	var bf = new Blowfish();
-	bf.init(util.str2bin(key));
-	return bf.encrypt_block(block);
-}
-//Paul Tero, July 2001
-//http://www.tero.co.uk/des/
-//
-//Optimised for performance with large blocks by Michael Hayworth, November 2001
-//http://www.netdealing.com
-//
-// Modified by Recurity Labs GmbH
-
-//THIS SOFTWARE IS PROVIDED "AS IS" AND
-//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-//IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-//ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-//FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-//DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-//OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-//HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-//OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-//SUCH DAMAGE.
-
-//des
-//this takes the key, the message, and whether to encrypt or decrypt
-
-// added by Recurity Labs
-function desede(block,key) {
-	var key1 = key.substring(0,8);
-	var key2 = key.substring(8,16);
-	var key3 = key.substring(16,24);
-	return util.str2bin(des(des_createKeys(key3),des(des_createKeys(key2),des(des_createKeys(key1),util.bin2str(block), true, 0,null,null), false, 0,null,null), true, 0,null,null));
-}
-
-
-function des (keys, message, encrypt, mode, iv, padding) {
-  //declaring this locally speeds things up a bit
-  var spfunction1 = new Array (0x1010400,0,0x10000,0x1010404,0x1010004,0x10404,0x4,0x10000,0x400,0x1010400,0x1010404,0x400,0x1000404,0x1010004,0x1000000,0x4,0x404,0x1000400,0x1000400,0x10400,0x10400,0x1010000,0x1010000,0x1000404,0x10004,0x1000004,0x1000004,0x10004,0,0x404,0x10404,0x1000000,0x10000,0x1010404,0x4,0x1010000,0x1010400,0x1000000,0x1000000,0x400,0x1010004,0x10000,0x10400,0x1000004,0x400,0x4,0x1000404,0x10404,0x1010404,0x10004,0x1010000,0x1000404,0x1000004,0x404,0x10404,0x1010400,0x404,0x1000400,0x1000400,0,0x10004,0x10400,0,0x1010004);
-  var spfunction2 = new Array (-0x7fef7fe0,-0x7fff8000,0x8000,0x108020,0x100000,0x20,-0x7fefffe0,-0x7fff7fe0,-0x7fffffe0,-0x7fef7fe0,-0x7fef8000,-0x80000000,-0x7fff8000,0x100000,0x20,-0x7fefffe0,0x108000,0x100020,-0x7fff7fe0,0,-0x80000000,0x8000,0x108020,-0x7ff00000,0x100020,-0x7fffffe0,0,0x108000,0x8020,-0x7fef8000,-0x7ff00000,0x8020,0,0x108020,-0x7fefffe0,0x100000,-0x7fff7fe0,-0x7ff00000,-0x7fef8000,0x8000,-0x7ff00000,-0x7fff8000,0x20,-0x7fef7fe0,0x108020,0x20,0x8000,-0x80000000,0x8020,-0x7fef8000,0x100000,-0x7fffffe0,0x100020,-0x7fff7fe0,-0x7fffffe0,0x100020,0x108000,0,-0x7fff8000,0x8020,-0x80000000,-0x7fefffe0,-0x7fef7fe0,0x108000);
-  var spfunction3 = new Array (0x208,0x8020200,0,0x8020008,0x8000200,0,0x20208,0x8000200,0x20008,0x8000008,0x8000008,0x20000,0x8020208,0x20008,0x8020000,0x208,0x8000000,0x8,0x8020200,0x200,0x20200,0x8020000,0x8020008,0x20208,0x8000208,0x20200,0x20000,0x8000208,0x8,0x8020208,0x200,0x8000000,0x8020200,0x8000000,0x20008,0x208,0x20000,0x8020200,0x8000200,0,0x200,0x20008,0x8020208,0x8000200,0x8000008,0x200,0,0x8020008,0x8000208,0x20000,0x8000000,0x8020208,0x8,0x20208,0x20200,0x8000008,0x8020000,0x8000208,0x208,0x8020000,0x20208,0x8,0x8020008,0x20200);
-  var spfunction4 = new Array (0x802001,0x2081,0x2081,0x80,0x802080,0x800081,0x800001,0x2001,0,0x802000,0x802000,0x802081,0x81,0,0x800080,0x800001,0x1,0x2000,0x800000,0x802001,0x80,0x800000,0x2001,0x2080,0x800081,0x1,0x2080,0x800080,0x2000,0x802080,0x802081,0x81,0x800080,0x800001,0x802000,0x802081,0x81,0,0,0x802000,0x2080,0x800080,0x800081,0x1,0x802001,0x2081,0x2081,0x80,0x802081,0x81,0x1,0x2000,0x800001,0x2001,0x802080,0x800081,0x2001,0x2080,0x800000,0x802001,0x80,0x800000,0x2000,0x802080);
-  var spfunction5 = new Array (0x100,0x2080100,0x2080000,0x42000100,0x80000,0x100,0x40000000,0x2080000,0x40080100,0x80000,0x2000100,0x40080100,0x42000100,0x42080000,0x80100,0x40000000,0x2000000,0x40080000,0x40080000,0,0x40000100,0x42080100,0x42080100,0x2000100,0x42080000,0x40000100,0,0x42000000,0x2080100,0x2000000,0x42000000,0x80100,0x80000,0x42000100,0x100,0x2000000,0x40000000,0x2080000,0x42000100,0x40080100,0x2000100,0x40000000,0x42080000,0x2080100,0x40080100,0x100,0x2000000,0x42080000,0x42080100,0x80100,0x42000000,0x42080100,0x2080000,0,0x40080000,0x42000000,0x80100,0x2000100,0x40000100,0x80000,0,0x40080000,0x2080100,0x40000100);
-  var spfunction6 = new Array (0x20000010,0x20400000,0x4000,0x20404010,0x20400000,0x10,0x20404010,0x400000,0x20004000,0x404010,0x400000,0x20000010,0x400010,0x20004000,0x20000000,0x4010,0,0x400010,0x20004010,0x4000,0x404000,0x20004010,0x10,0x20400010,0x20400010,0,0x404010,0x20404000,0x4010,0x404000,0x20404000,0x20000000,0x20004000,0x10,0x20400010,0x404000,0x20404010,0x400000,0x4010,0x20000010,0x400000,0x20004000,0x20000000,0x4010,0x20000010,0x20404010,0x404000,0x20400000,0x404010,0x20404000,0,0x20400010,0x10,0x4000,0x20400000,0x404010,0x4000,0x400010,0x20004010,0,0x20404000,0x20000000,0x400010,0x20004010);
-  var spfunction7 = new Array (0x200000,0x4200002,0x4000802,0,0x800,0x4000802,0x200802,0x4200800,0x4200802,0x200000,0,0x4000002,0x2,0x4000000,0x4200002,0x802,0x4000800,0x200802,0x200002,0x4000800,0x4000002,0x4200000,0x4200800,0x200002,0x4200000,0x800,0x802,0x4200802,0x200800,0x2,0x4000000,0x200800,0x4000000,0x200800,0x200000,0x4000802,0x4000802,0x4200002,0x4200002,0x2,0x200002,0x4000000,0x4000800,0x200000,0x4200800,0x802,0x200802,0x4200800,0x802,0x4000002,0x4200802,0x4200000,0x200800,0,0x2,0x4200802,0,0x200802,0x4200000,0x800,0x4000002,0x4000800,0x800,0x200002);
-  var spfunction8 = new Array (0x10001040,0x1000,0x40000,0x10041040,0x10000000,0x10001040,0x40,0x10000000,0x40040,0x10040000,0x10041040,0x41000,0x10041000,0x41040,0x1000,0x40,0x10040000,0x10000040,0x10001000,0x1040,0x41000,0x40040,0x10040040,0x10041000,0x1040,0,0,0x10040040,0x10000040,0x10001000,0x41040,0x40000,0x41040,0x40000,0x10041000,0x1000,0x40,0x10040040,0x1000,0x41040,0x10001000,0x40,0x10000040,0x10040000,0x10040040,0x10000000,0x40000,0x10001040,0,0x10041040,0x40040,0x10000040,0x10040000,0x10001000,0x10001040,0,0x10041040,0x41000,0x41000,0x1040,0x1040,0x40040,0x10000000,0x10041000);
-
-  //create the 16 or 48 subkeys we will need
-  var m=0, i, j, temp, temp2, right1, right2, left, right, looping;
-  var cbcleft, cbcleft2, cbcright, cbcright2
-  var endloop, loopinc;
-  var len = message.length;
-  var chunk = 0;
-  //set up the loops for single and triple des
-  var iterations = keys.length == 32 ? 3 : 9; //single or triple des
-  if (iterations == 3) {looping = encrypt ? new Array (0, 32, 2) : new Array (30, -2, -2);}
-  else {looping = encrypt ? new Array (0, 32, 2, 62, 30, -2, 64, 96, 2) : new Array (94, 62, -2, 32, 64, 2, 30, -2, -2);}
-
-  //pad the message depending on the padding parameter
-  if (padding == 2) message += "        "; //pad the message with spaces
-  else if (padding == 1) {temp = 8-(len%8); message += String.fromCharCode (temp,temp,temp,temp,temp,temp,temp,temp); if (temp==8) len+=8;} //PKCS7 padding
-  else if (!padding) message += "\0\0\0\0\0\0\0\0"; //pad the message out with null bytes
-
-  //store the result here
-  result = "";
-  tempresult = "";
-
-  if (mode == 1) { //CBC mode
-    cbcleft = (iv.charCodeAt(m++) << 24) | (iv.charCodeAt(m++) << 16) | (iv.charCodeAt(m++) << 8) | iv.charCodeAt(m++);
-    cbcright = (iv.charCodeAt(m++) << 24) | (iv.charCodeAt(m++) << 16) | (iv.charCodeAt(m++) << 8) | iv.charCodeAt(m++);
-    m=0;
-  }
-
-  //loop through each 64 bit chunk of the message
-  while (m < len) {
-    left = (message.charCodeAt(m++) << 24) | (message.charCodeAt(m++) << 16) | (message.charCodeAt(m++) << 8) | message.charCodeAt(m++);
-    right = (message.charCodeAt(m++) << 24) | (message.charCodeAt(m++) << 16) | (message.charCodeAt(m++) << 8) | message.charCodeAt(m++);
-
-    //for Cipher Block Chaining mode, xor the message with the previous result
-    if (mode == 1) {if (encrypt) {left ^= cbcleft; right ^= cbcright;} else {cbcleft2 = cbcleft; cbcright2 = cbcright; cbcleft = left; cbcright = right;}}
-
-    //first each 64 but chunk of the message must be permuted according to IP
-    temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4);
-    temp = ((left >>> 16) ^ right) & 0x0000ffff; right ^= temp; left ^= (temp << 16);
-    temp = ((right >>> 2) ^ left) & 0x33333333; left ^= temp; right ^= (temp << 2);
-    temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8);
-    temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
-
-    left = ((left << 1) | (left >>> 31)); 
-    right = ((right << 1) | (right >>> 31)); 
-
-    //do this either 1 or 3 times for each chunk of the message
-    for (j=0; j<iterations; j+=3) {
-      endloop = looping[j+1];
-      loopinc = looping[j+2];
-      //now go through and perform the encryption or decryption  
-      for (i=looping[j]; i!=endloop; i+=loopinc) { //for efficiency
-        right1 = right ^ keys[i]; 
-        right2 = ((right >>> 4) | (right << 28)) ^ keys[i+1];
-        //the result is attained by passing these bytes through the S selection functions
-        temp = left;
-        left = right;
-        right = temp ^ (spfunction2[(right1 >>> 24) & 0x3f] | spfunction4[(right1 >>> 16) & 0x3f]
-              | spfunction6[(right1 >>>  8) & 0x3f] | spfunction8[right1 & 0x3f]
-              | spfunction1[(right2 >>> 24) & 0x3f] | spfunction3[(right2 >>> 16) & 0x3f]
-              | spfunction5[(right2 >>>  8) & 0x3f] | spfunction7[right2 & 0x3f]);
-      }
-      temp = left; left = right; right = temp; //unreverse left and right
-    } //for either 1 or 3 iterations
-
-    //move then each one bit to the right
-    left = ((left >>> 1) | (left << 31)); 
-    right = ((right >>> 1) | (right << 31)); 
-
-    //now perform IP-1, which is IP in the opposite direction
-    temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
-    temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8);
-    temp = ((right >>> 2) ^ left) & 0x33333333; left ^= temp; right ^= (temp << 2);
-    temp = ((left >>> 16) ^ right) & 0x0000ffff; right ^= temp; left ^= (temp << 16);
-    temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4);
-
-    //for Cipher Block Chaining mode, xor the message with the previous result
-    if (mode == 1) {if (encrypt) {cbcleft = left; cbcright = right;} else {left ^= cbcleft2; right ^= cbcright2;}}
-    tempresult += String.fromCharCode ((left>>>24), ((left>>>16) & 0xff), ((left>>>8) & 0xff), (left & 0xff), (right>>>24), ((right>>>16) & 0xff), ((right>>>8) & 0xff), (right & 0xff));
-
-    chunk += 8;
-    if (chunk == 512) {result += tempresult; tempresult = ""; chunk = 0;}
-  } //for every 8 characters, or 64 bits in the message
-
-  //return the result as an array
-  result += tempresult;
-  result = result.replace(/\0*$/g, "");
-  return result;
-} //end of des
-
-
-
-//des_createKeys
-//this takes as input a 64 bit key (even though only 56 bits are used)
-//as an array of 2 integers, and returns 16 48 bit keys
-function des_createKeys (key) {
-  //declaring this locally speeds things up a bit
-  pc2bytes0  = new Array (0,0x4,0x20000000,0x20000004,0x10000,0x10004,0x20010000,0x20010004,0x200,0x204,0x20000200,0x20000204,0x10200,0x10204,0x20010200,0x20010204);
-  pc2bytes1  = new Array (0,0x1,0x100000,0x100001,0x4000000,0x4000001,0x4100000,0x4100001,0x100,0x101,0x100100,0x100101,0x4000100,0x4000101,0x4100100,0x4100101);
-  pc2bytes2  = new Array (0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808,0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808);
-  pc2bytes3  = new Array (0,0x200000,0x8000000,0x8200000,0x2000,0x202000,0x8002000,0x8202000,0x20000,0x220000,0x8020000,0x8220000,0x22000,0x222000,0x8022000,0x8222000);
-  pc2bytes4  = new Array (0,0x40000,0x10,0x40010,0,0x40000,0x10,0x40010,0x1000,0x41000,0x1010,0x41010,0x1000,0x41000,0x1010,0x41010);
-  pc2bytes5  = new Array (0,0x400,0x20,0x420,0,0x400,0x20,0x420,0x2000000,0x2000400,0x2000020,0x2000420,0x2000000,0x2000400,0x2000020,0x2000420);
-  pc2bytes6  = new Array (0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002,0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002);
-  pc2bytes7  = new Array (0,0x10000,0x800,0x10800,0x20000000,0x20010000,0x20000800,0x20010800,0x20000,0x30000,0x20800,0x30800,0x20020000,0x20030000,0x20020800,0x20030800);
-  pc2bytes8  = new Array (0,0x40000,0,0x40000,0x2,0x40002,0x2,0x40002,0x2000000,0x2040000,0x2000000,0x2040000,0x2000002,0x2040002,0x2000002,0x2040002);
-  pc2bytes9  = new Array (0,0x10000000,0x8,0x10000008,0,0x10000000,0x8,0x10000008,0x400,0x10000400,0x408,0x10000408,0x400,0x10000400,0x408,0x10000408);
-  pc2bytes10 = new Array (0,0x20,0,0x20,0x100000,0x100020,0x100000,0x100020,0x2000,0x2020,0x2000,0x2020,0x102000,0x102020,0x102000,0x102020);
-  pc2bytes11 = new Array (0,0x1000000,0x200,0x1000200,0x200000,0x1200000,0x200200,0x1200200,0x4000000,0x5000000,0x4000200,0x5000200,0x4200000,0x5200000,0x4200200,0x5200200);
-  pc2bytes12 = new Array (0,0x1000,0x8000000,0x8001000,0x80000,0x81000,0x8080000,0x8081000,0x10,0x1010,0x8000010,0x8001010,0x80010,0x81010,0x8080010,0x8081010);
-  pc2bytes13 = new Array (0,0x4,0x100,0x104,0,0x4,0x100,0x104,0x1,0x5,0x101,0x105,0x1,0x5,0x101,0x105);
-
-  //how many iterations (1 for des, 3 for triple des)
-  var iterations = key.length > 8 ? 3 : 1; //changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys
-  //stores the return keys
-  var keys = new Array (32 * iterations);
-  //now define the left shifts which need to be done
-  var shifts = new Array (0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0);
-  //other variables
-  var lefttemp, righttemp, m=0, n=0, temp;
-
-  for (var j=0; j<iterations; j++) { //either 1 or 3 iterations
-    left = (key.charCodeAt(m++) << 24) | (key.charCodeAt(m++) << 16) | (key.charCodeAt(m++) << 8) | key.charCodeAt(m++);
-    right = (key.charCodeAt(m++) << 24) | (key.charCodeAt(m++) << 16) | (key.charCodeAt(m++) << 8) | key.charCodeAt(m++);
-
-    temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4);
-    temp = ((right >>> -16) ^ left) & 0x0000ffff; left ^= temp; right ^= (temp << -16);
-    temp = ((left >>> 2) ^ right) & 0x33333333; right ^= temp; left ^= (temp << 2);
-    temp = ((right >>> -16) ^ left) & 0x0000ffff; left ^= temp; right ^= (temp << -16);
-    temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
-    temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8);
-    temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
-
-    //the right side needs to be shifted and to get the last four bits of the left side
-    temp = (left << 8) | ((right >>> 20) & 0x000000f0);
-    //left needs to be put upside down
-    left = (right << 24) | ((right << 8) & 0xff0000) | ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0);
-    right = temp;
-
-    //now go through and perform these shifts on the left and right keys
-    for (i=0; i < shifts.length; i++) {
-      //shift the keys either one or two bits to the left
-      if (shifts[i]) {left = (left << 2) | (left >>> 26); right = (right << 2) | (right >>> 26);}
-      else {left = (left << 1) | (left >>> 27); right = (right << 1) | (right >>> 27);}
-      left &= -0xf; right &= -0xf;
-
-      //now apply PC-2, in such a way that E is easier when encrypting or decrypting
-      //this conversion will look like PC-2 except only the last 6 bits of each byte are used
-      //rather than 48 consecutive bits and the order of lines will be according to 
-      //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7
-      lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf]
-              | pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[(left >>> 16) & 0xf]
-              | pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf]
-              | pc2bytes6[(left >>> 4) & 0xf];
-      righttemp = pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf]
-                | pc2bytes9[(right >>> 20) & 0xf] | pc2bytes10[(right >>> 16) & 0xf]
-                | pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf]
-                | pc2bytes13[(right >>> 4) & 0xf];
-      temp = ((righttemp >>> 16) ^ lefttemp) & 0x0000ffff; 
-      keys[n++] = lefttemp ^ temp; keys[n++] = righttemp ^ (temp << 16);
-    }
-  } //for each iterations
-  //return the keys we've created
-  return keys;
-} //end of des_createKeys
-
-
-
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Copyright 2010 pjacobs@xeekr.com . All rights reserved.
-
-// Modified by Recurity Labs GmbH
-
-// fixed/modified by Herbert Hanewinkel, www.haneWIN.de
-// check www.haneWIN.de for the latest version
-
-// cast5.js is a Javascript implementation of CAST-128, as defined in RFC 2144.
-// CAST-128 is a common OpenPGP cipher.
-
-
-// CAST5 constructor
-
-function cast5_encrypt(block, key) {
-	var cast5 = new openpgp_symenc_cast5();
-	cast5.setKey(util.str2bin(key));
-	return cast5.encrypt(block);
-}
-
-function openpgp_symenc_cast5() {
-	this.BlockSize= 8;
-	this.KeySize = 16;
-
-	this.setKey = function (key) {
-		 this.masking = new Array(16);
-		 this.rotate = new Array(16);
-
-		 this.reset();
-
-		 if (key.length == this.KeySize)
-		 {
-		   this.keySchedule(key);
-		 }
-		 else
-		 {
-		   util.print_error('cast5.js: CAST-128: keys must be 16 bytes');
-		   return false;
-		 }
-		 return true;
-	};
-	
-	this.reset = function() {
-		 for (var i = 0; i < 16; i++)
-		 {
-		  this.masking[i] = 0;
-		  this.rotate[i] = 0;
-		 }
-	};
-
-	this.getBlockSize = function() {
-		 return BlockSize;
-	};
-
-	this.encrypt = function(src) {
-		 var dst = new Array(src.length);
-
-		 for(i = 0; i < src.length; i+=8)
-		 {
-		  var l = src[i]<<24 | src[i+1]<<16 | src[i+2]<<8 | src[i+3];
-		  var r = src[i+4]<<24 | src[i+5]<<16 | src[i+6]<<8 | src[i+7];
-		  var t;
-
-		  t = r; r = l^f1(r, this.masking[0], this.rotate[0]); l = t;
-		  t = r; r = l^f2(r, this.masking[1], this.rotate[1]); l = t;
-		  t = r; r = l^f3(r, this.masking[2], this.rotate[2]); l = t;
-		  t = r; r = l^f1(r, this.masking[3], this.rotate[3]); l = t;
-
-		  t = r; r = l^f2(r, this.masking[4], this.rotate[4]); l = t;
-		  t = r; r = l^f3(r, this.masking[5], this.rotate[5]); l = t;
-		  t = r; r = l^f1(r, this.masking[6], this.rotate[6]); l = t;
-		  t = r; r = l^f2(r, this.masking[7], this.rotate[7]); l = t;
-
-		  t = r; r = l^f3(r, this.masking[8], this.rotate[8]); l = t;
-		  t = r; r = l^f1(r, this.masking[9], this.rotate[9]); l = t;
-		  t = r; r = l^f2(r, this.masking[10], this.rotate[10]); l = t;
-		  t = r; r = l^f3(r, this.masking[11], this.rotate[11]); l = t;
-
-		  t = r; r = l^f1(r, this.masking[12], this.rotate[12]); l = t;
-		  t = r; r = l^f2(r, this.masking[13], this.rotate[13]); l = t;
-		  t = r; r = l^f3(r, this.masking[14], this.rotate[14]); l = t;
-		  t = r; r = l^f1(r, this.masking[15], this.rotate[15]); l = t;
-
-		  dst[i]   = (r >>> 24)&255;
-		  dst[i+1] = (r >>> 16)&255;
-		  dst[i+2] = (r >>> 8)&255;
-		  dst[i+3] = r&255;
-		  dst[i+4] = (l >>> 24)&255;
-		  dst[i+5] = (l >>> 16)&255;
-		  dst[i+6] = (l >>> 8)&255;
-		  dst[i+7] = l&255;
-		 }
-
-		 return dst;
-	};
-	
-	this.decrypt = function(src) {
-		 var dst = new Array(src.length);
-
-		 for(i = 0; i < src.length; i+=8)
-		 {
-		  var l = src[i]<<24 | src[i+1]<<16 | src[i+2]<<8 | src[i+3];
-		  var r = src[i+4]<<24 | src[i+5]<<16 | src[i+6]<<8 | src[i+7];
-		  var t;
-
-		  t = r; r = l^f1(r, this.masking[15], this.rotate[15]); l = t;
-		  t = r; r = l^f3(r, this.masking[14], this.rotate[14]); l = t;
-		  t = r; r = l^f2(r, this.masking[13], this.rotate[13]); l = t;
-		  t = r; r = l^f1(r, this.masking[12], this.rotate[12]); l = t;
-
-		  t = r; r = l^f3(r, this.masking[11], this.rotate[11]); l = t;
-		  t = r; r = l^f2(r, this.masking[10], this.rotate[10]); l = t;
-		  t = r; r = l^f1(r, this.masking[9], this.rotate[9]); l = t;
-		  t = r; r = l^f3(r, this.masking[8], this.rotate[8]); l = t;
-
-		  t = r; r = l^f2(r, this.masking[7], this.rotate[7]); l = t;
-		  t = r; r = l^f1(r, this.masking[6], this.rotate[6]); l = t;
-		  t = r; r = l^f3(r, this.masking[5], this.rotate[5]); l = t;
-		  t = r; r = l^f2(r, this.masking[4], this.rotate[4]); l = t;
-
-		  t = r; r = l^f1(r, this.masking[3], this.rotate[3]); l = t;
-		  t = r; r = l^f3(r, this.masking[2], this.rotate[2]); l = t;
-		  t = r; r = l^f2(r, this.masking[1], this.rotate[1]); l = t;
-		  t = r; r = l^f1(r, this.masking[0], this.rotate[0]); l = t;
-
-		  dst[i]   = (r >>> 24)&255;
-		  dst[i+1] = (r >>> 16)&255;
-		  dst[i+2] = (r >>> 8)&255;
-		  dst[i+3] = r&255;
-		  dst[i+4] = (l >>> 24)&255;
-		  dst[i+5] = (l >> 16)&255;
-		  dst[i+6] = (l >> 8)&255;
-		  dst[i+7] = l&255;
-		 }
-
-		 return dst;
-		};
-		var scheduleA = new Array(4);
-
-		scheduleA[0] = new Array(4);
-		scheduleA[0][0] = new Array(4, 0, 0xd, 0xf, 0xc, 0xe, 0x8);
-		scheduleA[0][1] = new Array(5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa);
-		scheduleA[0][2] = new Array(6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9);
-		scheduleA[0][3] = new Array(7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb);
-
-		scheduleA[1] = new Array(4);
-		scheduleA[1][0] = new Array(0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0);
-		scheduleA[1][1] = new Array(1, 4, 0, 2, 1, 3, 16 + 2);
-		scheduleA[1][2] = new Array(2, 5, 7, 6, 5, 4, 16 + 1);
-		scheduleA[1][3] = new Array(3, 7, 0xa, 9, 0xb, 8, 16 + 3);
-
-		scheduleA[2] = new Array(4);
-		scheduleA[2][0] = new Array(4, 0, 0xd, 0xf, 0xc, 0xe, 8);
-		scheduleA[2][1] = new Array(5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa);
-		scheduleA[2][2] = new Array(6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9);
-		scheduleA[2][3] = new Array(7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb);
-
-
-		scheduleA[3] = new Array(4);
-		scheduleA[3][0] = new Array(0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0);
-		scheduleA[3][1] = new Array(1, 4, 0, 2, 1, 3, 16 + 2);
-		scheduleA[3][2] = new Array(2, 5, 7, 6, 5, 4, 16 + 1);
-		scheduleA[3][3] = new Array(3, 7, 0xa, 9, 0xb, 8, 16 + 3);
-
-		var scheduleB = new Array(4);
-
-		scheduleB[0] = new Array(4);
-		scheduleB[0][0] = new Array(16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2);
-		scheduleB[0][1] = new Array(16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6);
-		scheduleB[0][2] = new Array(16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9);
-		scheduleB[0][3] = new Array(16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc);
-
-		scheduleB[1] = new Array(4);
-		scheduleB[1][0] = new Array(3, 2, 0xc, 0xd, 8);
-		scheduleB[1][1] = new Array(1, 0, 0xe, 0xf, 0xd);
-		scheduleB[1][2] = new Array(7, 6, 8, 9, 3);
-		scheduleB[1][3] = new Array(5, 4, 0xa, 0xb, 7);
-
-
-		scheduleB[2] = new Array(4);
-		scheduleB[2][0] = new Array(16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9);
-		scheduleB[2][1] = new Array(16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc);
-		scheduleB[2][2] = new Array(16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2);
-		scheduleB[2][3] = new Array(16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6);
-
-
-		scheduleB[3] = new Array(4);
-		scheduleB[3][0] = new Array(8, 9, 7, 6, 3);
-		scheduleB[3][1] = new Array(0xa, 0xb, 5, 4, 7);
-		scheduleB[3][2] = new Array(0xc, 0xd, 3, 2, 8);
-		scheduleB[3][3] = new Array(0xe, 0xf, 1, 0, 0xd);
-
-		// changed 'in' to 'inn' (in javascript 'in' is a reserved word)
-		this.keySchedule = function(inn)
-		{
-		 var t = new Array(8);
-		 var k = new Array(32);
-
-		 for (var i = 0; i < 4; i++)
-		 {
-		  var j = i * 4;
-		  t[i] = inn[j]<<24 | inn[j+1]<<16 | inn[j+2]<<8 | inn[j+3];
-		 }
-
-		 var x = [6, 7, 4, 5];
-		 var ki = 0;
-
-		 for (var half = 0; half < 2; half++)
-		 {
-		  for (var round = 0; round < 4; round++)
-		  {
-		   for (var j = 0; j < 4; j++)
-		   {
-		    var a = scheduleA[round][j];
-		    var w = t[a[1]];
-
-		    w ^= sBox[4][(t[a[2]>>>2]>>>(24-8*(a[2]&3)))&0xff];
-		    w ^= sBox[5][(t[a[3]>>>2]>>>(24-8*(a[3]&3)))&0xff];
-		    w ^= sBox[6][(t[a[4]>>>2]>>>(24-8*(a[4]&3)))&0xff];
-		    w ^= sBox[7][(t[a[5]>>>2]>>>(24-8*(a[5]&3)))&0xff];
-		    w ^= sBox[x[j]][(t[a[6]>>>2]>>>(24-8*(a[6]&3)))&0xff];
-		    t[a[0]] = w;
-		   }
-
-		   for (var j = 0; j < 4; j++)
-		   {
-		    var b = scheduleB[round][j];
-		    var w = sBox[4][(t[b[0]>>>2]>>>(24-8*(b[0]&3)))&0xff];
-
-		    w ^= sBox[5][(t[b[1]>>>2]>>>(24-8*(b[1]&3)))&0xff];
-		    w ^= sBox[6][(t[b[2]>>>2]>>>(24-8*(b[2]&3)))&0xff];
-		    w ^= sBox[7][(t[b[3]>>>2]>>>(24-8*(b[3]&3)))&0xff];
-		    w ^= sBox[4+j][(t[b[4]>>>2]>>>(24-8*(b[4]&3)))&0xff];
-		    k[ki] = w;
-		    ki++;
-		   }
-		  }
-		 }
-
-		 for (var i = 0; i < 16; i++)
-		 {
-		  this.masking[i] = k[i];
-		  this.rotate[i]  = k[16+i] & 0x1f;
-		 }
-		};
-
-		// These are the three 'f' functions. See RFC 2144, section 2.2.
-
-		function f1(d, m, r)
-		{
-		 var t = m + d;
-		 var I = (t << r) | (t >>> (32 - r));
-		 return ((sBox[0][I>>>24] ^ sBox[1][(I>>>16)&255]) - sBox[2][(I>>>8)&255]) + sBox[3][I&255];
-		}
-
-		function f2(d, m, r)
-		{
-		 var t = m ^ d;
-		 var I = (t << r) | (t >>> (32 - r));
-		 return ((sBox[0][I>>>24] - sBox[1][(I>>>16)&255]) + sBox[2][(I>>>8)&255]) ^ sBox[3][I&255];
-		}
-
-		function f3(d, m, r)
-		{
-		 var t = m - d;
-		 var I = (t << r) | (t >>> (32 - r));
-		 return ((sBox[0][I>>>24] + sBox[1][(I>>>16)&255]) ^ sBox[2][(I>>>8)&255]) - sBox[3][I&255];
-		}
-
-		var sBox = new Array(8);
-		sBox[0] = new Array(
-		  0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
-		  0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
-		  0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
-		  0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
-		  0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
-		  0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
-		  0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
-		  0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
-		  0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
-		  0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
-		  0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
-		  0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
-		  0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
-		  0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
-		  0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
-		  0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
-		  0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
-		  0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
-		  0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
-		  0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
-		  0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
-		  0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
-		  0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
-		  0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
-		  0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
-		  0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
-		  0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
-		  0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
-		  0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
-		  0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
-		  0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
-		  0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf);
-
-		sBox[1] = new Array(
-		  0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
-		  0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
-		  0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
-		  0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
-		  0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
-		  0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
-		  0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
-		  0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
-		  0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
-		  0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
-		  0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
-		  0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
-		  0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
-		  0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
-		  0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
-		  0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
-		  0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
-		  0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
-		  0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
-		  0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
-		  0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
-		  0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
-		  0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
-		  0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
-		  0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
-		  0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
-		  0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
-		  0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
-		  0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
-		  0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
-		  0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
-		  0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1);
-
-		sBox[2] = new Array(
-		  0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
-		  0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
-		  0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
-		  0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
-		  0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
-		  0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
-		  0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
-		  0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
-		  0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
-		  0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
-		  0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
-		  0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
-		  0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
-		  0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
-		  0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
-		  0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
-		  0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
-		  0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
-		  0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
-		  0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
-		  0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
-		  0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
-		  0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
-		  0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
-		  0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
-		  0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
-		  0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
-		  0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
-		  0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
-		  0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
-		  0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
-		  0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783);
-
-		sBox[3] = new Array(
-		  0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
-		  0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
-		  0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
-		  0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
-		  0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
-		  0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
-		  0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
-		  0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
-		  0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
-		  0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
-		  0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
-		  0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
-		  0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
-		  0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
-		  0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
-		  0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
-		  0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
-		  0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
-		  0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
-		  0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
-		  0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
-		  0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
-		  0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
-		  0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
-		  0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
-		  0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
-		  0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
-		  0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
-		  0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
-		  0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
-		  0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
-		  0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2);
-
-		sBox[4] = new Array(
-		  0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
-		  0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
-		  0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
-		  0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
-		  0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
-		  0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
-		  0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
-		  0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
-		  0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
-		  0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
-		  0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
-		  0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
-		  0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
-		  0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
-		  0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
-		  0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
-		  0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
-		  0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
-		  0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
-		  0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
-		  0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
-		  0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
-		  0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
-		  0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
-		  0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
-		  0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
-		  0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
-		  0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
-		  0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
-		  0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
-		  0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
-		  0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4);
-
-		sBox[5] = new Array(
-		  0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
-		  0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
-		  0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
-		  0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
-		  0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
-		  0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
-		  0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
-		  0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
-		  0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
-		  0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
-		  0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
-		  0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
-		  0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
-		  0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
-		  0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
-		  0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
-		  0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
-		  0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
-		  0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
-		  0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
-		  0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
-		  0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
-		  0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
-		  0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
-		  0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
-		  0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
-		  0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
-		  0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
-		  0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
-		  0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
-		  0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
-		  0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f);
-
-		sBox[6] = new Array(
-		  0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
-		  0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
-		  0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
-		  0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
-		  0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
-		  0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
-		  0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
-		  0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
-		  0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
-		  0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
-		  0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
-		  0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
-		  0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
-		  0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
-		  0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
-		  0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
-		  0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
-		  0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
-		  0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
-		  0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
-		  0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
-		  0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
-		  0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
-		  0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
-		  0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
-		  0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
-		  0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
-		  0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
-		  0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
-		  0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
-		  0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
-		  0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3);
-
-		sBox[7] = new Array(
-		  0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
-		  0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
-		  0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
-		  0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
-		  0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
-		  0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
-		  0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
-		  0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
-		  0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
-		  0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
-		  0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
-		  0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
-		  0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
-		  0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
-		  0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
-		  0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
-		  0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
-		  0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
-		  0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
-		  0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
-		  0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
-		  0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
-		  0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
-		  0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
-		  0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
-		  0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
-		  0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
-		  0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
-		  0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
-		  0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
-		  0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
-		  0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e);
-
-};
-
-
-/* Rijndael (AES) Encryption
- * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de
- * version 1.1, check www.haneWIN.de for the latest version
-
- * This software is provided as-is, without express or implied warranty.  
- * Permission to use, copy, modify, distribute or sell this software, with or
- * without fee, for any purpose and by any individual or organization, is hereby
- * granted, provided that the above copyright notice and this paragraph appear 
- * in all copies. Distribution as a part of an application or binary must
- * include the above copyright notice in the documentation and/or other
- * materials provided with the application or distribution.
- */
-
-// The round constants used in subkey expansion
-var Rcon = [ 
-0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 
-0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 
-0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 ];
-
-// Precomputed lookup table for the SBox
-var S = [
- 99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254, 215, 171, 
-118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212, 162, 175, 156, 164, 
-114, 192, 183, 253, 147,  38,  54,  63, 247, 204,  52, 165, 229, 241, 113, 
-216,  49,  21,   4, 199,  35, 195,  24, 150,   5, 154,   7,  18, 128, 226, 
-235,  39, 178, 117,   9, 131,  44,  26,  27, 110,  90, 160,  82,  59, 214, 
-179,  41, 227,  47, 132,  83, 209,   0, 237,  32, 252, 177,  91, 106, 203, 
-190,  57,  74,  76,  88, 207, 208, 239, 170, 251,  67,  77,  51, 133,  69, 
-249,   2, 127,  80,  60, 159, 168,  81, 163,  64, 143, 146, 157,  56, 245, 
-188, 182, 218,  33,  16, 255, 243, 210, 205,  12,  19, 236,  95, 151,  68,  
-23,  196, 167, 126,  61, 100,  93,  25, 115,  96, 129,  79, 220,  34,  42, 
-144, 136,  70, 238, 184,  20, 222,  94,  11, 219, 224,  50,  58,  10,  73,
-  6,  36,  92, 194, 211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 
-141, 213,  78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,  
- 46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138, 112,  62, 
-181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134, 193,  29, 158, 225,
-248, 152,  17, 105, 217, 142, 148, 155,  30, 135, 233, 206,  85,  40, 223,
-140, 161, 137,  13, 191, 230,  66, 104,  65, 153,  45,  15, 176,  84, 187,  
- 22 ];
-
-var T1 = [
-0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6,
-0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591,
-0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56,
-0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec,
-0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
-0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb,
-0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45,
-0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b,
-0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c,
-0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
-0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9,
-0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a,
-0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d,
-0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f,
-0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
-0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea,
-0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34,
-0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b,
-0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d,
-0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
-0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1,
-0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6,
-0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972,
-0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85,
-0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
-0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511,
-0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe,
-0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b,
-0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05,
-0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
-0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142,
-0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf,
-0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3,
-0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e,
-0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
-0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6,
-0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3,
-0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b,
-0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428,
-0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
-0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14,
-0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8,
-0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4,
-0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2,
-0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
-0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949,
-0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf,
-0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810,
-0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c,
-0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
-0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e,
-0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f,
-0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc,
-0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c,
-0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
-0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27,
-0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122,
-0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433,
-0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9,
-0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
-0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a,
-0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0,
-0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e,
-0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c ];
-
-var T2 = [
-0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d,
-0xf2f2ff0d, 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154,
-0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d,
-0xfefee719, 0xd7d7b562, 0xabab4de6, 0x7676ec9a,
-0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87,
-0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b,
-0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea,
-0x9c9c23bf, 0xa4a453f7, 0x7272e496, 0xc0c09b5b,
-0xb7b775c2, 0xfdfde11c, 0x93933dae, 0x26264c6a,
-0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f,
-0x3434685c, 0xa5a551f4, 0xe5e5d134, 0xf1f1f908,
-0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f,
-0x0404080c, 0xc7c79552, 0x23234665, 0xc3c39d5e,
-0x18183028, 0x969637a1, 0x05050a0f, 0x9a9a2fb5,
-0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d,
-0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f,
-0x0909121b, 0x83831d9e, 0x2c2c5874, 0x1a1a342e,
-0x1b1b362d, 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb,
-0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce,
-0x2929527b, 0xe3e3dd3e, 0x2f2f5e71, 0x84841397,
-0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c,
-0x20204060, 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed,
-0x6a6ad4be, 0xcbcb8d46, 0xbebe67d9, 0x3939724b,
-0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a,
-0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16,
-0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194,
-0x45458acf, 0xf9f9e910, 0x02020406, 0x7f7ffe81,
-0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3,
-0x5151a2f3, 0xa3a35dfe, 0x404080c0, 0x8f8f058a,
-0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104,
-0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263,
-0x10102030, 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d,
-0xcdcd814c, 0x0c0c1814, 0x13132635, 0xececc32f,
-0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39,
-0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47,
-0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695,
-0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f,
-0x22224466, 0x2a2a547e, 0x90903bab, 0x88880b83,
-0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c,
-0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76,
-0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e,
-0x494992db, 0x06060c0a, 0x2424486c, 0x5c5cb8e4,
-0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6,
-0x919139a8, 0x959531a4, 0xe4e4d337, 0x7979f28b,
-0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7,
-0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0,
-0x6c6cd8b4, 0x5656acfa, 0xf4f4f307, 0xeaeacf25,
-0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x08081018,
-0xbaba6fd5, 0x7878f088, 0x25254a6f, 0x2e2e5c72,
-0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751,
-0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21,
-0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85,
-0x7070e090, 0x3e3e7c42, 0xb5b571c4, 0x6666ccaa,
-0x484890d8, 0x03030605, 0xf6f6f701, 0x0e0e1c12,
-0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0,
-0x86861791, 0xc1c19958, 0x1d1d3a27, 0x9e9e27b9,
-0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233,
-0x6969d2bb, 0xd9d9a970, 0x8e8e0789, 0x949433a7,
-0x9b9b2db6, 0x1e1e3c22, 0x87871592, 0xe9e9c920,
-0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a,
-0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17,
-0xbfbf65da, 0xe6e6d731, 0x424284c6, 0x6868d0b8,
-0x414182c3, 0x999929b0, 0x2d2d5a77, 0x0f0f1e11,
-0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a ];
-
-var T3 = [
-0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b,
-0xf2ff0df2, 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5,
-0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b,
-0xfee719fe, 0xd7b562d7, 0xab4de6ab, 0x76ec9a76,
-0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d,
-0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0,
-0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf,
-0x9c23bf9c, 0xa453f7a4, 0x72e49672, 0xc09b5bc0,
-0xb775c2b7, 0xfde11cfd, 0x933dae93, 0x264c6a26,
-0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc,
-0x34685c34, 0xa551f4a5, 0xe5d134e5, 0xf1f908f1,
-0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15,
-0x04080c04, 0xc79552c7, 0x23466523, 0xc39d5ec3,
-0x18302818, 0x9637a196, 0x050a0f05, 0x9a2fb59a,
-0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2,
-0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75,
-0x09121b09, 0x831d9e83, 0x2c58742c, 0x1a342e1a,
-0x1b362d1b, 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0,
-0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3,
-0x29527b29, 0xe3dd3ee3, 0x2f5e712f, 0x84139784,
-0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced,
-0x20406020, 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b,
-0x6ad4be6a, 0xcb8d46cb, 0xbe67d9be, 0x39724b39,
-0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf,
-0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb,
-0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485,
-0x458acf45, 0xf9e910f9, 0x02040602, 0x7ffe817f,
-0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8,
-0x51a2f351, 0xa35dfea3, 0x4080c040, 0x8f058a8f,
-0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5,
-0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321,
-0x10203010, 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2,
-0xcd814ccd, 0x0c18140c, 0x13263513, 0xecc32fec,
-0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917,
-0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d,
-0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573,
-0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc,
-0x22446622, 0x2a547e2a, 0x903bab90, 0x880b8388,
-0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14,
-0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db,
-0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a,
-0x4992db49, 0x060c0a06, 0x24486c24, 0x5cb8e45c,
-0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662,
-0x9139a891, 0x9531a495, 0xe4d337e4, 0x79f28b79,
-0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d,
-0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9,
-0x6cd8b46c, 0x56acfa56, 0xf4f307f4, 0xeacf25ea,
-0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x08101808,
-0xba6fd5ba, 0x78f08878, 0x254a6f25, 0x2e5c722e,
-0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6,
-0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f,
-0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a,
-0x70e09070, 0x3e7c423e, 0xb571c4b5, 0x66ccaa66,
-0x4890d848, 0x03060503, 0xf6f701f6, 0x0e1c120e,
-0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9,
-0x86179186, 0xc19958c1, 0x1d3a271d, 0x9e27b99e,
-0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311,
-0x69d2bb69, 0xd9a970d9, 0x8e07898e, 0x9433a794,
-0x9b2db69b, 0x1e3c221e, 0x87159287, 0xe9c920e9,
-0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf,
-0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d,
-0xbf65dabf, 0xe6d731e6, 0x4284c642, 0x68d0b868,
-0x4182c341, 0x9929b099, 0x2d5a772d, 0x0f1e110f,
-0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16 ];
-
-var T4 = [
-0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b,
-0xff0df2f2, 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5,
-0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b,
-0xe719fefe, 0xb562d7d7, 0x4de6abab, 0xec9a7676,
-0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d,
-0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0,
-0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf,
-0x23bf9c9c, 0x53f7a4a4, 0xe4967272, 0x9b5bc0c0,
-0x75c2b7b7, 0xe11cfdfd, 0x3dae9393, 0x4c6a2626,
-0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc,
-0x685c3434, 0x51f4a5a5, 0xd134e5e5, 0xf908f1f1,
-0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515,
-0x080c0404, 0x9552c7c7, 0x46652323, 0x9d5ec3c3,
-0x30281818, 0x37a19696, 0x0a0f0505, 0x2fb59a9a,
-0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2,
-0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575,
-0x121b0909, 0x1d9e8383, 0x58742c2c, 0x342e1a1a,
-0x362d1b1b, 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0,
-0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3,
-0x527b2929, 0xdd3ee3e3, 0x5e712f2f, 0x13978484,
-0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded,
-0x40602020, 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b,
-0xd4be6a6a, 0x8d46cbcb, 0x67d9bebe, 0x724b3939,
-0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf,
-0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb,
-0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585,
-0x8acf4545, 0xe910f9f9, 0x04060202, 0xfe817f7f,
-0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8,
-0xa2f35151, 0x5dfea3a3, 0x80c04040, 0x058a8f8f,
-0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5,
-0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121,
-0x20301010, 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2,
-0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec,
-0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717,
-0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d,
-0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373,
-0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc,
-0x44662222, 0x547e2a2a, 0x3bab9090, 0x0b838888,
-0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414,
-0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb,
-0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a,
-0x92db4949, 0x0c0a0606, 0x486c2424, 0xb8e45c5c,
-0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262,
-0x39a89191, 0x31a49595, 0xd337e4e4, 0xf28b7979,
-0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d,
-0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9,
-0xd8b46c6c, 0xacfa5656, 0xf307f4f4, 0xcf25eaea,
-0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808,
-0x6fd5baba, 0xf0887878, 0x4a6f2525, 0x5c722e2e,
-0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6,
-0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f,
-0x96dd4b4b, 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a,
-0xe0907070, 0x7c423e3e, 0x71c4b5b5, 0xccaa6666,
-0x90d84848, 0x06050303, 0xf701f6f6, 0x1c120e0e,
-0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9,
-0x17918686, 0x9958c1c1, 0x3a271d1d, 0x27b99e9e,
-0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111,
-0xd2bb6969, 0xa970d9d9, 0x07898e8e, 0x33a79494,
-0x2db69b9b, 0x3c221e1e, 0x15928787, 0xc920e9e9,
-0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf,
-0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d,
-0x65dabfbf, 0xd731e6e6, 0x84c64242, 0xd0b86868,
-0x82c34141, 0x29b09999, 0x5a772d2d, 0x1e110f0f,
-0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616 ];
-
-function B0(x) { return (x&255); }
-function B1(x) { return ((x>>8)&255); }
-function B2(x) { return ((x>>16)&255); }
-function B3(x) { return ((x>>24)&255); }
-
-function F1(x0, x1, x2, x3)
-{
-  return B1(T1[x0&255]) | (B1(T1[(x1>>8)&255])<<8)
-      | (B1(T1[(x2>>16)&255])<<16) | (B1(T1[x3>>>24])<<24);
-}
-
-function packBytes(octets)
-{
-  var i, j;
-  var len=octets.length;
-  var b=new Array(len/4);
-
-  if (!octets || len % 4) return;
-
-  for (i=0, j=0; j<len; j+= 4)
-     b[i++] = octets[j] | (octets[j+1]<<8) | (octets[j+2]<<16) | (octets[j+3]<<24);
-
-  return b;  
-}
-
-function unpackBytes(packed)
-{
-  var j;
-  var i=0, l = packed.length;
-  var r = new Array(l*4);
-
-  for (j=0; j<l; j++)
-  {
-    r[i++] = B0(packed[j]);
-    r[i++] = B1(packed[j]);
-    r[i++] = B2(packed[j]);
-    r[i++] = B3(packed[j]);
-  }
-  return r;
-}
-
-// ------------------------------------------------
-
-var maxkc=8;
-var maxrk=14;
-
-function keyExpansion(key)
-{
-  var kc, i, j, r, t;
-  var rounds;
-  var keySched=new Array(maxrk+1);
-  var keylen=key.length;
-  var k=new Array(maxkc);
-  var tk=new Array(maxkc);
-  var rconpointer=0;
-
-  if(keylen==16)
-  {
-   rounds=10;
-   kc=4;
-  }
-  else if(keylen==24)
-  {
-   rounds=12;
-   kc=6;
-  }
-  else if(keylen==32)
-  {
-   rounds=14;
-   kc=8;
-  }
-  else
-  {
-	util.print_error('aes.js: Invalid key-length for AES key:'+keylen);
-   return;
-  }
-
-  for(i=0; i<maxrk+1; i++) keySched[i]=new Array(4);
-
-  for(i=0,j=0; j<keylen; j++,i+=4)
-    k[j] = key.charCodeAt(i) | (key.charCodeAt(i+1)<<8)
-                     | (key.charCodeAt(i+2)<<16) | (key.charCodeAt(i+3)<<24);
-
-  for(j=kc-1; j>=0; j--) tk[j] = k[j];
-
-  r=0;
-  t=0;
-  for(j=0; (j<kc)&&(r<rounds+1); )
-  {
-    for(; (j<kc)&&(t<4); j++,t++)
-    {
-      keySched[r][t]=tk[j];
-    }
-    if(t==4)
-    {
-      r++;
-      t=0;
-    }
-  }
-
-  while(r<rounds+1)
-  {
-    var temp = tk[kc-1];
-
-    tk[0] ^= S[B1(temp)] | (S[B2(temp)]<<8) | (S[B3(temp)]<<16) | (S[B0(temp)]<<24);
-    tk[0] ^= Rcon[rconpointer++];
-
-    if(kc != 8)
-    {
-      for(j=1; j<kc; j++) tk[j] ^= tk[j-1];
-    }
-    else
-    {
-      for(j=1; j<kc/2; j++) tk[j] ^= tk[j-1];
- 
-      temp = tk[kc/2-1];
-      tk[kc/2] ^= S[B0(temp)] | (S[B1(temp)]<<8) | (S[B2(temp)]<<16) | (S[B3(temp)]<<24);
-
-      for(j=kc/2+1; j<kc; j++) tk[j] ^= tk[j-1];
-    }
-
-    for(j=0; (j<kc)&&(r<rounds+1); )
-    {
-      for(; (j<kc)&&(t<4); j++,t++)
-      {
-        keySched[r][t]=tk[j];
-      }
-      if(t==4)
-      {
-        r++;
-        t=0;
-      }
-    }
-  }
-  this.rounds = rounds;
-  this.rk = keySched;
-  return this;
-}
-
-function AESencrypt(block, ctx)
-{
-  var r;
-  var t0,t1,t2,t3;
-
-  var b = packBytes(block);
-  var rounds = ctx.rounds;
-  var b0 = b[0];
-  var b1 = b[1];
-  var b2 = b[2];
-  var b3 = b[3];
-
-  for(r=0; r<rounds-1; r++)
-  {
-    t0 = b0 ^ ctx.rk[r][0];
-    t1 = b1 ^ ctx.rk[r][1];
-    t2 = b2 ^ ctx.rk[r][2];
-    t3 = b3 ^ ctx.rk[r][3];
-
-    b0 = T1[t0&255] ^ T2[(t1>>8)&255] ^ T3[(t2>>16)&255] ^ T4[t3>>>24];
-    b1 = T1[t1&255] ^ T2[(t2>>8)&255] ^ T3[(t3>>16)&255] ^ T4[t0>>>24];
-    b2 = T1[t2&255] ^ T2[(t3>>8)&255] ^ T3[(t0>>16)&255] ^ T4[t1>>>24];
-    b3 = T1[t3&255] ^ T2[(t0>>8)&255] ^ T3[(t1>>16)&255] ^ T4[t2>>>24];
-  }
-
-  // last round is special
-  r = rounds-1;
-
-  t0 = b0 ^ ctx.rk[r][0];
-  t1 = b1 ^ ctx.rk[r][1];
-  t2 = b2 ^ ctx.rk[r][2];
-  t3 = b3 ^ ctx.rk[r][3];
-
-  b[0] = F1(t0, t1, t2, t3) ^ ctx.rk[rounds][0];
-  b[1] = F1(t1, t2, t3, t0) ^ ctx.rk[rounds][1];
-  b[2] = F1(t2, t3, t0, t1) ^ ctx.rk[rounds][2];
-  b[3] = F1(t3, t0, t1, t2) ^ ctx.rk[rounds][3];
-
-  return unpackBytes(b);
-}
-/* Modified by Recurity Labs GmbH 
- * 
- * Cipher.js
- * A block-cipher algorithm implementation on JavaScript
- * See Cipher.readme.txt for further information.
- *
- * Copyright(c) 2009 Atsushi Oka [ http://oka.nu/ ]
- * This script file is distributed under the LGPL
- *
- * ACKNOWLEDGMENT
- *
- *     The main subroutines are written by Michiel van Everdingen.
- * 
- *     Michiel van Everdingen
- *     http://home.versatel.nl/MAvanEverdingen/index.html
- * 
- *     All rights for these routines are reserved to Michiel van Everdingen.
- *
- */
-
-// added by Recurity Labs
-function TFencrypt(block, key) {
-	var block_copy = [].concat(block);
-	var tf = createTwofish();
-	tf.open(util.str2bin(key),0);
-	var result = tf.encrypt(block_copy, 0);
-	tf.close();
-	return result;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//Math
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-var MAXINT = 0xFFFFFFFF;
-
-function rotb(b,n){ return ( b<<n | b>>>( 8-n) ) & 0xFF; }
-function rotw(w,n){ return ( w<<n | w>>>(32-n) ) & MAXINT; }
-function getW(a,i){ return a[i]|a[i+1]<<8|a[i+2]<<16|a[i+3]<<24; }
-function setW(a,i,w){ a.splice(i,4,w&0xFF,(w>>>8)&0xFF,(w>>>16)&0xFF,(w>>>24)&0xFF); }
-function setWInv(a,i,w){ a.splice(i,4,(w>>>24)&0xFF,(w>>>16)&0xFF,(w>>>8)&0xFF,w&0xFF); }
-function getB(x,n){ return (x>>>(n*8))&0xFF; }
-
-function getNrBits(i){ var n=0; while (i>0){ n++; i>>>=1; } return n; }
-function getMask(n){ return (1<<n)-1; }
-
-//added 2008/11/13 XXX MUST USE ONE-WAY HASH FUNCTION FOR SECURITY REASON
-function randByte() {
- return Math.floor( Math.random() * 256 );
-}
-// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Twofish
-// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-function createTwofish() {
-	//
-	var keyBytes = null;
-	var dataBytes = null;
-	var dataOffset = -1;
-	// var dataLength = -1;
-	var algorithmName = null;
-	// var idx2 = -1;
-	//
-
-	algorithmName = "twofish";
-
-	var tfsKey = [];
-	var tfsM = [ [], [], [], [] ];
-
-	function tfsInit(key) {
-		keyBytes = key;
-		var i, a, b, c, d, meKey = [], moKey = [], inKey = [];
-		var kLen;
-		var sKey = [];
-		var f01, f5b, fef;
-
-		var q0 = [ [ 8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4 ],
-				[ 2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5 ] ];
-		var q1 = [ [ 14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13 ],
-				[ 1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8 ] ];
-		var q2 = [ [ 11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1 ],
-				[ 4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15 ] ];
-		var q3 = [ [ 13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10 ],
-				[ 11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10 ] ];
-		var ror4 = [ 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 ];
-		var ashx = [ 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7 ];
-		var q = [ [], [] ];
-		var m = [ [], [], [], [] ];
-
-		function ffm5b(x) {
-			return x ^ (x >> 2) ^ [ 0, 90, 180, 238 ][x & 3];
-		}
-		function ffmEf(x) {
-			return x ^ (x >> 1) ^ (x >> 2) ^ [ 0, 238, 180, 90 ][x & 3];
-		}
-
-		function mdsRem(p, q) {
-			var i, t, u;
-			for (i = 0; i < 8; i++) {
-				t = q >>> 24;
-				q = ((q << 8) & MAXINT) | p >>> 24;
-				p = (p << 8) & MAXINT;
-				u = t << 1;
-				if (t & 128) {
-					u ^= 333;
-				}
-				q ^= t ^ (u << 16);
-				u ^= t >>> 1;
-				if (t & 1) {
-					u ^= 166;
-				}
-				q ^= u << 24 | u << 8;
-			}
-			return q;
-		}
-
-		function qp(n, x) {
-			var a, b, c, d;
-			a = x >> 4;
-			b = x & 15;
-			c = q0[n][a ^ b];
-			d = q1[n][ror4[b] ^ ashx[a]];
-			return q3[n][ror4[d] ^ ashx[c]] << 4 | q2[n][c ^ d];
-		}
-
-		function hFun(x, key) {
-			var a = getB(x, 0), b = getB(x, 1), c = getB(x, 2), d = getB(x, 3);
-			switch (kLen) {
-			case 4:
-				a = q[1][a] ^ getB(key[3], 0);
-				b = q[0][b] ^ getB(key[3], 1);
-				c = q[0][c] ^ getB(key[3], 2);
-				d = q[1][d] ^ getB(key[3], 3);
-			case 3:
-				a = q[1][a] ^ getB(key[2], 0);
-				b = q[1][b] ^ getB(key[2], 1);
-				c = q[0][c] ^ getB(key[2], 2);
-				d = q[0][d] ^ getB(key[2], 3);
-			case 2:
-				a = q[0][q[0][a] ^ getB(key[1], 0)] ^ getB(key[0], 0);
-				b = q[0][q[1][b] ^ getB(key[1], 1)] ^ getB(key[0], 1);
-				c = q[1][q[0][c] ^ getB(key[1], 2)] ^ getB(key[0], 2);
-				d = q[1][q[1][d] ^ getB(key[1], 3)] ^ getB(key[0], 3);
-			}
-			return m[0][a] ^ m[1][b] ^ m[2][c] ^ m[3][d];
-		}
-
-		keyBytes = keyBytes.slice(0, 32);
-		i = keyBytes.length;
-		while (i != 16 && i != 24 && i != 32)
-			keyBytes[i++] = 0;
-
-		for (i = 0; i < keyBytes.length; i += 4) {
-			inKey[i >> 2] = getW(keyBytes, i);
-		}
-		for (i = 0; i < 256; i++) {
-			q[0][i] = qp(0, i);
-			q[1][i] = qp(1, i);
-		}
-		for (i = 0; i < 256; i++) {
-			f01 = q[1][i];
-			f5b = ffm5b(f01);
-			fef = ffmEf(f01);
-			m[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24);
-			m[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24);
-			f01 = q[0][i];
-			f5b = ffm5b(f01);
-			fef = ffmEf(f01);
-			m[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24);
-			m[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24);
-		}
-
-		kLen = inKey.length / 2;
-		for (i = 0; i < kLen; i++) {
-			a = inKey[i + i];
-			meKey[i] = a;
-			b = inKey[i + i + 1];
-			moKey[i] = b;
-			sKey[kLen - i - 1] = mdsRem(a, b);
-		}
-		for (i = 0; i < 40; i += 2) {
-			a = 0x1010101 * i;
-			b = a + 0x1010101;
-			a = hFun(a, meKey);
-			b = rotw(hFun(b, moKey), 8);
-			tfsKey[i] = (a + b) & MAXINT;
-			tfsKey[i + 1] = rotw(a + 2 * b, 9);
-		}
-		for (i = 0; i < 256; i++) {
-			a = b = c = d = i;
-			switch (kLen) {
-			case 4:
-				a = q[1][a] ^ getB(sKey[3], 0);
-				b = q[0][b] ^ getB(sKey[3], 1);
-				c = q[0][c] ^ getB(sKey[3], 2);
-				d = q[1][d] ^ getB(sKey[3], 3);
-			case 3:
-				a = q[1][a] ^ getB(sKey[2], 0);
-				b = q[1][b] ^ getB(sKey[2], 1);
-				c = q[0][c] ^ getB(sKey[2], 2);
-				d = q[0][d] ^ getB(sKey[2], 3);
-			case 2:
-				tfsM[0][i] = m[0][q[0][q[0][a] ^ getB(sKey[1], 0)]
-						^ getB(sKey[0], 0)];
-				tfsM[1][i] = m[1][q[0][q[1][b] ^ getB(sKey[1], 1)]
-						^ getB(sKey[0], 1)];
-				tfsM[2][i] = m[2][q[1][q[0][c] ^ getB(sKey[1], 2)]
-						^ getB(sKey[0], 2)];
-				tfsM[3][i] = m[3][q[1][q[1][d] ^ getB(sKey[1], 3)]
-						^ getB(sKey[0], 3)];
-			}
-		}
-	}
-
-	function tfsG0(x) {
-		return tfsM[0][getB(x, 0)] ^ tfsM[1][getB(x, 1)] ^ tfsM[2][getB(x, 2)]
-				^ tfsM[3][getB(x, 3)];
-	}
-	function tfsG1(x) {
-		return tfsM[0][getB(x, 3)] ^ tfsM[1][getB(x, 0)] ^ tfsM[2][getB(x, 1)]
-				^ tfsM[3][getB(x, 2)];
-	}
-
-	function tfsFrnd(r, blk) {
-		var a = tfsG0(blk[0]);
-		var b = tfsG1(blk[1]);
-		blk[2] = rotw(blk[2] ^ (a + b + tfsKey[4 * r + 8]) & MAXINT, 31);
-		blk[3] = rotw(blk[3], 1) ^ (a + 2 * b + tfsKey[4 * r + 9]) & MAXINT;
-		a = tfsG0(blk[2]);
-		b = tfsG1(blk[3]);
-		blk[0] = rotw(blk[0] ^ (a + b + tfsKey[4 * r + 10]) & MAXINT, 31);
-		blk[1] = rotw(blk[1], 1) ^ (a + 2 * b + tfsKey[4 * r + 11]) & MAXINT;
-	}
-
-	function tfsIrnd(i, blk) {
-		var a = tfsG0(blk[0]);
-		var b = tfsG1(blk[1]);
-		blk[2] = rotw(blk[2], 1) ^ (a + b + tfsKey[4 * i + 10]) & MAXINT;
-		blk[3] = rotw(blk[3] ^ (a + 2 * b + tfsKey[4 * i + 11]) & MAXINT, 31);
-		a = tfsG0(blk[2]);
-		b = tfsG1(blk[3]);
-		blk[0] = rotw(blk[0], 1) ^ (a + b + tfsKey[4 * i + 8]) & MAXINT;
-		blk[1] = rotw(blk[1] ^ (a + 2 * b + tfsKey[4 * i + 9]) & MAXINT, 31);
-	}
-
-	function tfsClose() {
-		tfsKey = [];
-		tfsM = [ [], [], [], [] ];
-	}
-
-	function tfsEncrypt(data, offset) {
-		dataBytes = data;
-		dataOffset = offset;
-		var blk = [ getW(dataBytes, dataOffset) ^ tfsKey[0],
-				getW(dataBytes, dataOffset + 4) ^ tfsKey[1],
-				getW(dataBytes, dataOffset + 8) ^ tfsKey[2],
-				getW(dataBytes, dataOffset + 12) ^ tfsKey[3] ];
-		for ( var j = 0; j < 8; j++) {
-			tfsFrnd(j, blk);
-		}
-		setW(dataBytes, dataOffset, blk[2] ^ tfsKey[4]);
-		setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[5]);
-		setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[6]);
-		setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[7]);
-		dataOffset += 16;
-		return dataBytes;
-	}
-
-	function tfsDecrypt(data, offset) {
-		dataBytes = data;
-		dataOffset = offset;
-		var blk = [ getW(dataBytes, dataOffset) ^ tfsKey[4],
-				getW(dataBytes, dataOffset + 4) ^ tfsKey[5],
-				getW(dataBytes, dataOffset + 8) ^ tfsKey[6],
-				getW(dataBytes, dataOffset + 12) ^ tfsKey[7] ];
-		for ( var j = 7; j >= 0; j--) {
-			tfsIrnd(j, blk);
-		}
-		setW(dataBytes, dataOffset, blk[2] ^ tfsKey[0]);
-		setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[1]);
-		setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[2]);
-		setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[3]);
-		dataOffset += 16;
-	}
-	
-	// added by Recurity Labs
-	function tfsFinal() {
-		return dataBytes;
-	}
-
-	return {
-		name : "twofish",
-		blocksize : 128 / 8,
-		open : tfsInit,
-		close : tfsClose,
-		encrypt : tfsEncrypt,
-		decrypt : tfsDecrypt,
-		// added by Recurity Labs
-		finalize: tfsFinal
-	};
-}
-
 // GPG4Browsers - An OpenPGP implementation in javascript
 // Copyright (C) 2011 Recurity Labs GmbH
 // 
@@ -7135,2832 +2473,541 @@ function createTwofish() {
 // You should have received a copy of the GNU Lesser General Public
 // License along with this library; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//
-// RSA implementation
 
-function SecureRandom(){
-    function nextBytes(byteArray){
-        for(var n = 0; n < byteArray.length;n++){
-            byteArray[n] = openpgp_crypto_getSecureRandomOctet();
-        }
-    }
-    this.nextBytes = nextBytes;
-}
-
-function RSA() {
+/**
+ * Implementation of the strange "Marker packet" (Tag 10)
+ * 
+ * RFC4880 5.8: An experimental version of PGP used this packet as the Literal
+ * packet, but no released version of PGP generated Literal packets with this
+ * tag. With PGP 5.x, this packet has been reassigned and is reserved for use as
+ * the Marker packet.
+ * 
+ * Such a packet MUST be ignored when received.
+ */
+function openpgp_packet_marker() {
+	this.tagType = 10;
 	/**
-	 * This function uses jsbn Big Num library to decrypt RSA
-	 * @param m
-	 *            message
-	 * @param d
-	 *            RSA d as BigInteger
-	 * @param p
-	 *            RSA p as BigInteger
-	 * @param q
-	 *            RSA q as BigInteger
-	 * @param u
-	 *            RSA u as BigInteger
-	 * @return {BigInteger} The decrypted value of the message
+	 * parsing function for a literal data packet (tag 10).
+	 * 
+	 * @param input
+	 *            [string] payload of a tag 10 packet
+	 * @param position
+	 *            [integer] position to start reading from the input string
+	 * @param len
+	 *            [integer] length of the packet or the remaining length of
+	 *            input at position
+	 * @return [openpgp_packet_encrypteddata] object representation
 	 */
-	function decrypt(m, d, p, q, u) {
-		var xp = m.mod(p).modPow(d.mod(p.subtract(BigInteger.ONE)), p);
-		var xq = m.mod(q).modPow(d.mod(q.subtract(BigInteger.ONE)), q);
-		util.print_debug("rsa.js decrypt\nxpn:"+util.hexstrdump(xp.toMPI())+"\nxqn:"+util.hexstrdump(xq.toMPI()));
+	function read_packet(input, position, len) {
+		this.packetLength = 3;
+		if (input[position].charCodeAt() == 0x50 && // P
+				input[position + 1].charCodeAt() == 0x47 && // G
+				input[position + 2].charCodeAt() == 0x50) // P
+			return this;
+		// marker packet does not contain "PGP"
+		return null;
+	}
 
-		var t = xq.subtract(xp);
-		if (t[0] == 0) {
-			t = xp.subtract(xq);
-			t = t.multiply(u).mod(q);
-			t = q.subtract(t);
+	/**
+	 * Generates Debug output
+	 * 
+	 * @return String which gives some information about the keymaterial
+	 */
+	function toString() {
+		return "5.8.  Marker Packet (Obsolete Literal Packet) (Tag 10)\n"
+				+ "     packet reads: \"PGP\"\n";
+	}
+
+	this.read_packet = read_packet;
+	this.toString = toString;
+}// GPG4Browsers - An OpenPGP implementation in javascript
+// Copyright (C) 2011 Recurity Labs GmbH
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+/**
+ * Implementation of the Modification Detection Code Packet (Tag 19)
+ * 
+ * RFC4880 5.14: The Modification Detection Code packet contains a SHA-1 hash of
+ * plaintext data, which is used to detect message modification. It is only used
+ * with a Symmetrically Encrypted Integrity Protected Data packet. The
+ * Modification Detection Code packet MUST be the last packet in the plaintext
+ * data that is encrypted in the Symmetrically Encrypted Integrity Protected
+ * Data packet, and MUST appear in no other place.
+ */
+
+function openpgp_packet_modificationdetectioncode() {
+	this.tagType = 19;
+	this.hash = null;
+	/**
+	 * parsing function for a modification detection code packet (tag 19).
+	 * 
+	 * @param input
+	 *            [String] payload of a tag 19 packet
+	 * @param position
+	 *            [Integer] position to start reading from the input string
+	 * @param len
+	 *            [Integer] length of the packet or the remaining length of
+	 *            input at position
+	 * @return [openpgp_packet_encrypteddata] object representation
+	 */
+	function read_packet(input, position, len) {
+		this.packetLength = len;
+
+		if (len != 20) {
+			util
+					.print_error("openpgp.packet.modificationdetectioncode.js\n"
+							+ 'invalid length for a modification detection code packet!'
+							+ len);
+			return null;
+		}
+		// - A 20-octet SHA-1 hash of the preceding plaintext data of the
+		// Symmetrically Encrypted Integrity Protected Data packet,
+		// including prefix data, the tag octet, and length octet of the
+		// Modification Detection Code packet.
+		this.hash = input.substring(position, position + 20);
+		return this;
+	}
+
+	/*
+	 * this packet is created within the encryptedintegrityprotected packet
+	 * function write_packet(data) { }
+	 */
+
+	/**
+	 * generates debug output (pretty print)
+	 * 
+	 * @return String which gives some information about the modification
+	 *         detection code
+	 */
+	function toString() {
+		return '5.14 Modification detection code packet\n' + '    bytes ('
+				+ this.hash.length + '): [' + util.hexstrdump(this.hash) + ']';
+	}
+	this.read_packet = read_packet;
+	this.toString = toString;
+};
+// GPG4Browsers - An OpenPGP implementation in javascript
+// Copyright (C) 2011 Recurity Labs GmbH
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+function _openpgp_packet() {
+	/**
+	 * Encodes a given integer of length to the openpgp length specifier to a
+	 * string
+	 * 
+	 * @param length
+	 *            [Integer] of the length to encode
+	 * @return string with openpgp length representation
+	 */
+	function encode_length(length) {
+		result = "";
+		if (length < 192) {
+			result += String.fromCharCode(length);
+		} else if (length > 191 && length < 8384) {
+			/*
+			 * let a = (total data packet length) - 192 let bc = two octet
+			 * representation of a let d = b + 192
+			 */
+			result += String.fromCharCode(((length - 192) >> 8) + 192);
+			result += String.fromCharCode((length - 192) & 0xFF);
 		} else {
-			t = t.multiply(u).mod(q);
+			result += String.fromCharCode(255);
+			result += String.fromCharCode((length >> 24) & 0xFF);
+			result += String.fromCharCode((length >> 16) & 0xFF);
+			result += String.fromCharCode((length >> 8) & 0xFF);
+			result += String.fromCharCode(length & 0xFF);
 		}
-		return t.multiply(p).add(xp);
-	}
-	
-	/**
-	 * encrypt message
-	 * @param m message as BigInteger
-	 * @param e public MPI part as BigInteger
-	 * @param n public MPI part as BigInteger
-	 * @return BigInteger
-	 */
-	function encrypt(m,e,n) {
-		return m.modPowInt(e, n);
-	}
-	
-	/* Sign and Verify */
-	function sign(m,d,n) {
-		return m.modPow(d, n);
-	}
-		
-	function verify(x,e,n) {
-		return x.modPowInt(e, n);
-	}
-	
-	// "empty" RSA key constructor
-    function keyObject() {
-        this.n = null;
-        this.e = 0;
-        this.ee = null;
-        this.d = null;
-        this.p = null;
-        this.q = null;
-        this.dmp1 = null;
-        this.dmq1 = null;
-        this.u = null;
-    }
-	
-	// Generate a new random private key B bits long, using public expt E
-    function generate(B,E) {
-        var key = new keyObject();
-        var rng = new SecureRandom();
-        var qs = B>>1;
-        key.e = parseInt(E,16);
-        key.ee = new BigInteger(E,16);
-        for(;;) {
-            for(;;) {
-                key.p = new BigInteger(B-qs,1,rng);
-                if(key.p.subtract(BigInteger.ONE).gcd(key.ee).compareTo(BigInteger.ONE) == 0 && key.p.isProbablePrime(10)) break;
-            }
-            for(;;) {
-                key.q = new BigInteger(qs,1,rng);
-                if(key.q.subtract(BigInteger.ONE).gcd(key.ee).compareTo(BigInteger.ONE) == 0 && key.q.isProbablePrime(10)) break;
-            }
-            if(key.p.compareTo(key.q) <= 0) {
-                var t = key.p;
-                key.p = key.q;
-                key.q = t;
-            }
-            var p1 = key.p.subtract(BigInteger.ONE);
-            var q1 = key.q.subtract(BigInteger.ONE);
-            var phi = p1.multiply(q1);
-            if(phi.gcd(key.ee).compareTo(BigInteger.ONE) == 0) {
-                key.n = key.p.multiply(key.q);
-                key.d = key.ee.modInverse(phi);
-                key.dmp1 = key.d.mod(p1);
-                key.dmq1 = key.d.mod(q1);
-                key.u = key.p.modInverse(key.q);
-                break;
-            }
-        }
-        return key;
-    }
-		
-	this.encrypt = encrypt;
-	this.decrypt = decrypt;
-	this.verify = verify;
-	this.sign = sign;
-	this.generate = generate;
-	this.keyObject = keyObject;
-}
-// GPG4Browsers - An OpenPGP implementation in javascript
-// Copyright (C) 2011 Recurity Labs GmbH
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//
-// A Digital signature algorithm implementation
-
-function DSA() {
-	// s1 = ((g**s) mod p) mod q
-	// s1 = ((s**-1)*(sha-1(m)+(s1*x) mod q)
-	function sign(hashalgo, m, g, p, q, x) {
-		// If the output size of the chosen hash is larger than the number of
-		// bits of q, the hash result is truncated to fit by taking the number
-		// of leftmost bits equal to the number of bits of q.  This (possibly
-		// truncated) hash function result is treated as a number and used
-		// directly in the DSA signature algorithm.
-		var hashed_data = util.getLeftNBits(openpgp_crypto_hashData(hashalgo,m),q.bitLength());
-		var hash = new BigInteger(util.hexstrdump(hashed_data), 16);
-		var k = openpgp_crypto_getRandomBigIntegerInRange(BigInteger.ONE.add(BigInteger.ONE), q.subtract(BigInteger.ONE));
-		var s1 = (g.modPow(k,p)).mod(q); 
-		var s2 = (k.modInverse(q).multiply(hash.add(x.multiply(s1)))).mod(q);
-		var result = new Array();
-		result[0] = s1.toMPI();
-		result[1] = s2.toMPI();
 		return result;
 	}
-	function select_hash_algorithm(q) {
-		var usersetting = openpgp.config.config.prefer_hash_algorithm;
-		/*
-		 * 1024-bit key, 160-bit q, SHA-1, SHA-224, SHA-256, SHA-384, or SHA-512 hash
-		 * 2048-bit key, 224-bit q, SHA-224, SHA-256, SHA-384, or SHA-512 hash
-		 * 2048-bit key, 256-bit q, SHA-256, SHA-384, or SHA-512 hash
-		 * 3072-bit key, 256-bit q, SHA-256, SHA-384, or SHA-512 hash
-		 */
-		switch (Math.round(q.bitLength() / 8)) {
-		case 20: // 1024 bit
-			if (usersetting != 2 &&
-				usersetting > 11 &&
-				usersetting != 10 &&
-				usersetting < 8)
-				return 2; // prefer sha1
-			return usersetting;
-		case 28: // 2048 bit
-			if (usersetting > 11 &&
-					usersetting < 8)
-					return 11;
-			return usersetting;
-		case 32: // 4096 bit // prefer sha224
-			if (usersetting > 10 &&
-					usersetting < 8)
-					return 8; // prefer sha256
-			return usersetting;
-		default:
-			util.print_debug("DSA select hash algorithm: returning null for an unknown length of q");
-			return null;
-			
-		}
-	}
-	this.select_hash_algorithm = select_hash_algorithm;
-	
-	function verify(hashalgo, s1,s2,m,p,q,g,y) {
-		var hashed_data = util.getLeftNBits(openpgp_crypto_hashData(hashalgo,m),q.bitLength());
-		var hash = new BigInteger(util.hexstrdump(hashed_data), 16); 
-		if (BigInteger.ZERO.compareTo(s1) > 0 ||
-				s1.compareTo(q) > 0 ||
-				BigInteger.ZERO.compareTo(s2) > 0 ||
-				s2.compareTo(q) > 0) {
-			util.print_error("invalid DSA Signature");
-			return null;
-		}
-		var w = s2.modInverse(q);
-		var u1 = hash.multiply(w).mod(q);
-		var u2 = s1.multiply(w).mod(q);
-		return g.modPow(u1,p).multiply(y.modPow(u2,p)).mod(p).mod(q);
-	}
-	
-	/*
-	 * unused code. This can be used as a start to write a key generator
-	 * function.
-	
-	function generateKey(bitcount) {
-	    var qi = new BigInteger(bitcount, primeCenterie);
-	    var pi = generateP(q, 512);
-	    var gi = generateG(p, q, bitcount);
-	    var xi;
-	    do {
-	        xi = new BigInteger(q.bitCount(), rand);
-	    } while (x.compareTo(BigInteger.ZERO) != 1 && x.compareTo(q) != -1);
-	    var yi = g.modPow(x, p);
-	    return {x: xi, q: qi, p: pi, g: gi, y: yi};
-	}
-
-	function generateP(q, bitlength, randomfn) {
-	    if (bitlength % 64 != 0) {
-	    	return false;
-	    }
-	    var pTemp;
-	    var pTemp2;
-	    do {
-	        pTemp = randomfn(bitcount, true);
-	        pTemp2 = pTemp.subtract(BigInteger.ONE);
-	        pTemp = pTemp.subtract(pTemp2.remainder(q));
-	    } while (!pTemp.isProbablePrime(primeCenterie) || pTemp.bitLength() != l);
-	    return pTemp;
-	}
-	
-	function generateG(p, q, bitlength, randomfn) {
-	    var aux = p.subtract(BigInteger.ONE);
-	    var pow = aux.divide(q);
-	    var gTemp;
-	    do {
-	        gTemp = randomfn(bitlength);
-	    } while (gTemp.compareTo(aux) != -1 && gTemp.compareTo(BigInteger.ONE) != 1);
-	    return gTemp.modPow(pow, p);
-	}
-
-	function generateK(q, bitlength, randomfn) {
-	    var tempK;
-	    do {
-	        tempK = randomfn(bitlength, false);
-	    } while (tempK.compareTo(q) != -1 && tempK.compareTo(BigInteger.ZERO) != 1);
-	    return tempK;
-	}
-
-	function generateR(q,p) {
-	    k = generateK(q);
-	    var r = g.modPow(k, p).mod(q);
-	    return r;
-	}
-
-	function generateS(hashfn,k,r,m,q,x) {
-        var hash = hashfn(m);
-        s = (k.modInverse(q).multiply(hash.add(x.multiply(r)))).mod(q);
-	    return s;
-	} */
-	this.sign = sign;
-	this.verify = verify;
-	// this.generate = generateKey;
-}
-/*
- * Copyright (c) 2003-2005  Tom Wu (tjw@cs.Stanford.EDU) 
- * All Rights Reserved.
- *
- * Modified by Recurity Labs GmbH 
- * 
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
- *
- * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
- * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
- * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * In addition, the following condition applies:
- *
- * All redistributions must retain an intact copy of this copyright notice
- * and disclaimer.
- */
-
-// Basic JavaScript BN library - subset useful for RSA encryption.
-
-// Bits per digit
-var dbits;
-
-// JavaScript engine analysis
-var canary = 0xdeadbeefcafe;
-var j_lm = ((canary&0xffffff)==0xefcafe);
-
-// (public) Constructor
-function BigInteger(a,b,c) {
-  if(a != null)
-    if("number" == typeof a) this.fromNumber(a,b,c);
-    else if(b == null && "string" != typeof a) this.fromString(a,256);
-    else this.fromString(a,b);
-}
-
-// return new, unset BigInteger
-function nbi() { return new BigInteger(null); }
-
-// am: Compute w_j += (x*this_i), propagate carries,
-// c is initial carry, returns final carry.
-// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
-// We need to select the fastest one that works in this environment.
-
-// am1: use a single mult and divide to get the high bits,
-// max digit bits should be 26 because
-// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
-function am1(i,x,w,j,c,n) {
-  while(--n >= 0) {
-    var v = x*this[i++]+w[j]+c;
-    c = Math.floor(v/0x4000000);
-    w[j++] = v&0x3ffffff;
-  }
-  return c;
-}
-// am2 avoids a big mult-and-extract completely.
-// Max digit bits should be <= 30 because we do bitwise ops
-// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
-function am2(i,x,w,j,c,n) {
-  var xl = x&0x7fff, xh = x>>15;
-  while(--n >= 0) {
-    var l = this[i]&0x7fff;
-    var h = this[i++]>>15;
-    var m = xh*l+h*xl;
-    l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
-    c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
-    w[j++] = l&0x3fffffff;
-  }
-  return c;
-}
-// Alternately, set max digit bits to 28 since some
-// browsers slow down when dealing with 32-bit numbers.
-function am3(i,x,w,j,c,n) {
-  var xl = x&0x3fff, xh = x>>14;
-  while(--n >= 0) {
-    var l = this[i]&0x3fff;
-    var h = this[i++]>>14;
-    var m = xh*l+h*xl;
-    l = xl*l+((m&0x3fff)<<14)+w[j]+c;
-    c = (l>>28)+(m>>14)+xh*h;
-    w[j++] = l&0xfffffff;
-  }
-  return c;
-}
-if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
-  BigInteger.prototype.am = am2;
-  dbits = 30;
-}
-else if(j_lm && (navigator.appName != "Netscape")) {
-  BigInteger.prototype.am = am1;
-  dbits = 26;
-}
-else { // Mozilla/Netscape seems to prefer am3
-  BigInteger.prototype.am = am3;
-  dbits = 28;
-}
-
-BigInteger.prototype.DB = dbits;
-BigInteger.prototype.DM = ((1<<dbits)-1);
-BigInteger.prototype.DV = (1<<dbits);
-
-var BI_FP = 52;
-BigInteger.prototype.FV = Math.pow(2,BI_FP);
-BigInteger.prototype.F1 = BI_FP-dbits;
-BigInteger.prototype.F2 = 2*dbits-BI_FP;
-
-// Digit conversions
-var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
-var BI_RC = new Array();
-var rr,vv;
-rr = "0".charCodeAt(0);
-for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
-rr = "a".charCodeAt(0);
-for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
-rr = "A".charCodeAt(0);
-for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
-
-function int2char(n) { return BI_RM.charAt(n); }
-function intAt(s,i) {
-  var c = BI_RC[s.charCodeAt(i)];
-  return (c==null)?-1:c;
-}
-
-// (protected) copy this to r
-function bnpCopyTo(r) {
-  for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
-  r.t = this.t;
-  r.s = this.s;
-}
-
-// (protected) set from integer value x, -DV <= x < DV
-function bnpFromInt(x) {
-  this.t = 1;
-  this.s = (x<0)?-1:0;
-  if(x > 0) this[0] = x;
-  else if(x < -1) this[0] = x+DV;
-  else this.t = 0;
-}
-
-// return bigint initialized to value
-function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
-
-// (protected) set from string and radix
-function bnpFromString(s,b) {
-  var k;
-  if(b == 16) k = 4;
-  else if(b == 8) k = 3;
-  else if(b == 256) k = 8; // byte array
-  else if(b == 2) k = 1;
-  else if(b == 32) k = 5;
-  else if(b == 4) k = 2;
-  else { this.fromRadix(s,b); return; }
-  this.t = 0;
-  this.s = 0;
-  var i = s.length, mi = false, sh = 0;
-  while(--i >= 0) {
-    var x = (k==8)?s[i]&0xff:intAt(s,i);
-    if(x < 0) {
-      if(s.charAt(i) == "-") mi = true;
-      continue;
-    }
-    mi = false;
-    if(sh == 0)
-      this[this.t++] = x;
-    else if(sh+k > this.DB) {
-      this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
-      this[this.t++] = (x>>(this.DB-sh));
-    }
-    else
-      this[this.t-1] |= x<<sh;
-    sh += k;
-    if(sh >= this.DB) sh -= this.DB;
-  }
-  if(k == 8 && (s[0]&0x80) != 0) {
-    this.s = -1;
-    if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
-  }
-  this.clamp();
-  if(mi) BigInteger.ZERO.subTo(this,this);
-}
-
-// (protected) clamp off excess high words
-function bnpClamp() {
-  var c = this.s&this.DM;
-  while(this.t > 0 && this[this.t-1] == c) --this.t;
-}
-
-// (public) return string representation in given radix
-function bnToString(b) {
-  if(this.s < 0) return "-"+this.negate().toString(b);
-  var k;
-  if(b == 16) k = 4;
-  else if(b == 8) k = 3;
-  else if(b == 2) k = 1;
-  else if(b == 32) k = 5;
-  else if(b == 4) k = 2;
-  else return this.toRadix(b);
-  var km = (1<<k)-1, d, m = false, r = "", i = this.t;
-  var p = this.DB-(i*this.DB)%k;
-  if(i-- > 0) {
-    if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
-    while(i >= 0) {
-      if(p < k) {
-        d = (this[i]&((1<<p)-1))<<(k-p);
-        d |= this[--i]>>(p+=this.DB-k);
-      }
-      else {
-        d = (this[i]>>(p-=k))&km;
-        if(p <= 0) { p += this.DB; --i; }
-      }
-      if(d > 0) m = true;
-      if(m) r += int2char(d);
-    }
-  }
-  return m?r:"0";
-}
-
-// (public) -this
-function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
-
-// (public) |this|
-function bnAbs() { return (this.s<0)?this.negate():this; }
-
-// (public) return + if this > a, - if this < a, 0 if equal
-function bnCompareTo(a) {
-  var r = this.s-a.s;
-  if(r != 0) return r;
-  var i = this.t;
-  r = i-a.t;
-  if(r != 0) return r;
-  while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
-  return 0;
-}
-
-// returns bit length of the integer x
-function nbits(x) {
-  var r = 1, t;
-  if((t=x>>>16) != 0) { x = t; r += 16; }
-  if((t=x>>8) != 0) { x = t; r += 8; }
-  if((t=x>>4) != 0) { x = t; r += 4; }
-  if((t=x>>2) != 0) { x = t; r += 2; }
-  if((t=x>>1) != 0) { x = t; r += 1; }
-  return r;
-}
-
-// (public) return the number of bits in "this"
-function bnBitLength() {
-  if(this.t <= 0) return 0;
-  return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
-}
-
-// (protected) r = this << n*DB
-function bnpDLShiftTo(n,r) {
-  var i;
-  for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
-  for(i = n-1; i >= 0; --i) r[i] = 0;
-  r.t = this.t+n;
-  r.s = this.s;
-}
-
-// (protected) r = this >> n*DB
-function bnpDRShiftTo(n,r) {
-  for(var i = n; i < this.t; ++i) r[i-n] = this[i];
-  r.t = Math.max(this.t-n,0);
-  r.s = this.s;
-}
-
-// (protected) r = this << n
-function bnpLShiftTo(n,r) {
-  var bs = n%this.DB;
-  var cbs = this.DB-bs;
-  var bm = (1<<cbs)-1;
-  var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
-  for(i = this.t-1; i >= 0; --i) {
-    r[i+ds+1] = (this[i]>>cbs)|c;
-    c = (this[i]&bm)<<bs;
-  }
-  for(i = ds-1; i >= 0; --i) r[i] = 0;
-  r[ds] = c;
-  r.t = this.t+ds+1;
-  r.s = this.s;
-  r.clamp();
-}
-
-// (protected) r = this >> n
-function bnpRShiftTo(n,r) {
-  r.s = this.s;
-  var ds = Math.floor(n/this.DB);
-  if(ds >= this.t) { r.t = 0; return; }
-  var bs = n%this.DB;
-  var cbs = this.DB-bs;
-  var bm = (1<<bs)-1;
-  r[0] = this[ds]>>bs;
-  for(var i = ds+1; i < this.t; ++i) {
-    r[i-ds-1] |= (this[i]&bm)<<cbs;
-    r[i-ds] = this[i]>>bs;
-  }
-  if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
-  r.t = this.t-ds;
-  r.clamp();
-}
-
-// (protected) r = this - a
-function bnpSubTo(a,r) {
-  var i = 0, c = 0, m = Math.min(a.t,this.t);
-  while(i < m) {
-    c += this[i]-a[i];
-    r[i++] = c&this.DM;
-    c >>= this.DB;
-  }
-  if(a.t < this.t) {
-    c -= a.s;
-    while(i < this.t) {
-      c += this[i];
-      r[i++] = c&this.DM;
-      c >>= this.DB;
-    }
-    c += this.s;
-  }
-  else {
-    c += this.s;
-    while(i < a.t) {
-      c -= a[i];
-      r[i++] = c&this.DM;
-      c >>= this.DB;
-    }
-    c -= a.s;
-  }
-  r.s = (c<0)?-1:0;
-  if(c < -1) r[i++] = this.DV+c;
-  else if(c > 0) r[i++] = c;
-  r.t = i;
-  r.clamp();
-}
-
-// (protected) r = this * a, r != this,a (HAC 14.12)
-// "this" should be the larger one if appropriate.
-function bnpMultiplyTo(a,r) {
-  var x = this.abs(), y = a.abs();
-  var i = x.t;
-  r.t = i+y.t;
-  while(--i >= 0) r[i] = 0;
-  for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
-  r.s = 0;
-  r.clamp();
-  if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
-}
-
-// (protected) r = this^2, r != this (HAC 14.16)
-function bnpSquareTo(r) {
-  var x = this.abs();
-  var i = r.t = 2*x.t;
-  while(--i >= 0) r[i] = 0;
-  for(i = 0; i < x.t-1; ++i) {
-    var c = x.am(i,x[i],r,2*i,0,1);
-    if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
-      r[i+x.t] -= x.DV;
-      r[i+x.t+1] = 1;
-    }
-  }
-  if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
-  r.s = 0;
-  r.clamp();
-}
-
-// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
-// r != q, this != m.  q or r may be null.
-function bnpDivRemTo(m,q,r) {
-  var pm = m.abs();
-  if(pm.t <= 0) return;
-  var pt = this.abs();
-  if(pt.t < pm.t) {
-    if(q != null) q.fromInt(0);
-    if(r != null) this.copyTo(r);
-    return;
-  }
-  if(r == null) r = nbi();
-  var y = nbi(), ts = this.s, ms = m.s;
-  var nsh = this.DB-nbits(pm[pm.t-1]);	// normalize modulus
-  if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
-  else { pm.copyTo(y); pt.copyTo(r); }
-  var ys = y.t;
-  var y0 = y[ys-1];
-  if(y0 == 0) return;
-  var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
-  var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
-  var i = r.t, j = i-ys, t = (q==null)?nbi():q;
-  y.dlShiftTo(j,t);
-  if(r.compareTo(t) >= 0) {
-    r[r.t++] = 1;
-    r.subTo(t,r);
-  }
-  BigInteger.ONE.dlShiftTo(ys,t);
-  t.subTo(y,y);	// "negative" y so we can replace sub with am later
-  while(y.t < ys) y[y.t++] = 0;
-  while(--j >= 0) {
-    // Estimate quotient digit
-    var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
-    if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) {	// Try it out
-      y.dlShiftTo(j,t);
-      r.subTo(t,r);
-      while(r[i] < --qd) r.subTo(t,r);
-    }
-  }
-  if(q != null) {
-    r.drShiftTo(ys,q);
-    if(ts != ms) BigInteger.ZERO.subTo(q,q);
-  }
-  r.t = ys;
-  r.clamp();
-  if(nsh > 0) r.rShiftTo(nsh,r);	// Denormalize remainder
-  if(ts < 0) BigInteger.ZERO.subTo(r,r);
-}
-
-// (public) this mod a
-function bnMod(a) {
-  var r = nbi();
-  this.abs().divRemTo(a,null,r);
-  if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
-  return r;
-}
-
-// Modular reduction using "classic" algorithm
-function Classic(m) { this.m = m; }
-function cConvert(x) {
-  if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
-  else return x;
-}
-function cRevert(x) { return x; }
-function cReduce(x) { x.divRemTo(this.m,null,x); }
-function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
-function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
-
-Classic.prototype.convert = cConvert;
-Classic.prototype.revert = cRevert;
-Classic.prototype.reduce = cReduce;
-Classic.prototype.mulTo = cMulTo;
-Classic.prototype.sqrTo = cSqrTo;
-
-// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
-// justification:
-//         xy == 1 (mod m)
-//         xy =  1+km
-//   xy(2-xy) = (1+km)(1-km)
-// x[y(2-xy)] = 1-k^2m^2
-// x[y(2-xy)] == 1 (mod m^2)
-// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
-// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
-// JS multiply "overflows" differently from C/C++, so care is needed here.
-function bnpInvDigit() {
-  if(this.t < 1) return 0;
-  var x = this[0];
-  if((x&1) == 0) return 0;
-  var y = x&3;		// y == 1/x mod 2^2
-  y = (y*(2-(x&0xf)*y))&0xf;	// y == 1/x mod 2^4
-  y = (y*(2-(x&0xff)*y))&0xff;	// y == 1/x mod 2^8
-  y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff;	// y == 1/x mod 2^16
-  // last step - calculate inverse mod DV directly;
-  // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
-  y = (y*(2-x*y%this.DV))%this.DV;		// y == 1/x mod 2^dbits
-  // we really want the negative inverse, and -DV < y < DV
-  return (y>0)?this.DV-y:-y;
-}
-
-// Montgomery reduction
-function Montgomery(m) {
-  this.m = m;
-  this.mp = m.invDigit();
-  this.mpl = this.mp&0x7fff;
-  this.mph = this.mp>>15;
-  this.um = (1<<(m.DB-15))-1;
-  this.mt2 = 2*m.t;
-}
-
-// xR mod m
-function montConvert(x) {
-  var r = nbi();
-  x.abs().dlShiftTo(this.m.t,r);
-  r.divRemTo(this.m,null,r);
-  if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
-  return r;
-}
-
-// x/R mod m
-function montRevert(x) {
-  var r = nbi();
-  x.copyTo(r);
-  this.reduce(r);
-  return r;
-}
-
-// x = x/R mod m (HAC 14.32)
-function montReduce(x) {
-  while(x.t <= this.mt2)	// pad x so am has enough room later
-    x[x.t++] = 0;
-  for(var i = 0; i < this.m.t; ++i) {
-    // faster way of calculating u0 = x[i]*mp mod DV
-    var j = x[i]&0x7fff;
-    var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
-    // use am to combine the multiply-shift-add into one call
-    j = i+this.m.t;
-    x[j] += this.m.am(0,u0,x,i,0,this.m.t);
-    // propagate carry
-    while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
-  }
-  x.clamp();
-  x.drShiftTo(this.m.t,x);
-  if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
-}
-
-// r = "x^2/R mod m"; x != r
-function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
-
-// r = "xy/R mod m"; x,y != r
-function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
-
-Montgomery.prototype.convert = montConvert;
-Montgomery.prototype.revert = montRevert;
-Montgomery.prototype.reduce = montReduce;
-Montgomery.prototype.mulTo = montMulTo;
-Montgomery.prototype.sqrTo = montSqrTo;
-
-// (protected) true iff this is even
-function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
-
-// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
-function bnpExp(e,z) {
-  if(e > 0xffffffff || e < 1) return BigInteger.ONE;
-  var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
-  g.copyTo(r);
-  while(--i >= 0) {
-    z.sqrTo(r,r2);
-    if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
-    else { var t = r; r = r2; r2 = t; }
-  }
-  return z.revert(r);
-}
-
-// (public) this^e % m, 0 <= e < 2^32
-function bnModPowInt(e,m) {
-  var z;
-  if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
-  return this.exp(e,z);
-}
-
-// protected
-BigInteger.prototype.copyTo = bnpCopyTo;
-BigInteger.prototype.fromInt = bnpFromInt;
-BigInteger.prototype.fromString = bnpFromString;
-BigInteger.prototype.clamp = bnpClamp;
-BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
-BigInteger.prototype.drShiftTo = bnpDRShiftTo;
-BigInteger.prototype.lShiftTo = bnpLShiftTo;
-BigInteger.prototype.rShiftTo = bnpRShiftTo;
-BigInteger.prototype.subTo = bnpSubTo;
-BigInteger.prototype.multiplyTo = bnpMultiplyTo;
-BigInteger.prototype.squareTo = bnpSquareTo;
-BigInteger.prototype.divRemTo = bnpDivRemTo;
-BigInteger.prototype.invDigit = bnpInvDigit;
-BigInteger.prototype.isEven = bnpIsEven;
-BigInteger.prototype.exp = bnpExp;
-
-// public
-BigInteger.prototype.toString = bnToString;
-BigInteger.prototype.negate = bnNegate;
-BigInteger.prototype.abs = bnAbs;
-BigInteger.prototype.compareTo = bnCompareTo;
-BigInteger.prototype.bitLength = bnBitLength;
-BigInteger.prototype.mod = bnMod;
-BigInteger.prototype.modPowInt = bnModPowInt;
-
-// "constants"
-BigInteger.ZERO = nbv(0);
-BigInteger.ONE = nbv(1);
-
-// GPG4Browsers - An OpenPGP implementation in javascript
-// Copyright (C) 2011 Recurity Labs GmbH
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//
-// ElGamal implementation
-
-function Elgamal() {
-	
-	function encrypt(m,g,p,y) {
-		//  choose k in {2,...,p-2}
-		var two = BigInteger.ONE.add(BigInteger.ONE);
-		var pMinus2 = p.subtract(two);
-		var k = openpgp_crypto_getRandomBigIntegerInRange(two, pMinus2);
-		var k = k.mod(pMinus2).add(BigInteger.ONE);
-		var c = new Array();
-		c[0] = g.modPow(k, p);
-		c[1] = y.modPow(k, p).multiply(m).mod(p).toMPI();
-		c[0] = c[0].toMPI();
-		return c;
-	}
-	
-	function decrypt(c1,c2,p,x) {
-		util.print_debug("Elgamal Decrypt:\nc1:"+util.hexstrdump(c1.toMPI())+"\n"+
-			  "c2:"+util.hexstrdump(c2.toMPI())+"\n"+
-			  "p:"+util.hexstrdump(p.toMPI())+"\n"+
-			  "x:"+util.hexstrdump(x.toMPI()));
-		return (c1.modPow(x, p).modInverse(p)).multiply(c2).mod(p);
-		//var c = c1.pow(x).modInverse(p); // c0^-a mod p
-	    //return c.multiply(c2).mod(p);
-	}
-	
-	// signing and signature verification using Elgamal is not required by OpenPGP.
-	this.encrypt = encrypt;
-	this.decrypt = decrypt;
-}/*
- * Copyright (c) 2003-2005  Tom Wu (tjw@cs.Stanford.EDU) 
- * All Rights Reserved.
- *
- * Modified by Recurity Labs GmbH
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
- *
- * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
- * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
- * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * In addition, the following condition applies:
- *
- * All redistributions must retain an intact copy of this copyright notice
- * and disclaimer.
- */
-// Extended JavaScript BN functions, required for RSA private ops.
-
-// Version 1.1: new BigInteger("0", 10) returns "proper" zero
-// Version 1.2: square() API, isProbablePrime fix
-
-// (public)
-function bnClone() { var r = nbi(); this.copyTo(r); return r; }
-
-// (public) return value as integer
-function bnIntValue() {
-  if(this.s < 0) {
-    if(this.t == 1) return this[0]-this.DV;
-    else if(this.t == 0) return -1;
-  }
-  else if(this.t == 1) return this[0];
-  else if(this.t == 0) return 0;
-  // assumes 16 < DB < 32
-  return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];
-}
-
-// (public) return value as byte
-function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }
-
-// (public) return value as short (assumes DB>=16)
-function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }
-
-// (protected) return x s.t. r^x < DV
-function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }
-
-// (public) 0 if this == 0, 1 if this > 0
-function bnSigNum() {
-  if(this.s < 0) return -1;
-  else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
-  else return 1;
-}
-
-// (protected) convert to radix string
-function bnpToRadix(b) {
-  if(b == null) b = 10;
-  if(this.signum() == 0 || b < 2 || b > 36) return "0";
-  var cs = this.chunkSize(b);
-  var a = Math.pow(b,cs);
-  var d = nbv(a), y = nbi(), z = nbi(), r = "";
-  this.divRemTo(d,y,z);
-  while(y.signum() > 0) {
-    r = (a+z.intValue()).toString(b).substr(1) + r;
-    y.divRemTo(d,y,z);
-  }
-  return z.intValue().toString(b) + r;
-}
-
-// (protected) convert from radix string
-function bnpFromRadix(s,b) {
-  this.fromInt(0);
-  if(b == null) b = 10;
-  var cs = this.chunkSize(b);
-  var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
-  for(var i = 0; i < s.length; ++i) {
-    var x = intAt(s,i);
-    if(x < 0) {
-      if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
-      continue;
-    }
-    w = b*w+x;
-    if(++j >= cs) {
-      this.dMultiply(d);
-      this.dAddOffset(w,0);
-      j = 0;
-      w = 0;
-    }
-  }
-  if(j > 0) {
-    this.dMultiply(Math.pow(b,j));
-    this.dAddOffset(w,0);
-  }
-  if(mi) BigInteger.ZERO.subTo(this,this);
-}
-
-// (protected) alternate constructor
-function bnpFromNumber(a,b,c) {
-  if("number" == typeof b) {
-    // new BigInteger(int,int,RNG)
-    if(a < 2) this.fromInt(1);
-    else {
-      this.fromNumber(a,c);
-      if(!this.testBit(a-1))	// force MSB set
-        this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);
-      if(this.isEven()) this.dAddOffset(1,0); // force odd
-      while(!this.isProbablePrime(b)) {
-        this.dAddOffset(2,0);
-        if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);
-      }
-    }
-  }
-  else {
-    // new BigInteger(int,RNG)
-    var x = new Array(), t = a&7;
-    x.length = (a>>3)+1;
-    b.nextBytes(x);
-    if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
-    this.fromString(x,256);
-  }
-}
-
-// (public) convert to bigendian byte array
-function bnToByteArray() {
-  var i = this.t, r = new Array();
-  r[0] = this.s;
-  var p = this.DB-(i*this.DB)%8, d, k = 0;
-  if(i-- > 0) {
-    if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)
-      r[k++] = d|(this.s<<(this.DB-p));
-    while(i >= 0) {
-      if(p < 8) {
-        d = (this[i]&((1<<p)-1))<<(8-p);
-        d |= this[--i]>>(p+=this.DB-8);
-      }
-      else {
-        d = (this[i]>>(p-=8))&0xff;
-        if(p <= 0) { p += this.DB; --i; }
-      }
-      //if((d&0x80) != 0) d |= -256;
-      //if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
-      if(k > 0 || d != this.s) r[k++] = d;
-    }
-  }
-  return r;
-}
-
-function bnEquals(a) { return(this.compareTo(a)==0); }
-function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
-function bnMax(a) { return(this.compareTo(a)>0)?this:a; }
-
-// (protected) r = this op a (bitwise)
-function bnpBitwiseTo(a,op,r) {
-  var i, f, m = Math.min(a.t,this.t);
-  for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);
-  if(a.t < this.t) {
-    f = a.s&this.DM;
-    for(i = m; i < this.t; ++i) r[i] = op(this[i],f);
-    r.t = this.t;
-  }
-  else {
-    f = this.s&this.DM;
-    for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);
-    r.t = a.t;
-  }
-  r.s = op(this.s,a.s);
-  r.clamp();
-}
-
-// (public) this & a
-function op_and(x,y) { return x&y; }
-function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }
-
-// (public) this | a
-function op_or(x,y) { return x|y; }
-function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }
-
-// (public) this ^ a
-function op_xor(x,y) { return x^y; }
-function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }
-
-// (public) this & ~a
-function op_andnot(x,y) { return x&~y; }
-function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }
-
-// (public) ~this
-function bnNot() {
-  var r = nbi();
-  for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];
-  r.t = this.t;
-  r.s = ~this.s;
-  return r;
-}
-
-// (public) this << n
-function bnShiftLeft(n) {
-  var r = nbi();
-  if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);
-  return r;
-}
-
-// (public) this >> n
-function bnShiftRight(n) {
-  var r = nbi();
-  if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);
-  return r;
-}
-
-// return index of lowest 1-bit in x, x < 2^31
-function lbit(x) {
-  if(x == 0) return -1;
-  var r = 0;
-  if((x&0xffff) == 0) { x >>= 16; r += 16; }
-  if((x&0xff) == 0) { x >>= 8; r += 8; }
-  if((x&0xf) == 0) { x >>= 4; r += 4; }
-  if((x&3) == 0) { x >>= 2; r += 2; }
-  if((x&1) == 0) ++r;
-  return r;
-}
-
-// (public) returns index of lowest 1-bit (or -1 if none)
-function bnGetLowestSetBit() {
-  for(var i = 0; i < this.t; ++i)
-    if(this[i] != 0) return i*this.DB+lbit(this[i]);
-  if(this.s < 0) return this.t*this.DB;
-  return -1;
-}
-
-// return number of 1 bits in x
-function cbit(x) {
-  var r = 0;
-  while(x != 0) { x &= x-1; ++r; }
-  return r;
-}
-
-// (public) return number of set bits
-function bnBitCount() {
-  var r = 0, x = this.s&this.DM;
-  for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);
-  return r;
-}
-
-// (public) true iff nth bit is set
-function bnTestBit(n) {
-  var j = Math.floor(n/this.DB);
-  if(j >= this.t) return(this.s!=0);
-  return((this[j]&(1<<(n%this.DB)))!=0);
-}
-
-// (protected) this op (1<<n)
-function bnpChangeBit(n,op) {
-  var r = BigInteger.ONE.shiftLeft(n);
-  this.bitwiseTo(r,op,r);
-  return r;
-}
-
-// (public) this | (1<<n)
-function bnSetBit(n) { return this.changeBit(n,op_or); }
-
-// (public) this & ~(1<<n)
-function bnClearBit(n) { return this.changeBit(n,op_andnot); }
-
-// (public) this ^ (1<<n)
-function bnFlipBit(n) { return this.changeBit(n,op_xor); }
-
-// (protected) r = this + a
-function bnpAddTo(a,r) {
-  var i = 0, c = 0, m = Math.min(a.t,this.t);
-  while(i < m) {
-    c += this[i]+a[i];
-    r[i++] = c&this.DM;
-    c >>= this.DB;
-  }
-  if(a.t < this.t) {
-    c += a.s;
-    while(i < this.t) {
-      c += this[i];
-      r[i++] = c&this.DM;
-      c >>= this.DB;
-    }
-    c += this.s;
-  }
-  else {
-    c += this.s;
-    while(i < a.t) {
-      c += a[i];
-      r[i++] = c&this.DM;
-      c >>= this.DB;
-    }
-    c += a.s;
-  }
-  r.s = (c<0)?-1:0;
-  if(c > 0) r[i++] = c;
-  else if(c < -1) r[i++] = this.DV+c;
-  r.t = i;
-  r.clamp();
-}
-
-// (public) this + a
-function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }
-
-// (public) this - a
-function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }
-
-// (public) this * a
-function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }
-
-// (public) this^2
-function bnSquare() { var r = nbi(); this.squareTo(r); return r; }
-
-// (public) this / a
-function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }
-
-// (public) this % a
-function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }
-
-// (public) [this/a,this%a]
-function bnDivideAndRemainder(a) {
-  var q = nbi(), r = nbi();
-  this.divRemTo(a,q,r);
-  return new Array(q,r);
-}
-
-// (protected) this *= n, this >= 0, 1 < n < DV
-function bnpDMultiply(n) {
-  this[this.t] = this.am(0,n-1,this,0,0,this.t);
-  ++this.t;
-  this.clamp();
-}
-
-// (protected) this += n << w words, this >= 0
-function bnpDAddOffset(n,w) {
-  if(n == 0) return;
-  while(this.t <= w) this[this.t++] = 0;
-  this[w] += n;
-  while(this[w] >= this.DV) {
-    this[w] -= this.DV;
-    if(++w >= this.t) this[this.t++] = 0;
-    ++this[w];
-  }
-}
-
-// A "null" reducer
-function NullExp() {}
-function nNop(x) { return x; }
-function nMulTo(x,y,r) { x.multiplyTo(y,r); }
-function nSqrTo(x,r) { x.squareTo(r); }
-
-NullExp.prototype.convert = nNop;
-NullExp.prototype.revert = nNop;
-NullExp.prototype.mulTo = nMulTo;
-NullExp.prototype.sqrTo = nSqrTo;
-
-// (public) this^e
-function bnPow(e) { return this.exp(e,new NullExp()); }
-
-// (protected) r = lower n words of "this * a", a.t <= n
-// "this" should be the larger one if appropriate.
-function bnpMultiplyLowerTo(a,n,r) {
-  var i = Math.min(this.t+a.t,n);
-  r.s = 0; // assumes a,this >= 0
-  r.t = i;
-  while(i > 0) r[--i] = 0;
-  var j;
-  for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);
-  for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);
-  r.clamp();
-}
-
-// (protected) r = "this * a" without lower n words, n > 0
-// "this" should be the larger one if appropriate.
-function bnpMultiplyUpperTo(a,n,r) {
-  --n;
-  var i = r.t = this.t+a.t-n;
-  r.s = 0; // assumes a,this >= 0
-  while(--i >= 0) r[i] = 0;
-  for(i = Math.max(n-this.t,0); i < a.t; ++i)
-    r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);
-  r.clamp();
-  r.drShiftTo(1,r);
-}
-
-// Barrett modular reduction
-function Barrett(m) {
-  // setup Barrett
-  this.r2 = nbi();
-  this.q3 = nbi();
-  BigInteger.ONE.dlShiftTo(2*m.t,this.r2);
-  this.mu = this.r2.divide(m);
-  this.m = m;
-}
-
-function barrettConvert(x) {
-  if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);
-  else if(x.compareTo(this.m) < 0) return x;
-  else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
-}
-
-function barrettRevert(x) { return x; }
-
-// x = x mod m (HAC 14.42)
-function barrettReduce(x) {
-  x.drShiftTo(this.m.t-1,this.r2);
-  if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }
-  this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);
-  this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);
-  while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);
-  x.subTo(this.r2,x);
-  while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
-}
-
-// r = x^2 mod m; x != r
-function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
-
-// r = x*y mod m; x,y != r
-function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
-
-Barrett.prototype.convert = barrettConvert;
-Barrett.prototype.revert = barrettRevert;
-Barrett.prototype.reduce = barrettReduce;
-Barrett.prototype.mulTo = barrettMulTo;
-Barrett.prototype.sqrTo = barrettSqrTo;
-
-// (public) this^e % m (HAC 14.85)
-function bnModPow(e,m) {
-  var i = e.bitLength(), k, r = nbv(1), z;
-  if(i <= 0) return r;
-  else if(i < 18) k = 1;
-  else if(i < 48) k = 3;
-  else if(i < 144) k = 4;
-  else if(i < 768) k = 5;
-  else k = 6;
-  if(i < 8)
-    z = new Classic(m);
-  else if(m.isEven())
-    z = new Barrett(m);
-  else
-    z = new Montgomery(m);
-
-  // precomputation
-  var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;
-  g[1] = z.convert(this);
-  if(k > 1) {
-    var g2 = nbi();
-    z.sqrTo(g[1],g2);
-    while(n <= km) {
-      g[n] = nbi();
-      z.mulTo(g2,g[n-2],g[n]);
-      n += 2;
-    }
-  }
-
-  var j = e.t-1, w, is1 = true, r2 = nbi(), t;
-  i = nbits(e[j])-1;
-  while(j >= 0) {
-    if(i >= k1) w = (e[j]>>(i-k1))&km;
-    else {
-      w = (e[j]&((1<<(i+1))-1))<<(k1-i);
-      if(j > 0) w |= e[j-1]>>(this.DB+i-k1);
-    }
-
-    n = k;
-    while((w&1) == 0) { w >>= 1; --n; }
-    if((i -= n) < 0) { i += this.DB; --j; }
-    if(is1) {	// ret == 1, don't bother squaring or multiplying it
-      g[w].copyTo(r);
-      is1 = false;
-    }
-    else {
-      while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }
-      if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }
-      z.mulTo(r2,g[w],r);
-    }
-
-    while(j >= 0 && (e[j]&(1<<i)) == 0) {
-      z.sqrTo(r,r2); t = r; r = r2; r2 = t;
-      if(--i < 0) { i = this.DB-1; --j; }
-    }
-  }
-  return z.revert(r);
-}
-
-// (public) gcd(this,a) (HAC 14.54)
-function bnGCD(a) {
-  var x = (this.s<0)?this.negate():this.clone();
-  var y = (a.s<0)?a.negate():a.clone();
-  if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }
-  var i = x.getLowestSetBit(), g = y.getLowestSetBit();
-  if(g < 0) return x;
-  if(i < g) g = i;
-  if(g > 0) {
-    x.rShiftTo(g,x);
-    y.rShiftTo(g,y);
-  }
-  while(x.signum() > 0) {
-    if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);
-    if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);
-    if(x.compareTo(y) >= 0) {
-      x.subTo(y,x);
-      x.rShiftTo(1,x);
-    }
-    else {
-      y.subTo(x,y);
-      y.rShiftTo(1,y);
-    }
-  }
-  if(g > 0) y.lShiftTo(g,y);
-  return y;
-}
-
-// (protected) this % n, n < 2^26
-function bnpModInt(n) {
-  if(n <= 0) return 0;
-  var d = this.DV%n, r = (this.s<0)?n-1:0;
-  if(this.t > 0)
-    if(d == 0) r = this[0]%n;
-    else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;
-  return r;
-}
-
-// (public) 1/this % m (HAC 14.61)
-function bnModInverse(m) {
-  var ac = m.isEven();
-  if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
-  var u = m.clone(), v = this.clone();
-  var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
-  while(u.signum() != 0) {
-    while(u.isEven()) {
-      u.rShiftTo(1,u);
-      if(ac) {
-        if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
-        a.rShiftTo(1,a);
-      }
-      else if(!b.isEven()) b.subTo(m,b);
-      b.rShiftTo(1,b);
-    }
-    while(v.isEven()) {
-      v.rShiftTo(1,v);
-      if(ac) {
-        if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
-        c.rShiftTo(1,c);
-      }
-      else if(!d.isEven()) d.subTo(m,d);
-      d.rShiftTo(1,d);
-    }
-    if(u.compareTo(v) >= 0) {
-      u.subTo(v,u);
-      if(ac) a.subTo(c,a);
-      b.subTo(d,b);
-    }
-    else {
-      v.subTo(u,v);
-      if(ac) c.subTo(a,c);
-      d.subTo(b,d);
-    }
-  }
-  if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
-  if(d.compareTo(m) >= 0) return d.subtract(m);
-  if(d.signum() < 0) d.addTo(m,d); else return d;
-  if(d.signum() < 0) return d.add(m); else return d;
-}
-
-var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,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];
-var lplim = (1<<26)/lowprimes[lowprimes.length-1];
-
-// (public) test primality with certainty >= 1-.5^t
-function bnIsProbablePrime(t) {
-  var i, x = this.abs();
-  if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {
-    for(i = 0; i < lowprimes.length; ++i)
-      if(x[0] == lowprimes[i]) return true;
-    return false;
-  }
-  if(x.isEven()) return false;
-  i = 1;
-  while(i < lowprimes.length) {
-    var m = lowprimes[i], j = i+1;
-    while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];
-    m = x.modInt(m);
-    while(i < j) if(m%lowprimes[i++] == 0) return false;
-  }
-  return x.millerRabin(t);
-}
-
-/* added by Recurity Labs */
-
-function nbits(x) {
-	var n = 1, t;
-	if ((t = x >>> 16) != 0) {
-		x = t;
-		n += 16;
-	}
-	if ((t = x >> 8) != 0) {
-		x = t;
-		n += 8;
-	}
-	if ((t = x >> 4) != 0) {
-		x = t;
-		n += 4;
-	}
-	if ((t = x >> 2) != 0) {
-		x = t;
-		n += 2;
-	}
-	if ((t = x >> 1) != 0) {
-		x = t;
-		n += 1;
-	}
-	return n;
-}
-
-function bnToMPI () {
-	var ba = this.toByteArray();
-	var size = (ba.length-1)*8+nbits(ba[0]);
-	var result = "";
-	result += String.fromCharCode((size & 0xFF00) >> 8);
-	result += String.fromCharCode(size & 0xFF);
-	result += util.bin2str(ba);
-	return result;
-}
-/* END of addition */
-
-// (protected) true if probably prime (HAC 4.24, Miller-Rabin)
-function bnpMillerRabin(t) {
-  var n1 = this.subtract(BigInteger.ONE);
-  var k = n1.getLowestSetBit();
-  if(k <= 0) return false;
-  var r = n1.shiftRight(k);
-  t = (t+1)>>1;
-  if(t > lowprimes.length) t = lowprimes.length;
-  var a = nbi();
-  for(var i = 0; i < t; ++i) {
-    //Pick bases at random, instead of starting at 2
-    a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);
-    var y = a.modPow(r,this);
-    if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
-      var j = 1;
-      while(j++ < k && y.compareTo(n1) != 0) {
-        y = y.modPowInt(2,this);
-        if(y.compareTo(BigInteger.ONE) == 0) return false;
-      }
-      if(y.compareTo(n1) != 0) return false;
-    }
-  }
-  return true;
-}
-
-// protected
-BigInteger.prototype.chunkSize = bnpChunkSize;
-BigInteger.prototype.toRadix = bnpToRadix;
-BigInteger.prototype.fromRadix = bnpFromRadix;
-BigInteger.prototype.fromNumber = bnpFromNumber;
-BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
-BigInteger.prototype.changeBit = bnpChangeBit;
-BigInteger.prototype.addTo = bnpAddTo;
-BigInteger.prototype.dMultiply = bnpDMultiply;
-BigInteger.prototype.dAddOffset = bnpDAddOffset;
-BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
-BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
-BigInteger.prototype.modInt = bnpModInt;
-BigInteger.prototype.millerRabin = bnpMillerRabin;
-
-// public
-BigInteger.prototype.clone = bnClone;
-BigInteger.prototype.intValue = bnIntValue;
-BigInteger.prototype.byteValue = bnByteValue;
-BigInteger.prototype.shortValue = bnShortValue;
-BigInteger.prototype.signum = bnSigNum;
-BigInteger.prototype.toByteArray = bnToByteArray;
-BigInteger.prototype.equals = bnEquals;
-BigInteger.prototype.min = bnMin;
-BigInteger.prototype.max = bnMax;
-BigInteger.prototype.and = bnAnd;
-BigInteger.prototype.or = bnOr;
-BigInteger.prototype.xor = bnXor;
-BigInteger.prototype.andNot = bnAndNot;
-BigInteger.prototype.not = bnNot;
-BigInteger.prototype.shiftLeft = bnShiftLeft;
-BigInteger.prototype.shiftRight = bnShiftRight;
-BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
-BigInteger.prototype.bitCount = bnBitCount;
-BigInteger.prototype.testBit = bnTestBit;
-BigInteger.prototype.setBit = bnSetBit;
-BigInteger.prototype.clearBit = bnClearBit;
-BigInteger.prototype.flipBit = bnFlipBit;
-BigInteger.prototype.add = bnAdd;
-BigInteger.prototype.subtract = bnSubtract;
-BigInteger.prototype.multiply = bnMultiply;
-BigInteger.prototype.divide = bnDivide;
-BigInteger.prototype.remainder = bnRemainder;
-BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
-BigInteger.prototype.modPow = bnModPow;
-BigInteger.prototype.modInverse = bnModInverse;
-BigInteger.prototype.pow = bnPow;
-BigInteger.prototype.gcd = bnGCD;
-BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
-BigInteger.prototype.toMPI = bnToMPI;
-
-// JSBN-specific extension
-BigInteger.prototype.square = bnSquare;
-// GPG4Browsers - An OpenPGP implementation in javascript
-// Copyright (C) 2011 Recurity Labs GmbH
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA 
-
-// The GPG4Browsers symmetric crypto interface
-
-/**
- * Symmetrically encrypts data using prefixedrandom, a key with length 
- * depending on the algorithm in openpgp_cfb mode with or without resync
- * (MDC style)
- * @param prefixrandom secure random bytes as string in length equal to the
- * block size of the algorithm used (use openpgp_crypto_getPrefixRandom(algo)
- * to retrieve that string
- * @param algo [Integer] algorithm to use (see RFC4880 9.2)
- * @param key [String] key as string. length is depending on the algorithm used
- * @param data [String] data to encrypt
- * @param openpgp_cfb [boolean]
- * @return [String] encrypted data
- */
-function openpgp_crypto_symmetricEncrypt(prefixrandom, algo, key, data, openpgp_cfb) {
-	switch(algo) {
-		case 0: // Plaintext or unencrypted data
-			return data; // blockcipherencryptfn, plaintext, block_size, key
-		case 2: // TripleDES (DES-EDE, [SCHNEIER] [HAC] - 168 bit key derived from 192)
-			return openpgp_cfb_encrypt(prefixrandom, desede, data,8,key, openpgp_cfb).substring(0, data.length + 10);
-		case 3: // CAST5 (128 bit key, as per [RFC2144])
-			return openpgp_cfb_encrypt(prefixrandom, cast5_encrypt, data,8,key, openpgp_cfb).substring(0, data.length + 10);
-		case 4: // Blowfish (128 bit key, 16 rounds) [BLOWFISH]
-			return openpgp_cfb_encrypt(prefixrandom, BFencrypt, data,8,key, openpgp_cfb).substring(0, data.length + 10);
-		case 7: // AES with 128-bit key [AES]
-		case 8: // AES with 192-bit key
-		case 9: // AES with 256-bit key
-			return openpgp_cfb_encrypt(prefixrandom, AESencrypt, data, 16, keyExpansion(key), openpgp_cfb).substring(0, data.length + 18);
-		case 10: // Twofish with 256-bit key [TWOFISH]
-			return openpgp_cfb_encrypt(prefixrandom, TFencrypt, data,16, key, openpgp_cfb).substring(0, data.length + 18);
-		case 1: // IDEA [IDEA]
-			util.print_error("IDEA Algorithm not implemented");
-			return null;
-		default:
-			return null;
-	}
-}
-
-/**
- * Symmetrically decrypts data using a key with length depending on the
- * algorithm in openpgp_cfb mode with or without resync (MDC style)
- * @param algo [Integer] algorithm to use (see RFC4880 9.2)
- * @param key [String] key as string. length is depending on the algorithm used
- * @param data [String] data to be decrypted
- * @param openpgp_cfb [boolean] if true use the resync (for encrypteddata); 
- * otherwise use without the resync (for MDC encrypted data)
- * @return [String] plaintext data
- */
-function openpgp_crypto_symmetricDecrypt(algo, key, data, openpgp_cfb) {
-	util.print_debug_hexstr_dump("openpgp_crypto_symmetricDecrypt:\nalgo:"+algo+"\nencrypteddata:",data);
-	var n = 0;
-	if (!openpgp_cfb)
-		n = 2;
-	switch(algo) {
-	case 0: // Plaintext or unencrypted data
-		return data;
-	case 2: // TripleDES (DES-EDE, [SCHNEIER] [HAC] - 168 bit key derived from 192)
-		return openpgp_cfb_decrypt(desede, 8, key, data, openpgp_cfb).substring(n, (data.length+n)-10);
-	case 3: // CAST5 (128 bit key, as per [RFC2144])
-		return openpgp_cfb_decrypt(cast5_encrypt, 8, key, data, openpgp_cfb).substring(n, (data.length+n)-10);
-	case 4: // Blowfish (128 bit key, 16 rounds) [BLOWFISH]
-		return openpgp_cfb_decrypt(BFencrypt, 8, key, data, openpgp_cfb).substring(n, (data.length+n)-10);
-	case 7: // AES with 128-bit key [AES]
-	case 8: // AES with 192-bit key
-	case 9: // AES with 256-bit key
-		return openpgp_cfb_decrypt(AESencrypt, 16, keyExpansion(key), data, openpgp_cfb).substring(n, (data.length+n)-18);
-	case 10: // Twofish with 256-bit key [TWOFISH]
-		var result = openpgp_cfb_decrypt(TFencrypt, 16, key, data, openpgp_cfb).substring(n, (data.length+n)-18);
+	this.encode_length = encode_length;
+
+	/**
+	 * Writes a packet header version 4 with the given tag_type and length to a
+	 * string
+	 * 
+	 * @param tag_type
+	 *            integer of tag type
+	 * @param length
+	 *            integer length of the payload
+	 * @return string of the header
+	 */
+	function write_packet_header(tag_type, length) {
+		/* we're only generating v4 packet headers here */
+		var result = "";
+		result += String.fromCharCode(0xC0 | tag_type);
+		result += encode_length(length);
 		return result;
-	case 1: // IDEA [IDEA]
-		util.print_error(""+ (algo == 1 ? "IDEA Algorithm not implemented" : "Twofish Algorithm not implemented"));
-		return null;
-	default:
-	}
-	return null;
-}// Modified by Recurity Labs GmbH 
-
-// modified version of http://www.hanewin.net/encrypt/PGdecode.js:
-
-/* OpenPGP encryption using RSA/AES
- * Copyright 2005-2006 Herbert Hanewinkel, www.haneWIN.de
- * version 2.0, check www.haneWIN.de for the latest version
-
- * This software is provided as-is, without express or implied warranty.  
- * Permission to use, copy, modify, distribute or sell this software, with or
- * without fee, for any purpose and by any individual or organization, is hereby
- * granted, provided that the above copyright notice and this paragraph appear 
- * in all copies. Distribution as a part of an application or binary must
- * include the above copyright notice in the documentation and/or other
- * materials provided with the application or distribution.
- */
-
-// --------------------------------------
-/**
- * This function encrypts a given with the specified prefixrandom 
- * using the specified blockcipher to encrypt a message
- * @param prefixrandom random bytes of block_size length provided 
- *  as a string to be used in prefixing the data
- * @param blockcipherfn the algorithm encrypt function to encrypt
- *  data in one block_size encryption. The function must be 
- *  specified as blockcipherfn([integer_array(integers 0..255)] 
- *  block,[integer_array(integers 0..255)] key) returning an 
- *  array of bytes (integers 0..255)
- * @param block_size the block size in bytes of the algorithm used
- * @param plaintext data to be encrypted provided as a string
- * @param key key to be used to encrypt the data as 
- *  integer_array(integers 0..255)]. This will be passed to the 
- *  blockcipherfn
- * @param resync a boolean value specifying if a resync of the 
- *  IV should be used or not. The encrypteddatapacket uses the 
- *  "old" style with a resync. Encryption within an 
- *  encryptedintegrityprotecteddata packet is not resyncing the IV.
- * @return a string with the encrypted data
- */
-function openpgp_cfb_encrypt(prefixrandom, blockcipherencryptfn, plaintext, block_size, key, resync) {
-	var FR = new Array(block_size);
-	var FRE = new Array(block_size);
-
-	prefixrandom = prefixrandom + prefixrandom.charAt(block_size-2) +prefixrandom.charAt(block_size-1);
-	util.print_debug("prefixrandom:"+util.hexstrdump(prefixrandom));
-	var ciphertext = "";
-	// 1.  The feedback register (FR) is set to the IV, which is all zeros.
-	for (var i = 0; i < block_size; i++) FR[i] = 0;
-	
-	// 2.  FR is encrypted to produce FRE (FR Encrypted).  This is the
-    //     encryption of an all-zero value.
-	FRE = blockcipherencryptfn(FR, key);
-	// 3.  FRE is xored with the first BS octets of random data prefixed to
-    //     the plaintext to produce C[1] through C[BS], the first BS octets
-    //     of ciphertext.
-	for (var i = 0; i < block_size; i++) ciphertext += String.fromCharCode(FRE[i] ^ prefixrandom.charCodeAt(i));
-	
-	// 4.  FR is loaded with C[1] through C[BS].
-	for (var i = 0; i < block_size; i++) FR[i] = ciphertext.charCodeAt(i);
-	
-	// 5.  FR is encrypted to produce FRE, the encryption of the first BS
-    // 	   octets of ciphertext.
-	FRE = blockcipherencryptfn(FR, key);
-
-	// 6.  The left two octets of FRE get xored with the next two octets of
-	//     data that were prefixed to the plaintext.  This produces C[BS+1]
-	//     and C[BS+2], the next two octets of ciphertext.
-	ciphertext += String.fromCharCode(FRE[0] ^ prefixrandom.charCodeAt(block_size));
-	ciphertext += String.fromCharCode(FRE[1] ^ prefixrandom.charCodeAt(block_size+1));
-
-	if (resync) {
-		// 7.  (The resync step) FR is loaded with C3-C10.
-		for (var i = 0; i < block_size; i++) FR[i] = ciphertext.charCodeAt(i+2);
-	} else {
-		for (var i = 0; i < block_size; i++) FR[i] = ciphertext.charCodeAt(i);
-	}
-	// 8.  FR is encrypted to produce FRE.
-	FRE = blockcipherencryptfn(FR, key);
-	
-	if (resync) {
-		// 9.  FRE is xored with the first 8 octets of the given plaintext, now
-	    //	   that we have finished encrypting the 10 octets of prefixed data.
-	    // 	   This produces C11-C18, the next 8 octets of ciphertext.
-		for (var i = 0; i < block_size; i++)
-			ciphertext += String.fromCharCode(FRE[i] ^ plaintext.charCodeAt(i));
-		for(n=block_size+2; n < plaintext.length; n+=block_size) {
-			// 10. FR is loaded with C11-C18
-			for (var i = 0; i < block_size; i++) FR[i] = ciphertext.charCodeAt(n+i);
-		
-			// 11. FR is encrypted to produce FRE.
-			FRE = blockcipherencryptfn(FR, key);
-		
-			// 12. FRE is xored with the next 8 octets of plaintext, to produce the
-			// next 8 octets of ciphertext.  These are loaded into FR and the
-			// process is repeated until the plaintext is used up.
-			for (var i = 0; i < block_size; i++) ciphertext += String.fromCharCode(FRE[i] ^ plaintext.charCodeAt((n-2)+i));
-		}
-	}
-	else {
-		plaintext = "  "+plaintext;
-		// 9.  FRE is xored with the first 8 octets of the given plaintext, now
-	    //	   that we have finished encrypting the 10 octets of prefixed data.
-	    // 	   This produces C11-C18, the next 8 octets of ciphertext.
-		for (var i = 2; i < block_size; i++) ciphertext += String.fromCharCode(FRE[i] ^ plaintext.charCodeAt(i));
-		var tempCiphertext = ciphertext.substring(0,2*block_size).split('');
-		var tempCiphertextString = ciphertext.substring(block_size);
-		for(n=block_size; n<plaintext.length; n+=block_size) {
-			// 10. FR is loaded with C11-C18
-			for (var i = 0; i < block_size; i++) FR[i] = tempCiphertextString.charCodeAt(i);
-			tempCiphertextString='';
-			
-			// 11. FR is encrypted to produce FRE.
-			FRE = blockcipherencryptfn(FR, key);
-			
-			// 12. FRE is xored with the next 8 octets of plaintext, to produce the
-			//     next 8 octets of ciphertext.  These are loaded into FR and the
-			//     process is repeated until the plaintext is used up.
-			for (var i = 0; i < block_size; i++){ tempCiphertext.push(String.fromCharCode(FRE[i] ^ plaintext.charCodeAt(n+i)));
-			tempCiphertextString += String.fromCharCode(FRE[i] ^ plaintext.charCodeAt(n+i));
-			}
-		}
-		ciphertext = tempCiphertext.join('');
-		
-	}
-	return ciphertext;
-}
-
-/**
- * decrypts the prefixed data for the Modification Detection Code (MDC) computation
- * @param blockcipherencryptfn cipher function to use
- * @param block_size blocksize of the algorithm
- * @param key the key for encryption
- * @param ciphertext the encrypted data
- * @return plaintext data of D(ciphertext) with blocksize length +2
- */
-function openpgp_cfb_mdc(blockcipherencryptfn, block_size, key, ciphertext) {
-	var iblock = new Array(block_size);
-	var ablock = new Array(block_size);
-	var i;
-
-	// initialisation vector
-	for(i=0; i < block_size; i++) iblock[i] = 0;
-
-	iblock = blockcipherencryptfn(iblock, key);
-	for(i = 0; i < block_size; i++)
-	{
-		ablock[i] = ciphertext.charCodeAt(i);
-		iblock[i] ^= ablock[i];
 	}
 
-	ablock = blockcipherencryptfn(ablock, key);
-
-	return util.bin2str(iblock)+
-		String.fromCharCode(ablock[0]^ciphertext.charCodeAt(block_size))+
-		String.fromCharCode(ablock[1]^ciphertext.charCodeAt(block_size+1));
-}
-/**
- * This function decrypts a given plaintext using the specified
- * blockcipher to decrypt a message
- * @param blockcipherfn the algorithm _encrypt_ function to encrypt
- *  data in one block_size encryption. The function must be 
- *  specified as blockcipherfn([integer_array(integers 0..255)] 
- *  block,[integer_array(integers 0..255)] key) returning an 
- *  array of bytes (integers 0..255)
- * @param block_size the block size in bytes of the algorithm used
- * @param plaintext ciphertext to be decrypted provided as a string
- * @param key key to be used to decrypt the ciphertext as 
- *  integer_array(integers 0..255)]. This will be passed to the 
- *  blockcipherfn
- * @param resync a boolean value specifying if a resync of the 
- *  IV should be used or not. The encrypteddatapacket uses the 
- *  "old" style with a resync. Decryption within an 
- *  encryptedintegrityprotecteddata packet is not resyncing the IV.
- * @return a string with the plaintext data
- */
-
-function openpgp_cfb_decrypt(blockcipherencryptfn, block_size, key, ciphertext, resync)
-{
-	util.print_debug("resync:"+resync);
-	var iblock = new Array(block_size);
-	var ablock = new Array(block_size);
-	var i, n = '';
-	var text = [];
-
-	// initialisation vector
-	for(i=0; i < block_size; i++) iblock[i] = 0;
-
-	iblock = blockcipherencryptfn(iblock, key);
-	for(i = 0; i < block_size; i++)
-	{
-		ablock[i] = ciphertext.charCodeAt(i);
-		iblock[i] ^= ablock[i];
-	}
-
-	ablock = blockcipherencryptfn(ablock, key);
-
-	util.print_debug("openpgp_cfb_decrypt:\niblock:"+util.hexidump(iblock)+"\nablock:"+util.hexidump(ablock)+"\n");
-	util.print_debug((ablock[0]^ciphertext.charCodeAt(block_size)).toString(16)+(ablock[1]^ciphertext.charCodeAt(block_size+1)).toString(16));
-	
-	// test check octets
-	if(iblock[block_size-2]!=(ablock[0]^ciphertext.charCodeAt(block_size))
-	|| iblock[block_size-1]!=(ablock[1]^ciphertext.charCodeAt(block_size+1)))
-	{
-		util.print_eror("error duding decryption. Symmectric encrypted data not valid.");
-		return text.join('');
-	}
-	
-	/*  RFC4880: Tag 18 and Resync:
-	 *  [...] Unlike the Symmetrically Encrypted Data Packet, no
-   	 *  special CFB resynchronization is done after encrypting this prefix
-     *  data.  See "OpenPGP CFB Mode" below for more details.
-
+	/**
+	 * Writes a packet header Version 3 with the given tag_type and length to a
+	 * string
+	 * 
+	 * @param tag_type
+	 *            integer of tag type
+	 * @param length
+	 *            integer length of the payload
+	 * @return string of the header
 	 */
-	
-	if (resync) {
-	    for(i=0; i<block_size; i++) iblock[i] = ciphertext.charCodeAt(i+2);
-		for(n=block_size+2; n<ciphertext.length; n+=block_size)
-		{
-			ablock = blockcipherencryptfn(iblock, key);
-
-			for(i = 0; i<block_size && i+n < ciphertext.length; i++)
-			{
-				iblock[i] = ciphertext.charCodeAt(n+i);
-				text.push(String.fromCharCode(ablock[i]^iblock[i])); 
-			}
+	function write_old_packet_header(tag_type, length) {
+		var result = "";
+		if (length < 256) {
+			result += String.fromCharCode(0x80 | (tag_type << 2));
+			result += String.fromCharCode(length);
+		} else if (length < 65536) {
+			result += String.fromCharCode(0x80 | (tag_type << 2) | 1);
+			result += String.fromCharCode(length >> 8);
+			result += String.fromCharCode(length & 0xFF);
+		} else {
+			result += String.fromCharCode(0x80 | (tag_type << 2) | 2);
+			result += String.fromCharCode((length >> 24) & 0xFF);
+			result += String.fromCharCode((length >> 16) & 0xFF);
+			result += String.fromCharCode((length >> 8) & 0xFF);
+			result += String.fromCharCode(length & 0xFF);
 		}
-	} else {
-		for(i=0; i<block_size; i++) iblock[i] = ciphertext.charCodeAt(i);
-		for(n=block_size; n<ciphertext.length; n+=block_size)
-		{
-			ablock = blockcipherencryptfn(iblock, key);
-			for(i = 0; i<block_size && i+n < ciphertext.length; i++)
-			{
-				iblock[i] = ciphertext.charCodeAt(n+i);
-				text.push(String.fromCharCode(ablock[i]^iblock[i])); 
-			}
-		}
-		
+		return result;
 	}
-	
-	return text.join('');
-}
-
-
-function normal_cfb_encrypt(blockcipherencryptfn, block_size, key, plaintext, iv) {
-	var blocki ="";
-	var blockc = "";
-	var pos = 0;
-	var cyphertext = [];
-	var tempBlock = [];
-	blockc = iv.substring(0,block_size);
-	while (plaintext.length > block_size*pos) {
-		var encblock = blockcipherencryptfn(blockc, key);
-		blocki = plaintext.substring((pos*block_size),(pos*block_size)+block_size);
-		for (var i=0; i < blocki.length; i++)
-		    tempBlock.push(String.fromCharCode(blocki.charCodeAt(i) ^ encblock[i]));
-		blockc = tempBlock.join('');
-		tempBlock = [];
-		cyphertext.push(blockc);
-		pos++;
-	}
-	return cyphertext.join('');
-}
-
-function normal_cfb_decrypt(blockcipherencryptfn, block_size, key, ciphertext, iv) { 
-	var blockp ="";
-	var pos = 0;
-	var plaintext = [];
-	var offset = 0;
-	if (iv == null)
-		for (var i = 0; i < block_size; i++) blockp += String.fromCharCode(0);
-	else
-		blockp = iv.substring(0,block_size);
-	while (ciphertext.length > (block_size*pos)) {
-		var decblock = blockcipherencryptfn(blockp, key);
-		blockp = ciphertext.substring((pos*(block_size))+offset,(pos*(block_size))+(block_size)+offset);
-		for (var i=0; i < blockp.length; i++) {
-			plaintext.push(String.fromCharCode(blockp.charCodeAt(i) ^ decblock[i]));
-		}
-		pos++;
-	}
-	
-	return plaintext.join('');
-}
-// GPG4Browsers - An OpenPGP implementation in javascript
-// Copyright (C) 2011 Recurity Labs GmbH
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA 
-
-// The GPG4Browsers crypto interface
-
-/**
- * Encrypts data using the specified public key multiprecision integers 
- * and the specified algorithm.
- * @param algo [Integer] Algorithm to be used (See RFC4880 9.1)
- * @param publicMPIs [Array[openpgp_type_mpi]] algorithm dependent multiprecision integers
- * @param data [openpgp_type_mpi] data to be encrypted as MPI
- * @return [Object] if RSA an openpgp_type_mpi; if elgamal encryption an array of two
- * openpgp_type_mpi is returned; otherwise null
- */
-function openpgp_crypto_asymetricEncrypt(algo, publicMPIs, data) {
-	switch(algo) {
-	case 1: // RSA (Encrypt or Sign) [HAC]
-	case 2: // RSA Encrypt-Only [HAC]
-	case 3: // RSA Sign-Only [HAC]
-		var rsa = new RSA();
-		var n = publicMPIs[0].toBigInteger();
-		var e = publicMPIs[1].toBigInteger();
-		var m = data.toBigInteger();
-		return rsa.encrypt(m,e,n).toMPI();
-	case 16: // Elgamal (Encrypt-Only) [ELGAMAL] [HAC]
-		var elgamal = new Elgamal();
-		var p = publicMPIs[0].toBigInteger();
-		var g = publicMPIs[1].toBigInteger();
-		var y = publicMPIs[2].toBigInteger();
-		var m = data.toBigInteger();
-		return elgamal.encrypt(m,g,p,y);
-	default:
-		return null;
-	}
-}
-
-/**
- * Decrypts data using the specified public key multiprecision integers of the private key,
- * the specified secretMPIs of the private key and the specified algorithm.
- * @param algo [Integer] Algorithm to be used (See RFC4880 9.1)
- * @param publicMPIs [Array[openpgp_type_mpi]] algorithm dependent multiprecision integers of the public key part of the private key
- * @param secretMPIs [Array[openpgp_type_mpi]] algorithm dependent multiprecision integers of the private key used
- * @param data [openpgp_type_mpi] data to be encrypted as MPI
- * @return [BigInteger] returns a big integer containing the decrypted data; otherwise null
- */
-
-function openpgp_crypto_asymetricDecrypt(algo, publicMPIs, secretMPIs, dataMPIs) {
-	switch(algo) {
-	case 1: // RSA (Encrypt or Sign) [HAC]  
-	case 2: // RSA Encrypt-Only [HAC]
-	case 3: // RSA Sign-Only [HAC]
-		var rsa = new RSA();
-		var d = secretMPIs[0].toBigInteger();
-		var p = secretMPIs[1].toBigInteger();
-		var q = secretMPIs[2].toBigInteger();
-		var u = secretMPIs[3].toBigInteger();
-		var m = dataMPIs[0].toBigInteger();
-		return rsa.decrypt(m, d, p, q, u);
-	case 16: // Elgamal (Encrypt-Only) [ELGAMAL] [HAC]
-		var elgamal = new Elgamal();
-		var x = secretMPIs[0].toBigInteger();
-		var c1 = dataMPIs[0].toBigInteger();
-		var c2 = dataMPIs[1].toBigInteger();
-		var p = publicMPIs[0].toBigInteger();
-		return elgamal.decrypt(c1,c2,p,x);
-	default:
-		return null;
-	}
-	
-}
-
-/**
- * generate random byte prefix as string for the specified algorithm
- * @param algo [Integer] algorithm to use (see RFC4880 9.2)
- * @return [String] random bytes with length equal to the block
- * size of the cipher
- */
-function openpgp_crypto_getPrefixRandom(algo) {
-	switch(algo) {
-	case 2:
-	case 3:
-	case 4:
-		return openpgp_crypto_getRandomBytes(8);
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-		return openpgp_crypto_getRandomBytes(16);
-	default:
-		return null;
-	}
-}
-
-/**
- * retrieve the MDC prefixed bytes by decrypting them
- * @param algo [Integer] algorithm to use (see RFC4880 9.2)
- * @param key [String] key as string. length is depending on the algorithm used
- * @param data [String] encrypted data where the prefix is decrypted from
- * @return [String] plain text data of the prefixed data
- */
-function openpgp_crypto_MDCSystemBytes(algo, key, data) {
-	util.print_debug_hexstr_dump("openpgp_crypto_symmetricDecrypt:\nencrypteddata:",data);
-	switch(algo) {
-	case 0: // Plaintext or unencrypted data
-		return data;
-	case 2: // TripleDES (DES-EDE, [SCHNEIER] [HAC] - 168 bit key derived from 192)
-		return openpgp_cfb_mdc(desede, 8, key, data, openpgp_cfb);
-	case 3: // CAST5 (128 bit key, as per [RFC2144])
-		return openpgp_cfb_mdc(cast5_encrypt, 8, key, data);
-	case 4: // Blowfish (128 bit key, 16 rounds) [BLOWFISH]
-		return openpgp_cfb_mdc(BFencrypt, 8, key, data);
-	case 7: // AES with 128-bit key [AES]
-	case 8: // AES with 192-bit key
-	case 9: // AES with 256-bit key
-		return openpgp_cfb_mdc(AESencrypt, 16, keyExpansion(key), data);
-	case 10: 
-		return openpgp_cfb_mdc(TFencrypt, 16, key, data);
-	case 1: // IDEA [IDEA]
-		util.print_error(""+ (algo == 1 ? "IDEA Algorithm not implemented" : "Twofish Algorithm not implemented"));
-		return null;
-	default:
-	}
-	return null;
-}
-/**
- * Generating a session key for the specified symmetric algorithm
- * @param algo [Integer] algorithm to use (see RFC4880 9.2)
- * @return [String] random bytes as a string to be used as a key
- */
-function openpgp_crypto_generateSessionKey(algo) {
-	switch (algo) {
-	case 2: // TripleDES (DES-EDE, [SCHNEIER] [HAC] - 168 bit key derived from 192)
-	case 8: // AES with 192-bit key
-		return openpgp_crypto_getRandomBytes(24); 
-	case 3: // CAST5 (128 bit key, as per [RFC2144])
-	case 4: // Blowfish (128 bit key, 16 rounds) [BLOWFISH]
-	case 7: // AES with 128-bit key [AES]
-		util.print_debug("length = 16:\n"+util.hexstrdump(openpgp_crypto_getRandomBytes(16)));
-		return openpgp_crypto_getRandomBytes(16);
-	case 9: // AES with 256-bit key
-	case 10:// Twofish with 256-bit key [TWOFISH]
-		return openpgp_crypto_getRandomBytes(32);
-	}
-	return null;
-}
-
-/**
- * 
- * @param algo [Integer] public key algorithm
- * @param hash_algo [Integer] hash algorithm
- * @param msg_MPIs [Array[openpgp_type_mpi]] signature multiprecision integers
- * @param publickey_MPIs [Array[openpgp_type_mpi]] public key multiprecision integers 
- * @param data [String] data on where the signature was computed on.
- * @return true if signature (sig_data was equal to data over hash)
- */
-function openpgp_crypto_verifySignature(algo, hash_algo, msg_MPIs, publickey_MPIs, data) {
-	var calc_hash = openpgp_crypto_hashData(hash_algo, data);
-	switch(algo) {
-	case 1: // RSA (Encrypt or Sign) [HAC]  
-	case 2: // RSA Encrypt-Only [HAC]
-	case 3: // RSA Sign-Only [HAC]
-		var rsa = new RSA();
-		var n = publickey_MPIs[0].toBigInteger();
-		var e = publickey_MPIs[1].toBigInteger();
-		var x = msg_MPIs[0].toBigInteger();
-		var dopublic = rsa.verify(x,e,n);
-		var hash  = openpgp_encoding_emsa_pkcs1_decode(hash_algo,dopublic.toMPI().substring(2));
-		if (hash == -1) {
-			util.print_error("PKCS1 padding in message or key incorrect. Aborting...");
-			return false;
-		}
-		return hash == calc_hash;
-		
-	case 16: // Elgamal (Encrypt-Only) [ELGAMAL] [HAC]
-		util.print_error("signing with Elgamal is not defined in the OpenPGP standard.");
-		return null;
-	case 17: // DSA (Digital Signature Algorithm) [FIPS186] [HAC]
-		var dsa = new DSA();
-		var s1 = msg_MPIs[0].toBigInteger();
-		var s2 = msg_MPIs[1].toBigInteger();
-		var p = publickey_MPIs[0].toBigInteger();
-		var q = publickey_MPIs[1].toBigInteger();
-		var g = publickey_MPIs[2].toBigInteger();
-		var y = publickey_MPIs[3].toBigInteger();
-		var m = data;
-		var dopublic = dsa.verify(hash_algo,s1,s2,m,p,q,g,y);
-		return dopublic.compareTo(s1) == 0;
-	default:
-		return null;
-	}
-	
-}
-   
-/**
- * Create a signature on data using the specified algorithm
- * @param hash_algo [Integer] hash algorithm to use (See RFC4880 9.4)
- * @param algo [Integer] asymmetric cipher algorithm to use (See RFC4880 9.1)
- * @param publicMPIs [Array[openpgp_type_mpi]] public key multiprecision integers of the private key 
- * @param secretMPIs [Array[openpgp_type_mpi]] private key multiprecision integers which is used to sign the data
- * @param data [String] data to be signed
- * @return [String or openpgp_type_mpi] 
- */
-function openpgp_crypto_signData(hash_algo, algo, publicMPIs, secretMPIs, data) {
-	
-	switch(algo) {
-	case 1: // RSA (Encrypt or Sign) [HAC]  
-	case 2: // RSA Encrypt-Only [HAC]
-	case 3: // RSA Sign-Only [HAC]
-		var rsa = new RSA();
-		var d = secretMPIs[0].toBigInteger();
-		var n = publicMPIs[0].toBigInteger();
-		var m = openpgp_encoding_emsa_pkcs1_encode(hash_algo, data,publicMPIs[0].mpiByteLength);
-		util.print_debug("signing using RSA");
-		return rsa.sign(m, d, n).toMPI();
-	case 17: // DSA (Digital Signature Algorithm) [FIPS186] [HAC]
-		var dsa = new DSA();
-		util.print_debug("DSA Sign: q size in Bytes:"+publicMPIs[1].getByteLength());
-		var p = publicMPIs[0].toBigInteger();
-		var q = publicMPIs[1].toBigInteger();
-		var g = publicMPIs[2].toBigInteger();
-		var y = publicMPIs[3].toBigInteger();
-		var x = secretMPIs[0].toBigInteger();
-		var m = data;
-		var result = dsa.sign(hash_algo,m, g, p, q, x);
-		util.print_debug("signing using DSA\n result:"+util.hexstrdump(result[0])+"|"+util.hexstrdump(result[1]));
-		return result[0]+result[1];
-	case 16: // Elgamal (Encrypt-Only) [ELGAMAL] [HAC]
-			util.print_debug("signing with Elgamal is not defined in the OpenPGP standard.");
+	this.write_old_packet_header = write_old_packet_header;
+	this.write_packet_header = write_packet_header;
+	/**
+	 * Generic static Packet Parser function
+	 * 
+	 * @param input
+	 *            [String] input stream as string
+	 * @param position
+	 *            [integer] position to start parsing
+	 * @param len
+	 *            [integer] length of the input from position on
+	 * @return [openpgp_packet_*] returns a parsed openpgp_packet
+	 */
+	function read_packet(input, position, len) {
+		// some sanity checks
+		if (input == null || input.length <= position
+				|| input.substring(position).length < 2
+				|| (input[position].charCodeAt() & 0x80) == 0) {
+			util
+					.print_error("Error during parsing. This message / key is propably not containing a valid OpenPGP format.");
 			return null;
-	default:
-		return null;
-	}	
-}
+		}
+		var mypos = position;
+		var tag = -1;
+		var format = -1;
 
-/**
- * create a hash on the specified data using the specified algorithm
- * @param algo [Integer] hash algorithm type (see RFC4880 9.4)
- * @param data [String] data to be hashed
- * @return [String] hash value
- */
-function openpgp_crypto_hashData(algo, data) {
-	var hash = null;
-	switch(algo) {
-	case 1: // - MD5 [HAC]
-		hash = MD5(data);
-		break;
-	case 2: // - SHA-1 [FIPS180]
-		hash = str_sha1(data);
-		break;
-	case 3: // - RIPE-MD/160 [HAC]
-		hash = RMDstring(data);
-		break;
-	case 8: // - SHA256 [FIPS180]
-		hash = str_sha256(data);
-		break;
-	case 9: // - SHA384 [FIPS180]
-		hash = str_sha384(data);
-		break;
-	case 10:// - SHA512 [FIPS180]
-		hash = str_sha512(data);
-		break;
-	case 11:// - SHA224 [FIPS180]
-		hash = str_sha224(data);
-	default:
-		break;
-	}
-	return hash;
-}
+		format = 0; // 0 = old format; 1 = new format
+		if ((input[mypos].charCodeAt() & 0x40) != 0) {
+			format = 1;
+		}
 
-/**
- * returns the hash size in bytes of the specified hash algorithm type
- * @param algo [Integer] hash algorithm type (See RFC4880 9.4)
- * @return [Integer] size in bytes of the resulting hash
- */
-function openpgp_crypto_getHashByteLength(algo) {
-	var hash = null;
-	switch(algo) {
-	case 1: // - MD5 [HAC]
-		return 16;
-	case 2: // - SHA-1 [FIPS180]
-	case 3: // - RIPE-MD/160 [HAC]
-		return 20;
-	case 8: // - SHA256 [FIPS180]
-		return 32;
-	case 9: // - SHA384 [FIPS180]
-		return 48
-	case 10:// - SHA512 [FIPS180]
-		return 64;
-	case 11:// - SHA224 [FIPS180]
-		return 28;
-	}
-	return null;
-}
+		var packet_length_type;
+		if (format) {
+			// new format header
+			tag = input[mypos].charCodeAt() & 0x3F; // bit 5-0
+		} else {
+			// old format header
+			tag = (input[mypos].charCodeAt() & 0x3F) >> 2; // bit 5-2
+			packet_length_type = input[mypos].charCodeAt() & 0x03; // bit 1-0
+		}
 
-/**
- * retrieve secure random byte string of the specified length
- * @param length [Integer] length in bytes to generate
- * @return [String] random byte string
- */
-function openpgp_crypto_getRandomBytes(length) {
-	var result = '';
-	for (var i = 0; i < length; i++) {
-		result += String.fromCharCode(openpgp_crypto_getSecureRandomOctet());
-	}
-	return result;
-}
+		// header octet parsing done
+		mypos++;
 
-/**
- * return a pseudo-random number in the specified range
- * @param from [Integer] min of the random number
- * @param to [Integer] max of the random number (max 32bit)
- * @return [Integer] a pseudo random number
- */
-function openpgp_crypto_getPseudoRandom(from, to) {
-	return Math.round(Math.random()*(to-from))+from;
-}
+		// parsed length from length field
+		var len = 0;
+		var bodydata = null;
 
-/**
- * return a secure random number in the specified range
- * @param from [Integer] min of the random number
- * @param to [Integer] max of the random number (max 32bit)
- * @return [Integer] a secure random number
- */
-function openpgp_crypto_getSecureRandom(from, to) {
-	var buf = new Uint32Array(1);
-	window.crypto.getRandomValues(buf);
-	var bits = ((to-from)).toString(2).length;
-	while ((buf[0] & (Math.pow(2, bits) -1)) > (to-from))
-		window.crypto.getRandomValues(buf);
-	return from+(Math.abs(buf[0] & (Math.pow(2, bits) -1)));
-}
-
-function openpgp_crypto_getSecureRandomOctet() {
-	var buf = new Uint32Array(1);
-	window.crypto.getRandomValues(buf);
-	return buf[0] & 0xFF;
-}
-
-/**
- * create a secure random big integer of bits length
- * @param bits [Integer] bit length of the MPI to create
- * @return [BigInteger] resulting big integer
- */
-function openpgp_crypto_getRandomBigInteger(bits) {
-	if (bits < 0)
-	   return null;
-	var numBytes = Math.floor((bits+7)/8);
-
-	var randomBits = openpgp_crypto_getRandomBytes(numBytes);
-	if (bits % 8 > 0) {
-		
-		randomBits = String.fromCharCode(
-						(Math.pow(2,bits % 8)-1) &
-						randomBits.charCodeAt(0)) +
-			randomBits.substring(1);
-	}
-	return new openpgp_type_mpi().create(randomBits).toBigInteger();
-}
-
-function openpgp_crypto_getRandomBigIntegerInRange(min, max) {
-	if (max.compareTo(min) <= 0)
-		return;
-	var range = max.subtract(min);
-	var r = openpgp_crypto_getRandomBigInteger(range.bitLength());
-	while (r > range) {
-		r = openpgp_crypto_getRandomBigInteger(range.bitLength());
-	}
-	return min.add(r);
-}
-
-
-//This is a test method to ensure that encryption/decryption with a given 1024bit RSAKey object functions as intended
-function openpgp_crypto_testRSA(key){
-	debugger;
-    var rsa = new RSA();
-	var mpi = new openpgp_type_mpi();
-	mpi.create(openpgp_encoding_eme_pkcs1_encode('ABABABAB', 128));
-	var msg = rsa.encrypt(mpi.toBigInteger(),key.ee,key.n);
-	var result = rsa.decrypt(msg, key.d, key.p, key.q, key.u);
-}
-/**
- * calls the necessary crypto functions to generate a keypair. Called directly by openpgp.js
- * @keyType [int] follows OpenPGP algorithm convention.
- * @numBits [int] number of bits to make the key to be generated
- * @return {privateKey: [openpgp_packet_keymaterial] , publicKey: [openpgp_packet_keymaterial]}
- */
-function openpgp_crypto_generateKeyPair(keyType, numBits, passphrase, s2kHash, symmetricEncryptionAlgorithm){
-	var privKeyPacket;
-	var publicKeyPacket;
-	var d = new Date();
-	d = d.getTime()/1000;
-	var timePacket = String.fromCharCode(Math.floor(d/0x1000000%0x100)) + String.fromCharCode(Math.floor(d/0x10000%0x100)) + String.fromCharCode(Math.floor(d/0x100%0x100)) + String.fromCharCode(Math.floor(d%0x100));
-	switch(keyType){
-	case 1:
-	    var rsa = new RSA();
-	    var key = rsa.generate(numBits,"10001");
-	    privKeyPacket = new openpgp_packet_keymaterial().write_private_key(keyType, key, passphrase, s2kHash, symmetricEncryptionAlgorithm, timePacket);
-	    publicKeyPacket =  new openpgp_packet_keymaterial().write_public_key(keyType, key, timePacket);
-	    break;
-	default:
-		util.print_error("Unknown keytype "+keyType)
-	}
-	return {privateKey: privKeyPacket, publicKey: publicKeyPacket};
-}
-// GPG4Browsers - An OpenPGP implementation in javascript
-// Copyright (C) 2011 Recurity Labs GmbH
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-/**
- * GPG4Browsers Core interface. A single instance is hold
- * from the beginning. To use this library call "openpgp.init()"
- * @alias openpgp
- * @class
- * @classdesc Main Openpgp.js class. Use this to initiate and make all calls to this library.
- */
-function _openpgp () {
-	this.tostring = "";
-	
-	/**
-	 * initializes the library:
-	 * - reading the keyring from local storage
-	 * - reading the config from local storage
-	 * @return [void]
-	 */
-	function init() {
-		this.config = new openpgp_config();
-		this.config.read();
-		this.keyring = new openpgp_keyring();
-		this.keyring.init();
-	}
-	
-	/**
-	 * reads several publicKey objects from a ascii armored
-	 * representation an returns openpgp_msg_publickey packets
-	 * @param {String} armoredText OpenPGP armored text containing
-	 * the public key(s)
-	 * @return {Array[openpgp_msg_publickey]} on error the function
-	 * returns null
-	 */
-	function read_publicKey(armoredText) {
-		var mypos = 0;
-		var publicKeys = new Array();
-		var publicKeyCount = 0;
-		var input = openpgp_encoding_deArmor(armoredText.replace(/\r/g,'')).openpgp;
-		var l = input.length;
-		while (mypos != input.length) {
-			var first_packet = openpgp_packet.read_packet(input, mypos, l);
-			// public key parser
-			if (input[mypos].charCodeAt() == 0x99 || first_packet.tagType == 6) {
-				publicKeys[publicKeyCount] = new openpgp_msg_publickey();				
-				publicKeys[publicKeyCount].header = input.substring(mypos,mypos+3);
-				if (input[mypos].charCodeAt() == 0x99) {
-					// parse the length and read a tag6 packet
-					mypos++;
-					var l = (input[mypos++].charCodeAt() << 8)
-							| input[mypos++].charCodeAt();
-					publicKeys[publicKeyCount].publicKeyPacket = new openpgp_packet_keymaterial();
-					publicKeys[publicKeyCount].publicKeyPacket.header = publicKeys[publicKeyCount].header;
-					publicKeys[publicKeyCount].publicKeyPacket.read_tag6(input, mypos, l);
-					mypos += publicKeys[publicKeyCount].publicKeyPacket.packetLength;
-					mypos += publicKeys[publicKeyCount].read_nodes(publicKeys[publicKeyCount].publicKeyPacket, input, mypos, (input.length - mypos));
-				} else {
-					publicKeys[publicKeyCount] = new openpgp_msg_publickey();
-					publicKeys[publicKeyCount].publicKeyPacket = first_packet;
-					mypos += first_packet.headerLength+first_packet.packetLength;
-					mypos += publicKeys[publicKeyCount].read_nodes(first_packet, input, mypos, input.length -mypos);
-				}
-			} else {
-				util.print_error("no public key found!");
-				return null;
+		// used for partial body lengths
+		var real_packet_length = -1;
+		if (!format) {
+			// 4.2.1. Old Format Packet Lengths
+			switch (packet_length_type) {
+			case 0: // The packet has a one-octet length. The header is 2 octets
+				// long.
+				packet_length = input[mypos++].charCodeAt();
+				break;
+			case 1: // The packet has a two-octet length. The header is 3 octets
+				// long.
+				packet_length = (input[mypos++].charCodeAt() << 8)
+						| input[mypos++].charCodeAt();
+				break;
+			case 2: // The packet has a four-octet length. The header is 5
+				// octets long.
+				packet_length = (input[mypos++].charCodeAt() << 24)
+						| (input[mypos++].charCodeAt() << 16)
+						| (input[mypos++].charCodeAt() << 8)
+						| input[mypos++].charCodeAt();
+				break;
+			default:
+				// 3 - The packet is of indeterminate length. The header is 1
+				// octet long, and the implementation must determine how long
+				// the packet is. If the packet is in a file, this means that
+				// the packet extends until the end of the file. In general, 
+				// an implementation SHOULD NOT use indeterminate-length 
+				// packets except where the end of the data will be clear 
+				// from the context, and even then it is better to use a 
+				// definite length, or a new format header. The new format 
+				// headers described below have a mechanism for precisely
+				// encoding data of indeterminate length.
 			}
-			publicKeys[publicKeyCount].data = input.substring(0,mypos);
-			publicKeyCount++;
-		}
-		return publicKeys;
-	}
-	
-	/**
-	 * reads several privateKey objects from a ascii armored
-	 * representation an returns openpgp_msg_privatekey objects
-	 * @param {String} armoredText OpenPGP armored text containing
-	 * the private key(s)
-	 * @return {Array[openpgp_msg_privatekey]} on error the function
-	 * returns null
-	 */
-	function read_privateKey(armoredText) {
-		var privateKeys = new Array();
-		var privateKeyCount = 0;
-		var mypos = 0;
-		var input = openpgp_encoding_deArmor(armoredText.replace(/\r/g,'')).openpgp;
-		var l = input.length;
-		while (mypos != input.length) {
-			var first_packet = openpgp_packet.read_packet(input, mypos, l);
-			if (first_packet.tagType == 5) {
-				privateKeys[privateKeys.length] = new openpgp_msg_privatekey();
-				mypos += first_packet.headerLength+first_packet.packetLength;
-				mypos += privateKeys[privateKeyCount].read_nodes(first_packet, input, mypos, l);
-			// other blocks	            
-			} else {
-				util.print_error('no block packet found!');
-				return null;
-			}
-			privateKeys[privateKeyCount].data = input.substring(0,mypos);
-			privateKeyCount++;
-		}
-		return privateKeys;		
-	}
 
-	/**
-	 * reads message packets out of an OpenPGP armored text and
-	 * returns an array of message objects
-	 * @param {String} armoredText text to be parsed
-	 * @return {Array[openpgp_msg_message]} on error the function
-	 * returns null
-	 */
-	function read_message(armoredText) {
-		var dearmored;
-		try{
-    		dearmored = openpgp_encoding_deArmor(armoredText.replace(/\r/g,''));
-		}
-		catch(e){
-    		util.print_error('no message found!');
-    		return null;
-		}
-		var input = dearmored.openpgp;
-		var messages = new Array();
-		var messageCount = 0;
-		var mypos = 0;
-		var l = input.length;
-		while (mypos < input.length) {
-			var first_packet = openpgp_packet.read_packet(input, mypos, l);
-			// public key parser (definition from the standard:)
-			// OpenPGP Message      :- Encrypted Message | Signed Message |
-			//                         Compressed Message | Literal Message.
-			// Compressed Message   :- Compressed Data Packet.
-			// 
-			// Literal Message      :- Literal Data Packet.
-			// 
-			// ESK                  :- Public-Key Encrypted Session Key Packet |
-			//                         Symmetric-Key Encrypted Session Key Packet.
-			// 
-			// ESK Sequence         :- ESK | ESK Sequence, ESK.
-			// 
-			// Encrypted Data       :- Symmetrically Encrypted Data Packet |
-			//                         Symmetrically Encrypted Integrity Protected Data Packet
-			// 
-			// Encrypted Message    :- Encrypted Data | ESK Sequence, Encrypted Data.
-			// 
-			// One-Pass Signed Message :- One-Pass Signature Packet,
-			//                         OpenPGP Message, Corresponding Signature Packet.
+		} else // 4.2.2. New Format Packet Lengths
+		{
 
-			// Signed Message       :- Signature Packet, OpenPGP Message |
-			//                         One-Pass Signed Message.
-			if (first_packet.tagType ==  1 ||
-			    (first_packet.tagType == 2 && first_packet.signatureType < 16) ||
-			     first_packet.tagType ==  3 ||
-				 first_packet.tagType ==  8 ||
-				 first_packet.tagType ==  9 ||
-				 first_packet.tagType == 10 ||
-				 first_packet.tagType == 11 ||
-				 first_packet.tagType == 18 ||
-				 first_packet.tagType == 19) {
-				messages[messages.length] = new openpgp_msg_message();
-				messages[messageCount].messagePacket = first_packet;
-				messages[messageCount].type = dearmored.type;
-				// Encrypted Message
-				if (first_packet.tagType == 9 ||
-				    first_packet.tagType == 1 ||
-				    first_packet.tagType == 3 ||
-				    first_packet.tagType == 18) {
-					if (first_packet.tagType == 9) {
-						util.print_error("unexpected openpgp packet");
+			// 4.2.2.1. One-Octet Lengths
+			if (input[mypos].charCodeAt() < 192) {
+				packet_length = input[mypos++].charCodeAt();
+				util.print_debug("1 byte length:" + packet_length);
+				// 4.2.2.2. Two-Octet Lengths
+			} else if (input[mypos].charCodeAt() >= 192
+					&& input[mypos].charCodeAt() < 224) {
+				packet_length = ((input[mypos++].charCodeAt() - 192) << 8)
+						+ (input[mypos++].charCodeAt()) + 192;
+				util.print_debug("2 byte length:" + packet_length);
+				// 4.2.2.4. Partial Body Lengths
+			} else if (input[mypos].charCodeAt() > 223
+					&& input[mypos].charCodeAt() < 255) {
+				packet_length = 1 << (input[mypos++].charCodeAt() & 0x1F);
+				util.print_debug("4 byte length:" + packet_length);
+				// EEEK, we're reading the full data here...
+				var mypos2 = mypos + packet_length;
+				bodydata = input.substring(mypos, mypos + packet_length);
+				while (true) {
+					if (input[mypos2].charCodeAt() < 192) {
+						var tmplen = input[mypos2++].charCodeAt();
+						packet_length += tmplen;
+						bodydata += input.substring(mypos2, mypos2 + tmplen);
+						mypos2 += tmplen;
 						break;
-					} else if (first_packet.tagType == 1) {
-						util.print_debug("session key found:\n "+first_packet.toString());
-						var issessionkey = true;
-						messages[messageCount].sessionKeys = new Array();
-						var sessionKeyCount = 0;
-						while (issessionkey) {
-							messages[messageCount].sessionKeys[sessionKeyCount] = first_packet;
-							mypos += first_packet.packetLength + first_packet.headerLength;
-							l -= (first_packet.packetLength + first_packet.headerLength);
-							first_packet = openpgp_packet.read_packet(input, mypos, l);
-							
-							if (first_packet.tagType != 1 && first_packet.tagType != 3)
-								issessionkey = false;
-							sessionKeyCount++;
-						}
-						if (first_packet.tagType == 18 || first_packet.tagType == 9) {
-							util.print_debug("encrypted data found:\n "+first_packet.toString());
-							messages[messageCount].encryptedData = first_packet;
-							mypos += first_packet.packetLength+first_packet.headerLength;
-							l -= (first_packet.packetLength+first_packet.headerLength);
-							messageCount++;
-							
-						} else {
-							util.print_debug("something is wrong: "+first_packet.tagType);
-						}
-						
-					} else if (first_packet.tagType == 18) {
-						util.print_debug("symmetric encrypted data");
+					} else if (input[mypos2].charCodeAt() >= 192
+							&& input[mypos2].charCodeAt() < 224) {
+						var tmplen = ((input[mypos2++].charCodeAt() - 192) << 8)
+								+ (input[mypos2++].charCodeAt()) + 192;
+						packet_length += tmplen;
+						bodydata += input.substring(mypos2, mypos2 + tmplen);
+						mypos2 += tmplen;
+						break;
+					} else if (input[mypos2].charCodeAt() > 223
+							&& input[mypos2].charCodeAt() < 255) {
+						var tmplen = 1 << (input[mypos2++].charCodeAt() & 0x1F);
+						packet_length += tmplen;
+						bodydata += input.substring(mypos2, mypos2 + tmplen);
+						mypos2 += tmplen;
+					} else {
+						mypos2++;
+						var tmplen = (input[mypos2++].charCodeAt() << 24)
+								| (input[mypos2++].charCodeAt() << 16)
+								| (input[mypos2++].charCodeAt() << 8)
+								| input[mypos2++].charCodeAt();
+						bodydata += input.substring(mypos2, mypos2 + tmplen);
+						packet_length += tmplen;
+						mypos2 += tmplen;
 						break;
 					}
-				} else 
-					// Signed Message
-					if (first_packet.tagType == 2 && first_packet.signatureType < 3) {
-						messages[messageCount].text = dearmored.text;
-						messages[messageCount].signature = first_packet;
-						break;
-				} else 
-					// Compressed Message
-					// TODO: needs to be implemented. From a security perspective: this message is plaintext anyway.
-					if (first_packet.tagType == 8) {
-						util.print_error("A directly compressed message is currently not supported");
-						break;
-				} else
-					// Marker Packet (Obsolete Literal Packet) (Tag 10)
-					// "Such a packet MUST be ignored when received." see http://tools.ietf.org/html/rfc4880#section-5.8
-					if (first_packet.tagType == 10) {
-						// reset messages
-						messages.length = 0;
-						// continue with next packet
-						mypos += first_packet.packetLength + first_packet.headerLength;
-						l -= (first_packet.packetLength + first_packet.headerLength);
-				} else
-					// Literal Message
-					// TODO: needs to be implemented. From a security perspective: this message is plaintext anyway.
-					if (first_packet.tagType == 11) {
-						util.print_error("A direct literal message is currently not supported.");
-						break;
 				}
+				real_packet_length = mypos2;
+				// 4.2.2.3. Five-Octet Lengths
 			} else {
-				util.print_error('no message found!');
-				return null;
+				mypos++;
+				packet_length = (input[mypos++].charCodeAt() << 24)
+						| (input[mypos++].charCodeAt() << 16)
+						| (input[mypos++].charCodeAt() << 8)
+						| input[mypos++].charCodeAt();
 			}
 		}
-		
-		return messages;
-	}
-	
-	/**
-	 * creates a binary string representation of an encrypted and signed message.
-	 * The message will be encrypted with the public keys specified and signed
-	 * with the specified private key.
-	 * @param {obj: [openpgp_msg_privatekey]} privatekey private key to be used to sign the message
-	 * @param {Array {obj: [openpgp_msg_publickey]}} publickeys  public keys to be used to encrypt the message 
-	 * @param {String} messagetext message text to encrypt and sign
-	 * @return {String} a binary string representation of the message which can be OpenPGP armored
-	 */
-	function write_signed_and_encrypted_message(privatekey, publickeys, messagetext) {
-		var result = "";
-		var literal = new openpgp_packet_literaldata().write_packet(messagetext.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"));
-		util.print_debug_hexstr_dump("literal_packet: |"+literal+"|\n",literal);
-		for (var i = 0; i < publickeys.length; i++) {
-			var onepasssignature = new openpgp_packet_onepasssignature();
-			var onepasssigstr = "";
-			if (i == 0)
-				onepasssigstr = onepasssignature.write_packet(1, openpgp.config.config.prefer_hash_algorithm,  privatekey, false);
-			else
-				onepasssigstr = onepasssignature.write_packet(1, openpgp.config.config.prefer_hash_algorithm,  privatekey, false);
-			util.print_debug_hexstr_dump("onepasssigstr: |"+onepasssigstr+"|\n",onepasssigstr);
-			var datasignature = new openpgp_packet_signature().write_message_signature(1, messagetext.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"), privatekey);
-			util.print_debug_hexstr_dump("datasignature: |"+datasignature.openpgp+"|\n",datasignature.openpgp);
-			if (i == 0) {
-				result = onepasssigstr+literal+datasignature.openpgp;
-			} else {
-				result = onepasssigstr+result+datasignature.openpgp;
-			}
-		}
-		
-		util.print_debug_hexstr_dump("signed packet: |"+result+"|\n",result);
-		// signatures done.. now encryption
-		var sessionkey = openpgp_crypto_generateSessionKey(openpgp.config.config.encryption_cipher); 
-		var result2 = "";
-		
-		// creating session keys for each recipient
-		for (var i = 0; i < publickeys.length; i++) {
-			var pkey = publickeys[i].getEncryptionKey();
-			if (pkey == null) {
-				util.print_error("no encryption key found! Key is for signing only.");
-				return null;
-			}
-			result2 += new openpgp_packet_encryptedsessionkey().
-					write_pub_key_packet(
-						pkey.getKeyId(),
-						pkey.MPIs,
-						pkey.publicKeyAlgorithm,
-						openpgp.config.config.encryption_cipher,
-						sessionkey);
-		}
-		if (openpgp.config.config.integrity_protect) {
-			result2 += new openpgp_packet_encryptedintegrityprotecteddata().write_packet(openpgp.config.config.encryption_cipher, sessionkey, result);
-		} else {
-			result2 += new openpgp_packet_encrypteddata().write_packet(openpgp.config.config.encryption_cipher, sessionkey, result);
-		}
-		return openpgp_encoding_armor(3,result2,null,null);
-	}
-	/**
-	 * creates a binary string representation of an encrypted message.
-	 * The message will be encrypted with the public keys specified 
-	 * @param {Array {obj: [openpgp_msg_publickey]}} publickeys public
-	 * keys to be used to encrypt the message 
-	 * @param {String} messagetext message text to encrypt
-	 * @return {String} a binary string representation of the message
-	 * which can be OpenPGP armored
-	 */
-	function write_encrypted_message(publickeys, messagetext) {
-		var result = "";
-		var literal = new openpgp_packet_literaldata().write_packet(messagetext.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"));
-		util.print_debug_hexstr_dump("literal_packet: |"+literal+"|\n",literal);
-		result = literal;
-		
-		// signatures done.. now encryption
-		var sessionkey = openpgp_crypto_generateSessionKey(openpgp.config.config.encryption_cipher); 
-		var result2 = "";
-		
-		// creating session keys for each recipient
-		for (var i = 0; i < publickeys.length; i++) {
-			var pkey = publickeys[i].getEncryptionKey();
-			if (pkey == null) {
-				util.print_error("no encryption key found! Key is for signing only.");
-				return null;
-			}
-			result2 += new openpgp_packet_encryptedsessionkey().
-					write_pub_key_packet(
-						pkey.getKeyId(),
-						pkey.MPIs,
-						pkey.publicKeyAlgorithm,
-						openpgp.config.config.encryption_cipher,
-						sessionkey);
-		}
-		if (openpgp.config.config.integrity_protect) {
-			result2 += new openpgp_packet_encryptedintegrityprotecteddata().write_packet(openpgp.config.config.encryption_cipher, sessionkey, result);
-		} else {
-			result2 += new openpgp_packet_encrypteddata().write_packet(openpgp.config.config.encryption_cipher, sessionkey, result);
-		}
-		return openpgp_encoding_armor(3,result2,null,null);
-	}
-	
-	/**
-	 * creates a binary string representation a signed message.
-	 * The message will be signed with the specified private key.
-	 * @param {obj: [openpgp_msg_privatekey]} privatekey private
-	 * key to be used to sign the message 
-	 * @param {String} messagetext message text to sign
-	 * @return {Object: text [String]}, openpgp: {String} a binary
-	 *  string representation of the message which can be OpenPGP
-	 *   armored(openpgp) and a text representation of the message (text). This can be directly used to OpenPGP armor the message
-	 */
-	function write_signed_message(privatekey, messagetext) {
-		var sig = new openpgp_packet_signature().write_message_signature(1, messagetext.replace(/\r\n/g,"\n").replace(/\n/,"\r\n"), privatekey);
-		var result = {text: messagetext.replace(/\r\n/g,"\n").replace(/\n/,"\r\n"), openpgp: sig.openpgp, hash: sig.hash};
-		return openpgp_encoding_armor(2,result, null, null)
-	}
-	
-	/**
-	 * generates a new key pair for openpgp. Beta stage. Currently only supports RSA keys, and no subkeys.
-	 * @param {int} keyType to indicate what type of key to make. RSA is 1. Follows algorithms outlined in OpenPGP.
-	 * @param {int} numBits number of bits for the key creation. (should be 1024+, generally)
-	 * @param {string} userId assumes already in form of "User Name <username@email.com>"
-	 * @return {privateKey: [openpgp_msg_privatekey], privateKeyArmored: [string], publicKeyArmored: [string]}
-	 */
-	function generate_key_pair(keyType, numBits, userId, passphrase){
-		var userIdPacket = new openpgp_packet_userid();
-		var userIdString = userIdPacket.write_packet(userId);
-		
-		var keyPair = openpgp_crypto_generateKeyPair(keyType,numBits, passphrase, openpgp.config.config.prefer_hash_algorithm, 3);
-		var privKeyString = keyPair.privateKey;
-		var privKeyPacket = new openpgp_packet_keymaterial().read_priv_key(privKeyString.string,3,privKeyString.string.length);
-		if(!privKeyPacket.decryptSecretMPIs(passphrase))
-		    util.print_error('Issue creating key. Unable to read resulting private key');
-		var privKey = new openpgp_msg_privatekey();
-		privKey.privateKeyPacket = privKeyPacket;
-		privKey.getPreferredSignatureHashAlgorithm = function(){return openpgp.config.config.prefer_hash_algorithm};//need to override this to solve catch 22 to generate signature. 8 is value for SHA256
-		
-		var publicKeyString = privKey.privateKeyPacket.publicKey.data;
-		var hashData = String.fromCharCode(0x99)+ String.fromCharCode(((publicKeyString.length) >> 8) & 0xFF) 
-			+ String.fromCharCode((publicKeyString.length) & 0xFF) +publicKeyString+String.fromCharCode(0xB4) +
-			String.fromCharCode((userId.length) >> 24) +String.fromCharCode(((userId.length) >> 16) & 0xFF) 
-			+ String.fromCharCode(((userId.length) >> 8) & 0xFF) + String.fromCharCode((userId.length) & 0xFF) + userId
-		var signature = new openpgp_packet_signature();
-		signature = signature.write_message_signature(16,hashData, privKey);
-		var publicArmored = openpgp_encoding_armor(4, keyPair.publicKey.string + userIdString + signature.openpgp );
 
-		var privArmored = openpgp_encoding_armor(5,privKeyString.string+userIdString+signature.openpgp);
-		
-		return {privateKey : privKey, privateKeyArmored: privArmored, publicKeyArmored: publicArmored}
+		// if there was'nt a partial body length: use the specified
+		// packet_length
+		if (real_packet_length == -1) {
+			real_packet_length = packet_length;
+		}
+
+		if (bodydata == null) {
+			bodydata = input.substring(mypos, mypos + real_packet_length);
+		}
+
+		// alert('tag type: '+this.tag+' length: '+packet_length);
+		var version = 1; // (old format; 2= new format)
+		// if (input[mypos++].charCodeAt() > 15)
+		// version = 2;
+
+		switch (tag) {
+		case 0: // Reserved - a packet tag MUST NOT have this value
+			break;
+		case 1: // Public-Key Encrypted Session Key Packet
+			var result = new openpgp_packet_encryptedsessionkey();
+			if (result.read_pub_key_packet(bodydata, 0, packet_length) != null) {
+				result.headerLength = mypos - position;
+				result.packetLength = real_packet_length;
+				return result;
+			}
+			break;
+		case 2: // Signature Packet
+			var result = new openpgp_packet_signature();
+			if (result.read_packet(bodydata, 0, packet_length) != null) {
+				result.headerLength = mypos - position;
+				result.packetLength = real_packet_length;
+				return result;
+			}
+			break;
+		case 3: // Symmetric-Key Encrypted Session Key Packet
+			var result = new openpgp_packet_encryptedsessionkey();
+			if (result.read_symmetric_key_packet(bodydata, 0, packet_length) != null) {
+				result.headerLength = mypos - position;
+				result.packetLength = real_packet_length;
+				return result;
+			}
+			break;
+		case 4: // One-Pass Signature Packet
+			var result = new openpgp_packet_onepasssignature();
+			if (result.read_packet(bodydata, 0, packet_length)) {
+				result.headerLength = mypos - position;
+				result.packetLength = real_packet_length;
+				return result;
+			}
+			break;
+		case 5: // Secret-Key Packet
+			var result = new openpgp_packet_keymaterial();
+			result.header = input.substring(position, mypos);
+			if (result.read_tag5(bodydata, 0, packet_length) != null) {
+				result.headerLength = mypos - position;
+				result.packetLength = real_packet_length;
+				return result;
+			}
+			break;
+		case 6: // Public-Key Packet
+			var result = new openpgp_packet_keymaterial();
+			result.header = input.substring(position, mypos);
+			if (result.read_tag6(bodydata, 0, packet_length) != null) {
+				result.headerLength = mypos - position;
+				result.packetLength = real_packet_length;
+				return result;
+			}
+			break;
+		case 7: // Secret-Subkey Packet
+			var result = new openpgp_packet_keymaterial();
+			if (result.read_tag7(bodydata, 0, packet_length) != null) {
+				result.headerLength = mypos - position;
+				result.packetLength = real_packet_length;
+				return result;
+			}
+			break;
+		case 8: // Compressed Data Packet
+			var result = new openpgp_packet_compressed();
+			if (result.read_packet(bodydata, 0, packet_length) != null) {
+				result.headerLength = mypos - position;
+				result.packetLength = real_packet_length;
+				return result;
+			}
+			break;
+		case 9: // Symmetrically Encrypted Data Packet
+			var result = new openpgp_packet_encrypteddata();
+			if (result.read_packet(bodydata, 0, packet_length) != null) {
+				result.headerLength = mypos - position;
+				result.packetLength = real_packet_length;
+				return result;
+			}
+			break;
+		case 10: // Marker Packet = PGP (0x50, 0x47, 0x50)
+			var result = new openpgp_packet_marker();
+			if (result.read_packet(bodydata, 0, packet_length) != null) {
+				result.headerLength = mypos - position;
+				result.packetLength = real_packet_length;
+				return result;
+			}
+			break;
+		case 11: // Literal Data Packet
+			var result = new openpgp_packet_literaldata();
+			if (result.read_packet(bodydata, 0, packet_length) != null) {
+				result.headerLength = mypos - position;
+				result.header = input.substring(position, mypos);
+				result.packetLength = real_packet_length;
+				return result;
+			}
+			break;
+		case 12: // Trust Packet
+			// TODO: to be implemented
+			break;
+		case 13: // User ID Packet
+			var result = new openpgp_packet_userid();
+			if (result.read_packet(bodydata, 0, packet_length) != null) {
+				result.headerLength = mypos - position;
+				result.packetLength = real_packet_length;
+				return result;
+			}
+			break;
+		case 14: // Public-Subkey Packet
+			var result = new openpgp_packet_keymaterial();
+			result.header = input.substring(position, mypos);
+			if (result.read_tag14(bodydata, 0, packet_length) != null) {
+				result.headerLength = mypos - position;
+				result.packetLength = real_packet_length;
+				return result;
+			}
+			break;
+		case 17: // User Attribute Packet
+			var result = new openpgp_packet_userattribute();
+			if (result.read_packet(bodydata, 0, packet_length) != null) {
+				result.headerLength = mypos - position;
+				result.packetLength = real_packet_length;
+				return result;
+			}
+			break;
+		case 18: // Sym. Encrypted and Integrity Protected Data Packet
+			var result = new openpgp_packet_encryptedintegrityprotecteddata();
+			if (result.read_packet(bodydata, 0, packet_length) != null) {
+				result.headerLength = mypos - position;
+				result.packetLength = real_packet_length;
+				return result;
+			}
+			break;
+		case 19: // Modification Detection Code Packet
+			var result = new openpgp_packet_modificationdetectioncode();
+			if (result.read_packet(bodydata, 0, packet_length) != null) {
+				result.headerLength = mypos - position;
+				result.packetLength = real_packet_length;
+				return result;
+			}
+			break;
+		default:
+			util.print_error("openpgp.packet.js\n"
+					+ "[ERROR] openpgp_packet: failed to parse packet @:"
+					+ mypos + "\nchar:'"
+					+ util.hexstrdump(input.substring(mypos)) + "'\ninput:"
+					+ util.hexstrdump(input));
+			return null;
+			break;
+		}
 	}
-	
-	this.generate_key_pair = generate_key_pair;
-	this.write_signed_message = write_signed_message; 
-	this.write_signed_and_encrypted_message = write_signed_and_encrypted_message;
-	this.write_encrypted_message = write_encrypted_message;
-	this.read_message = read_message;
-	this.read_publicKey = read_publicKey;
-	this.read_privateKey = read_privateKey;
-	this.init = init;
+
+	this.read_packet = read_packet;
 }
 
-var openpgp = new _openpgp();
-
-
+var openpgp_packet = new _openpgp_packet();
 // GPG4Browsers - An OpenPGP implementation in javascript
 // Copyright (C) 2011 Recurity Labs GmbH
 // 
@@ -9978,243 +3025,864 @@ var openpgp = new _openpgp();
 // License along with this library; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
-function openpgp_msg_publickey() {
-	this.data;
-	this.position;
-	this.len;
-	this.tostring = "OPENPGP PUBLIC KEY\n";
-	this.bindingSignature = null;
-	this.publicKeyPacket = null;
-	this.userIds = new Array();
-	this.userAttributes = new Array();
-	this.revocationSignatures = new Array();
-	this.subKeys = new Array();
-	this.arbitraryPacket = new Array();
-	this.directSignatures = new Array();
+/**
+ * Implementation of the Literal Data Packet (Tag 11)
+ * 
+ * RFC4880 5.9: A Literal Data packet contains the body of a message; data that
+ * is not to be further interpreted.
+ */
+function openpgp_packet_literaldata() {
+	this.tagType = 11;
+
 	/**
+	 * parsing function for a literal data packet (tag 11).
 	 * 
-	 * @return last position
+	 * @param input
+	 *            [string] payload of a tag 11 packet
+	 * @param position
+	 *            [integer] position to start reading from the input string
+	 * @param len
+	 *            [integer] length of the packet or the remaining length of
+	 *            input at position
+	 * @return [openpgp_packet_encrypteddata] object representation
 	 */
-	function read_nodes(parent_node, input, position, len) {
-		this.publicKeyPacket = parent_node;
-		var exit = false;
-		var pos = position;
-		var l = len;
-		while (input.length != pos) {
-			var result = openpgp_packet.read_packet(input, pos, input.length - pos);
-			if (result == null) {
-				util.print_error("openpgp.msg.publickey read_nodes:\n"+'[pub_key]parsing ends here @:' + pos + " l:" + l);
-				break;
-			} else {
-				switch (result.tagType) {
-				case 2: // public key revocation signature
-					if (result.signatureType == 32)
-						this.revocationSignatures[this.revocationSignatures.length] = result;
-					else if (result.signatureType == 16 || result.signatureType == 17 || result.signatureType == 18  || result.signatureType == 19)
-						this.certificationSignature = result;
-					else if (result.signatureType == 25) {
-						this.bindingSignature = result;
-					} else if (result.signatureType == 31) {
-						this.directSignatures[this.directSignatures.length] = result;
-					} else
-						util.print_error("openpgp.msg.publickey read_nodes:\n"+"unknown signature type directly on key "+result.signatureType);
-					pos += result.packetLength + result.headerLength;
-					break;
-				case 14: // Public-Subkey Packet
-					this.subKeys[this.subKeys.length] = result;
-					pos += result.packetLength + result.headerLength;
-					pos += result.read_nodes(this.publicKeyPacket,input, pos, input.length - pos);
-					break;
-				case 17: // User Attribute Packet
-					this.userAttributes[this.userAttributes.length] = result;
-					pos += result.packetLength + result.headerLength;
-					pos += result.read_nodes(this.publicKeyPacket,input, pos, input.length - pos);
-					break;
-				case 13: // User ID Packet
-					this.userIds[this.userIds.length] = result;
-					pos += result.packetLength + result.headerLength;
-					pos += result.read_nodes(this.publicKeyPacket, input, pos, input.length - pos);
-					break;
-				default:
-					this.data = input;
-					this.position = position - this.publicKeyPacket.packetLength - this.publicKeyPacket.headerLength;
-					this.len = pos - position;
-					return this.len;
-				}
-			}
-		}
-		this.data = input;
-		this.position = position - (this.publicKeyPacket.packetLength - this.publicKeyPacket.headerLength);
-		this.len = pos - position;
-		return this.len;
+	function read_packet(input, position, len) {
+		this.packetLength = len;
+		// - A one-octet field that describes how the data is formatted.
+
+		this.format = input[position];
+		this.filename = input.substr(position + 2, input
+				.charCodeAt(position + 1));
+		this.date = new Date(parseInt(input.substr(position + 2
+				+ input.charCodeAt(position + 1), 4)) * 1000);
+		this.data = input.substring(position + 6
+				+ input.charCodeAt(position + 1));
+		return this;
 	}
 
-	function write() {
-
-	}
-
-	function getKeyId() {
-		return this.publicKeyPacket.getKeyId();
-	}
-	
-	function getFingerprint() {
-		return this.publicKeyPacket.getFingerprint();
-	}
-
-
-	
-	function validate() {
-		// check revocation keys
-		for (var i = 0; i < this.revocationSignatures.length; i++) {
-			var tohash = this.publicKeyPacket.header+this.publicKeyPacket.data;
-			if (this.revocationSignatures[i].verify(tohash, this.publicKeyPacket))
-				return false;
-		}
-		
-		if (this.subKeys.length != 0) {
-			// search for a valid subkey
-			var found = false;
-			for (var i = 0; i < this.subKeys.length; i++)
-				if (this.subKeys[i].verifyKey() == 3) {
-					found = true;
-					break;
-				}
-			if (!found)
-				return false;
-		}
-		// search for one valid userid
-		found = false;
-		for (var i = 0; i < this.userIds.length; i++)
-			if (this.userIds[i].verify(this.publicKeyPacket) == 0) {
-				found = true;
-				break;
-			}
-		if (!found)
-			return false;
-		return true;
-	}
-	
 	/**
-	 * verifies all signatures
-	 * @return a 2 dimensional array. the first dimension corresponds to the userids available
+	 * Creates a string representation of the packet
+	 * 
+	 * @param data
+	 *            [String] the data to be inserted as body
+	 * @return [String] string-representation of the packet
 	 */
-	function verifyCertificationSignatures() {
-		var result = new Array();
-		for (var i = 0; i < this.userIds.length; i++) {
-			result[i] = this.userIds[i].verifyCertificationSignatures(this.publicKeyPacket);
-		}
+	function write_packet(data) {
+		data = data.replace(/\r\n/g, "\n").replace(/\n/g, "\r\n");
+		this.filename = "msg.txt";
+		this.date = new Date();
+		this.format = 't';
+		var result = openpgp_packet.write_packet_header(11, data.length + 6
+				+ this.filename.length);
+		result += this.format;
+		result += String.fromCharCode(this.filename.length);
+		result += this.filename;
+		result += String
+				.fromCharCode((Math.round(this.date.getTime() / 1000) >> 24) & 0xFF);
+		result += String
+				.fromCharCode((Math.round(this.date.getTime() / 1000) >> 16) & 0xFF);
+		result += String
+				.fromCharCode((Math.round(this.date.getTime() / 1000) >> 8) & 0xFF);
+		result += String
+				.fromCharCode(Math.round(this.date.getTime() / 1000) & 0xFF);
+		result += data;
+		this.data = data;
 		return result;
 	}
-	this.verifyCertificationSignatures = verifyCertificationSignatures;
-	
+
 	/**
-	 * verifies:
-	 *  - revocation certificates directly on key
-	 *  - self signatures
-	 *  - subkey binding and revocation certificates
-	 *  
-	 *  This is useful for validating the key
-	 *  @returns true if the basic signatures are all valid
+	 * generates debug output (pretty print)
+	 * 
+	 * @return String which gives some information about the keymaterial
 	 */
-	function verifyBasicSignatures() {
-		for (var i = 0; i < this.revocationSignatures.length; i++) {
-			var tohash = this.publicKeyPacket.header+this.publicKeyPacket.data;
-			if (this.revocationSignatures[i].verify(tohash, this.publicKeyPacket))
-				return false;
-			else return false;
-		}
-		
-		if (this.subKeys.length != 0) {
-			// search for a valid subkey
-			var found = false;
-			for (var i = 0; i < this.subKeys.length; i++) {
-				if (this.subKeys[i] == null)
-					continue;
-				var result = this.subKeys[i].verifyKey();
-				if (result == 3) {
-					found = true;
-					break;
-				} 
-			}
-			if (!found)
-				return false;
-		}
-		var keyId = this.getKeyId();
-		for (var i = 0; i < this.userIds.length; i++) {
-			for (var j = 0; j < this.userIds[i].certificationRevocationSignatures.length; j++) {
-				if (this.userIds[i].certificationSignatures[j].getIssuer == keyId &&
-					this.userIds[i].certificationSignatures[j].verifyBasic(this.publicKeyPacket) != 4)
-					return false;
-			}
-		}
-		return true;
-	}
-	
 	function toString() {
-		var result = " OPENPGP Public Key\n    length: "+this.len+"\n";
-		result += "    Revocation Signatures:\n"
-		for (var i=0; i < this.revocationSignatures.length; i++) {
-			result += "    "+this.revocationSignatures[i].toString(); 
-		}
-		result += "    User Ids:\n";
-		for (var i=0; i < this.userIds.length; i++) {
-			result += "    "+this.userIds[i].toString(); 
-		}
-		result += "    User Attributes:\n";
-		for (var i=0; i < this.userAttributes.length; i++) {
-			result += "    "+this.userAttributes[i].toString(); 
-		}
-		result += "    Public Key SubKeys:\n";
-		for (var i=0; i < this.subKeys.length; i++) {
-			result += "    "+this.subKeys[i].toString(); 
-		}
-		return result;
-	}
-	
-	/**
-	 * finds an encryption key for this public key
-	 * @returns null if no encryption key has been found
-	 */
-	function getEncryptionKey() {
-		if (this.publicKeyPacket.publicKeyAlgorithm != 17 && this.publicKeyPacket.publicKeyAlgorithm != 3
-				&& this.publicKeyPacket.verifyKey())
-			return this.publicKeyPacket;
-		else if (this.publicKeyPacket.version == 4) // V3 keys MUST NOT have subkeys.
-			for (var j = 0; j < this.subKeys.length; j++)
-				if (this.subKeys[j].publicKeyAlgorithm != 17 &&
-						this.subKeys[j].publicKeyAlgorithm != 3 &&
-						this.subKeys[j].verifyKey()) {
-					return this.subKeys[j];
-				}
-		return null;
-	}
-	
-	function getSigningKey() {
-		if ((this.publicKeyPacket.publicKeyAlgorithm == 17 ||
-			 this.publicKeyPacket.publicKeyAlgorithm != 2))
-			return this.publicKeyPacket;
-		else if (this.publicKeyPacket.version == 4) // V3 keys MUST NOT have subkeys.
-			for (var j = 0; j < this.subKeys.length; j++) {
-				if ((this.subKeys[j].publicKeyAlgorithm == 17 ||
-					 this.subKeys[j].publicKeyAlgorithm != 2) &&
-					 this.subKeys[j].verifyKey())
-					return this.subKeys[j];
-			}
-		return null;
+		return '5.9.  Literal Data Packet (Tag 11)\n' + '    length: '
+				+ this.packetLength + '\n' + '    format: ' + this.format
+				+ '\n' + '    filename:' + this.filename + '\n'
+				+ '    date:   ' + this.date + '\n' + '    data:  |'
+				+ this.data + '|\n' + '    rdata: |' + this.real_data + '|\n';
 	}
 
-	this.getEncryptionKey = getEncryptionKey;
-	this.getSigningKey = getSigningKey;
-	this.read_nodes = read_nodes;
-	this.write = write;
+	this.read_packet = read_packet;
 	this.toString = toString;
-	this.validate = validate;
-	this.getFingerprint = getFingerprint;
-	this.getKeyId = getKeyId;
-	this.verifyBasicSignatures = verifyBasicSignatures;
+	this.write_packet = write_packet;
 }
 // GPG4Browsers - An OpenPGP implementation in javascript
 // Copyright (C) 2011 Recurity Labs GmbH
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+/**
+ * Implementation of the Compressed Data Packet (Tag 8)
+ * 
+ * RFC4880 5.6:
+ * The Compressed Data packet contains compressed data.  Typically, this
+ * packet is found as the contents of an encrypted packet, or following
+ * a Signature or One-Pass Signature packet, and contains a literal data
+ * packet.
+ */   
+function openpgp_packet_compressed() {
+	this.tagType = 8;
+	
+	/**
+	 * parsing function for the packet.
+	 * @param input [string] payload of a tag 8 packet
+	 * @param position [integer] position to start reading from the input string
+	 * @param len [integer] length of the packet or the remaining length of input at position
+	 * @return [openpgp_packet_compressed] object representation
+	 */
+	function read_packet (input, position, len) {
+		this.packetLength = len;
+		var mypos = position;
+		// One octet that gives the algorithm used to compress the packet.
+		this.type = input.charCodeAt(mypos++);
+		// Compressed data, which makes up the remainder of the packet.
+		this.compressedData = input.substring(position+1, position+len);
+		return this;
+	}
+	/**
+	 * decompression method for decompressing the compressed data
+	 * read by read_packet
+	 * @return [String] the decompressed data
+	 */
+	function decompress() {
+		if (this.decompressedData != null)
+			return this.decompressedData;
+
+		if (this.type == null)
+			return null;
+
+		switch (this.type) {
+		case 0: // - Uncompressed
+			this.decompressedData = this.compressedData;
+			break;
+		case 1: // - ZIP [RFC1951]
+			var compData = this.compressedData;
+			var radix = s2r(compData).replace(/\n/g,"");
+			// no header in this case, directly call deflate
+			var jxg_obj = new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(radix));
+			var outputString = unescape(jxg_obj.deflate()[0][0]);
+			var packet = openpgp_packet.read_packet(outputString, 0, outputString.length);
+			util.print_info('Decompressed packet [Type 1-ZIP]: ' + packet);
+			this.decompressedData = packet.data;
+			break;
+		case 2: // - ZLIB [RFC1950]
+			var compressionMethod = this.compressedData.charCodeAt(0) % 0x10; //RFC 1950. Bits 0-3 Compression Method
+			//Bits 4-7 RFC 1950 are LZ77 Window. Generally this value is 7 == 32k window size.
+			//2nd Byte in RFC 1950 is for "FLAGs" Allows for a Dictionary (how is this defined). Basic checksum, and compression level.
+			if (compressionMethod == 8) { //CM 8 is for DEFLATE, RFC 1951
+				// remove 4 bytes ADLER32 checksum from the end
+				var compData = this.compressedData.substring(0, this.compressedData.length - 4);
+				var radix = s2r(compData).replace(/\n/g,"");
+				var outputString = JXG.decompress(radix);
+				//TODO check ADLER32 checksum
+				var packet = openpgp_packet.read_packet(outputString, 0, outputString.length);
+				util.print_info('Decompressed packet [Type 2-ZLIB]: ' + packet);
+				this.decompressedData = packet.data;
+			} else {
+				util.print_error("Compression algorithm ZLIB only supports DEFLATE compression method.");
+			}
+			break;
+		case 3: //  - BZip2 [BZ2]
+			// TODO: need to implement this
+			util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");
+			break;
+		default:
+			util.print_error("Compression algorithm unknown :"+this.type);
+			break;
+		}
+		util.print_debug("decompressed:"+util.hexstrdump(this.decompressedData));
+		return this.decompressedData; 
+	}
+
+	/**
+	 * Compress the packet data (member decompressedData)
+	 * @param type [integer] algorithm to be used // See RFC 4880 9.3
+	 * @param data [String] data to be compressed
+	 * @return [String] The compressed data stored in attribute compressedData
+	 */
+	function compress(type, data) {
+		this.type = type;
+		this.decompressedData = data;
+		switch (this.type) {
+		case 0: // - Uncompressed
+			this.compressedData = this.decompressedData;
+			break;
+		case 1: // - ZIP [RFC1951]
+			util.print_error("Compression algorithm ZIP [RFC1951] is not implemented.");
+			break;
+		case 2: // - ZLIB [RFC1950]
+			// TODO: need to implement this
+			util.print_error("Compression algorithm ZLIB [RFC1950] is not implemented.");
+			break;
+		case 3: //  - BZip2 [BZ2]
+			// TODO: need to implement this
+			util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");
+			break;
+		default:
+			util.print_error("Compression algorithm unknown :"+this.type);
+			break;
+		}
+		this.packetLength = this.compressedData.length +1;
+		return this.compressedData; 
+	}
+	
+	/**
+	 * creates a string representation of the packet
+	 * @param algorithm [integer] algorithm to be used // See RFC 4880 9.3
+	 * @param data [String] data to be compressed
+	 * @return [String] string-representation of the packet
+	 */
+	function write_packet(algorithm, data) {
+		this.decompressedData = data;
+		if (algorithm == null) {
+			this.type = 1;
+		}
+		var result = String.fromCharCode(this.type)+this.compress(this.type);
+		return openpgp_packet.write_packet_header(8, result.length)+result;
+	}
+	
+	/**
+	 * pretty printing the packet (useful for debug purposes)
+	 * @return [String]
+	 */
+	function toString() {
+		return '5.6.  Compressed Data Packet (Tag 8)\n'+
+		   '    length:  '+this.packetLength+'\n'+
+			   '    Compression Algorithm = '+this.type+'\n'+
+		       '    Compressed Data: Byte ['+util.hexstrdump(this.compressedData)+']\n';
+	}
+	
+	this.read_packet = read_packet;
+	this.toString = toString;
+	this.compress = compress;
+	this.decompress = decompress;
+	this.write_packet = write_packet;
+};
+// GPG4Browsers - An OpenPGP implementation in javascript
+// Copyright (C) 2011 Recurity Labs GmbH
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+/**
+ * A User ID packet consists of UTF-8 text that is intended to represent
+ * the name and email address of the key holder.  By convention, it
+ * includes an RFC 2822 [RFC2822] mail name-addr, but there are no
+ * restrictions on its content.  The packet length in the header
+ * specifies the length of the User ID. 
+ */
+
+function openpgp_packet_userid() {
+	this.tagType = 13;
+	this.certificationSignatures = new Array();
+	this.certificationRevocationSignatures = new Array();
+	this.revocationSignatures = new Array();
+	this.parentNode = null;
+
+	/**
+	 * parsing function for a user id packet (tag 13).
+	 * @param input [string] payload of a tag 13 packet
+	 * @param position [integer] position to start reading from the input string
+	 * @param len [integer] length of the packet or the remaining length of input at position
+	 * @return [openpgp_packet_encrypteddata] object representation
+	 */
+	function read_packet(input, position, len) {
+		this.text = '';
+		this.packetLength = len;
+
+		for ( var i = 0; i < len; i++) {
+			this.text += input[position + i];
+		}
+		return this;
+	}
+
+	/**
+	 * creates a string representation of the user id packet
+	 * @param user_id [String] the user id as string ("John Doe <john.doe@mail.us")
+	 * @return [String] string representation
+	 */
+	function write_packet(user_id) {
+		this.text = user_id;
+		var result = openpgp_packet.write_packet_header(13,this.text.length);
+		result += this.text;
+		return result;
+	}
+
+	/**
+	 * Continue parsing packets belonging to the userid packet such as signatures
+	 * @param parent_node [openpgp_*] the parent object
+	 * @param input [String] input string to read the packet(s) from
+	 * @param position [integer] start position for the parser
+	 * @param len [integer] length of the packet(s) or remaining length of input
+	 * @return [integer] length of nodes read
+	 */
+	function read_nodes(parent_node, input, position, len) {
+		if (parent_node.tagType == 6) { // public key
+			this.parentNode = parent_node;
+			var pos = position;
+			var l = len;
+			while (input.length != pos) {
+				var result = openpgp_packet.read_packet(input, pos, l - (pos - position));
+				if (result == null) {
+					util.print_error('[user_id] parsing ends here @:' + pos + " l:" + l);
+					break;
+				} else {
+					
+					pos += result.packetLength + result.headerLength;
+					l = input.length - pos;
+					switch (result.tagType) {
+					case 2: // Signature Packet
+						if (result.signatureType > 15
+								&& result.signatureType < 20) { // certification
+							// //
+							// signature
+							this.certificationSignatures[this.certificationSignatures.length] = result;
+							break;
+						} else if (result.signatureType == 48) {// certification revocation signature
+							this.certificationRevocationSignatures[this.certificationRevocationSignatures.length] = result;
+							break;
+						} else if (result.signatureType == 24) { // omg. standalone signature 
+							this.certificationSignatures[this.certificationSignatures.length] = result;
+							break;
+						} else {
+							util.debug("unknown sig t: "+result.signatureType+"@"+(pos - (result.packetLength + result.headerLength)));
+						}
+					default:
+						this.data = input;
+						this.position = position - parent_node.packetLength;
+						this.len = pos - position -(result.headerLength + result.packetLength);
+						return this.len;
+					}
+				}
+			}
+			this.data = input;
+			this.position = position - parent_node.packetLength;
+			this.len = pos - position -(result.headerLength + result.packetLength);
+			return this.len;
+		} else if (parent_node.tagType == 5) { // secret Key
+			this.parentNode = parent_node;
+			var exit = false;
+			var pos = position;
+			while (input.length != pos) {
+				var result = openpgp_packet.read_packet(input, pos, l - (pos - position));
+				if (result == null) {
+					util.print_error('parsing ends here @:' + pos + " l:" + l);
+					break;
+				} else {
+					pos += result.packetLength + result.headerLength;
+					l = input.length - pos;
+					switch (result.tagType) {
+					case 2: // Signature Packet certification signature
+						if (result.signatureType > 15
+								&& result.signatureType < 20)
+							this.certificationSignatures[this.certificationSignatures.length] = result;
+						// certification revocation signature
+						else if (result.signatureType == 48)
+							this.certificationRevocationSignatures[this.certificationRevocationSignatures.length] = result;
+					default:
+						this.data = input;
+						this.position = position - parent_node.packetLength;
+						this.len = pos - position -(result.headerLength + result.packetLength);
+						return this.len;
+					}
+				}
+			}
+		} else {
+			util.print_error("unknown parent node for a userId packet "+parent_node.tagType);
+		}
+	}
+	
+	/**
+	 * generates debug output (pretty print)
+	 * @return String which gives some information about the user id packet
+	 */
+	function toString() {
+		var result = '     5.11.  User ID Packet (Tag 13)\n' + '    text ('
+				+ this.text.length + '): "' + this.text.replace("<", "&lt;")
+				+ '"\n';
+		result +="certification signatures:\n";
+		for (var i = 0; i < this.certificationSignatures.length; i++) {
+			result += "        "+this.certificationSignatures[i].toString();
+		}
+		result +="certification revocation signatures:\n";
+		for (var i = 0; i < this.certificationRevocationSignatures.length; i++) {
+			result += "        "+this.certificationRevocationSignatures[i].toString();
+		}
+		return result;
+	}
+
+	/**
+	 * lookup function to find certification revocation signatures
+	 * @param keyId string containing the key id of the issuer of this signature
+	 * @return a CertificationRevocationSignature if found; otherwise null
+	 */
+	function hasCertificationRevocationSignature(keyId) {
+		for (var i = 0; i < this.certificationRevocationSignatures.length; i++) {
+			if ((this.certificationRevocationSignatures[i].version == 3 &&
+				 this.certificationRevocationSignatures[i].keyId == keyId) ||
+				(this.certificationRevocationSignatures[i].version == 4 &&
+				 this.certificationRevocationSignatures[i].issuerKeyId == keyId))
+				return this.certificationRevocationSignatures[i];
+		}
+		return null;
+	}
+
+	/**
+	 * Verifies all certification signatures. This method does not consider possible revocation signatures.
+	 * @param publicKeyPacket the top level key material
+	 * @return an array of integers corresponding to the array of certification signatures. The meaning of each integer is the following:
+	 * 0 = bad signature
+	 * 1 = signature expired
+	 * 2 = issuer key not available
+	 * 3 = revoked
+	 * 4 = signature valid
+	 * 5 = signature by key owner expired
+	 * 6 = signature by key owner revoked
+	 */
+	function verifyCertificationSignatures(publicKeyPacket) {
+		result = new Array();
+		for (var i = 0 ; i < this.certificationSignatures.length; i++) {
+			// A certification signature (type 0x10 through 0x13) hashes the User
+			// ID being bound to the key into the hash context after the above
+			// data.  A V3 certification hashes the contents of the User ID or
+			// attribute packet packet, without any header.  A V4 certification
+			// hashes the constant 0xB4 for User ID certifications or the constant
+			// 0xD1 for User Attribute certifications, followed by a four-octet
+			// number giving the length of the User ID or User Attribute data, and
+			// then the User ID or User Attribute data.
+
+			if (this.certificationSignatures[i].version == 4) {
+				if (this.certificationSignatures[i].signatureExpirationTime != null &&
+						this.certificationSignatures[i].signatureExpirationTime != null &&
+						this.certificationSignatures[i].signatureExpirationTime != 0 &&
+						!this.certificationSignatures[i].signatureNeverExpires &&
+						new Date(this.certificationSignatures[i].creationTime.getTime() +(this.certificationSignatures[i].signatureExpirationTime*1000)) < new Date()) {
+					if (this.certificationSignatures[i].issuerKeyId == publicKeyPacket.getKeyId())
+						result[i] = 5;
+					else
+						result[i] = 1;
+					continue;
+				}
+				if (this.certificationSignatures[i].issuerKeyId == null) {
+					result[i] = 0;
+					continue;
+				}
+				var issuerPublicKey = openpgp.keyring.getPublicKeysForKeyId(this.certificationSignatures[i].issuerKeyId);
+				if (issuerPublicKey == null || issuerPublicKey.length == 0) {
+					result[i] = 2;
+					continue;
+				}
+				// TODO: try to verify all returned issuer public keys (key ids are not unique!)
+				var issuerPublicKey = issuerPublicKey[0];
+				var signingKey = issuerPublicKey.obj.getSigningKey();
+				if (signingKey == null) {
+					result[i] = 0;
+					continue;
+				}
+				var revocation = this.hasCertificationRevocationSignature(this.certificationSignatures[i].issuerKeyId);
+				if (revocation != null && revocation.creationTime > 
+					this.certificationSignatures[i].creationTime) {
+					var signaturedata = String.fromCharCode(0x99)+ publicKeyPacket.header.substring(1)+
+					publicKeyPacket.data+String.fromCharCode(0xB4)+
+					String.fromCharCode((this.text.length >> 24) & 0xFF)+
+					String.fromCharCode((this.text.length >> 16) & 0xFF)+
+					String.fromCharCode((this.text.length >>  8) & 0xFF)+
+					String.fromCharCode((this.text.length) & 0xFF)+
+					this.text;
+					if (revocation.verify(signaturedata, signingKey)) {
+						if (this.certificationSignatures[i].issuerKeyId == publicKeyPacket.getKeyId())
+							result[i] = 6;
+						else
+							result[i] = 3;
+						continue;
+					}
+				}
+				var signaturedata = String.fromCharCode(0x99)+ publicKeyPacket.header.substring(1)+
+						publicKeyPacket.data+String.fromCharCode(0xB4)+
+						String.fromCharCode((this.text.length >> 24) & 0xFF)+
+						String.fromCharCode((this.text.length >> 16) & 0xFF)+
+						String.fromCharCode((this.text.length >>  8) & 0xFF)+
+						String.fromCharCode((this.text.length) & 0xFF)+
+						this.text;
+				if (this.certificationSignatures[i].verify(signaturedata, signingKey)) {
+					result[i] = 4;
+				} else
+				result[i] = 0;
+			} else if (this.certificationSignatures[i].version == 3) {
+				if (this.certificationSignatures[i].keyId == null) {
+					result[i] = 0;
+					continue;
+				}
+				var issuerPublicKey = openpgp.keyring.getPublicKeysForKeyId(this.certificationSignatures[i].keyId);
+				if (issuerPublicKey == null || issuerPublicKey.length == 0) {
+					result[i] = 2;
+					continue;
+				}
+				issuerPublicKey = issuerPublicKey[0];
+				var signingKey = publicKey.obj.getSigningKey();
+				if (signingKey == null) {
+					result[i] = 0;
+					continue;
+				}
+				var revocation = this.hasCertificationRevocationSignature(this.certificationSignatures[i].keyId);
+				if (revocation != null && revocation.creationTime > 
+					this.certificationSignatures[i].creationTime) {
+					var signaturedata = String.fromCharCode(0x99)+ this.publicKeyPacket.header.substring(1)+
+					this.publicKeyPacket.data+this.text;
+					if (revocation.verify(signaturedata, signingKey)) {
+						if (revocation.keyId == publicKeyPacket.getKeyId())
+							result[i] = 6;
+						else
+							result[i] = 3;
+						continue;
+					}
+				}
+				var signaturedata = String.fromCharCode(0x99)+ publicKeyPacket.header.substring(1)+
+					publicKeyPacket.data+this.text;
+				if (this.certificationSignatures[i].verify(signaturedata, signingKey)) {
+					result[i] = 4;
+				} else 
+				result[i] = 0;
+			} else {
+				result[i] = 0;
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * verifies the signatures of the user id
+	 * @return 0 if the userid is valid; 1 = userid expired; 2 = userid revoked
+	 */
+	function verify(publicKeyPacket) {
+		var result = this.verifyCertificationSignatures(publicKeyPacket);
+		if (result.indexOf(6) != -1)
+			return 2;
+		if (result.indexOf(5) != -1)
+			return 1;
+		return 0;
+	}
+
+	// TODO: implementation missing
+	function addCertification(publicKeyPacket, privateKeyPacket) {
+		
+	}
+
+	// TODO: implementation missing
+	function revokeCertification(publicKeyPacket, privateKeyPacket) {
+		
+	}
+
+	this.hasCertificationRevocationSignature = hasCertificationRevocationSignature;
+	this.verifyCertificationSignatures = verifyCertificationSignatures;
+	this.verify = verify;
+	this.read_packet = read_packet;
+	this.write_packet = write_packet;
+	this.toString = toString;
+	this.read_nodes = read_nodes;
+}
+// GPG4Browsers - An OpenPGP implementation in javascript
+// Copyright (C) 2011 Recurity Labs GmbH
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+/**
+ * Implementation of the Sym. Encrypted Integrity Protected Data Packet (Tag 18)
+ * 
+ * RFC4880 5.13: The Symmetrically Encrypted Integrity Protected Data packet is
+ * a variant of the Symmetrically Encrypted Data packet. It is a new feature
+ * created for OpenPGP that addresses the problem of detecting a modification to
+ * encrypted data. It is used in combination with a Modification Detection Code
+ * packet.
+ */
+
+function openpgp_packet_encryptedintegrityprotecteddata() {
+	this.tagType = 18;
+	this.version = null; // integer == 1
+	this.packetLength = null; // integer
+	this.encryptedData = null; // string
+	this.decrytpedData = null; // string
+	this.hash = null; // string
+	/**
+	 * parsing function for the packet.
+	 * 
+	 * @param input
+	 *            [string] payload of a tag 18 packet
+	 * @param position
+	 *            [integer] position to start reading from the input string
+	 * @param len
+	 *            [integer] length of the packet or the remaining length of
+	 *            input at position
+	 * @return [openpgp_packet_encryptedintegrityprotecteddata] object
+	 *         representation
+	 */
+	function read_packet(input, position, len) {
+		this.packetLength = len;
+		// - A one-octet version number. The only currently defined value is
+		// 1.
+		this.version = input[position].charCodeAt();
+		if (this.version != 1) {
+			util
+					.print_error('openpgp.packet.encryptedintegrityprotecteddata.js\nunknown encrypted integrity protected data packet version: '
+							+ this.version
+							+ " , @ "
+							+ position
+							+ "hex:"
+							+ util.hexstrdump(input));
+			return null;
+		}
+		// - Encrypted data, the output of the selected symmetric-key cipher
+		//   operating in Cipher Feedback mode with shift amount equal to the
+		//   block size of the cipher (CFB-n where n is the block size).
+		this.encryptedData = input.substring(position + 1, position + 1 + len);
+		util.print_debug("openpgp.packet.encryptedintegrityprotecteddata.js\n"
+				+ this.toString());
+		return this;
+	}
+
+	/**
+	 * Creates a string representation of a Sym. Encrypted Integrity Protected
+	 * Data Packet (tag 18) (see RFC4880 5.13)
+	 * 
+	 * @param symmetric_algorithm
+	 *            [integer] the selected symmetric encryption algorithm to be
+	 *            used
+	 * @param key
+	 *            [String] the key of cipher blocksize length to be used
+	 * @param data
+	 *            plaintext data to be encrypted within the packet
+	 * @return a string representation of the packet
+	 */
+	function write_packet(symmetric_algorithm, key, data) {
+
+		var prefixrandom = openpgp_crypto_getPrefixRandom(symmetric_algorithm);
+		var prefix = prefixrandom
+				+ prefixrandom.charAt(prefixrandom.length - 2)
+				+ prefixrandom.charAt(prefixrandom.length - 1);
+		var tohash = data;
+		tohash += String.fromCharCode(0xD3);
+		tohash += String.fromCharCode(0x14);
+		util.print_debug_hexstr_dump("data to be hashed:"
+				, prefix + tohash);
+		tohash += str_sha1(prefix + tohash);
+		util.print_debug_hexstr_dump("hash:"
+				, tohash.substring(tohash.length - 20,
+						tohash.length));
+		var result = openpgp_crypto_symmetricEncrypt(prefixrandom,
+				symmetric_algorithm, key, tohash, false).substring(0,
+				prefix.length + tohash.length);
+		var header = openpgp_packet.write_packet_header(18, result.length + 1)
+				+ String.fromCharCode(1);
+		this.encryptedData = result;
+		return header + result;
+	}
+
+	/**
+	 * Decrypts the encrypted data contained in this object read_packet must
+	 * have been called before
+	 * 
+	 * @param symmetric_algorithm_type
+	 *            [integer] the selected symmetric encryption algorithm to be
+	 *            used
+	 * @param key
+	 *            [String] the key of cipher blocksize length to be used
+	 * @return the decrypted data of this packet
+	 */
+	function decrypt(symmetric_algorithm_type, key) {
+		this.decryptedData = openpgp_crypto_symmetricDecrypt(
+				symmetric_algorithm_type, key, this.encryptedData, false);
+		// there must be a modification detection code packet as the
+		// last packet and everything gets hashed except the hash itself
+		this.hash = str_sha1(openpgp_crypto_MDCSystemBytes(
+				symmetric_algorithm_type, key, this.encryptedData)
+				+ this.decryptedData.substring(0,
+						this.decryptedData.length - 20));
+		util.print_debug_hexstr_dump("calc hash = ", this.hash);
+		if (this.hash == this.decryptedData.substring(
+				this.decryptedData.length - 20, this.decryptedData.length))
+			return this.decryptedData;
+		else
+			util
+					.print_error("Decryption stopped: discovered a modification of encrypted data.");
+		return null;
+	}
+
+	function toString() {
+	    var data = '';
+	    if(openpgp.config.debug)
+	        data = '    data: Bytes ['
+				+ util.hexstrdump(this.encryptedData) + ']';
+	    
+		return '5.13.  Sym. Encrypted Integrity Protected Data Packet (Tag 18)\n'
+				+ '    length:  '
+				+ this.packetLength
+				+ '\n'
+				+ '    version: '
+				+ this.version
+				+ '\n'
+				+ data;
+	}
+
+	this.write_packet = write_packet;
+	this.read_packet = read_packet;
+	this.toString = toString;
+	this.decrypt = decrypt;
+};
+// GPG4Browsers - An OpenPGP implementation in javascript
+// Copyright (C) 2011 Recurity Labs GmbH
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+/**
+ * Implementation of the One-Pass Signature Packets (Tag 4)
+ * 
+ * RFC4880 5.4:
+ * The One-Pass Signature packet precedes the signed data and contains
+ * enough information to allow the receiver to begin calculating any
+ * hashes needed to verify the signature.  It allows the Signature
+ * packet to be placed at the end of the message, so that the signer
+ * can compute the entire signed message in one pass.
+ */
+function openpgp_packet_onepasssignature() {
+	this.tagType = 4;
+	this.version = null; // A one-octet version number.  The current version is 3.
+	this.type == null; 	 // A one-octet signature type.  Signature types are described in RFC4880 Section 5.2.1.
+	this.hashAlgorithm = null; 	   // A one-octet number describing the hash algorithm used. (See RFC4880 9.4)
+	this.publicKeyAlgorithm = null;	     // A one-octet number describing the public-key algorithm used. (See RFC4880 9.1)
+	this.signingKeyId = null; // An eight-octet number holding the Key ID of the signing key.
+	this.flags = null; 	//  A one-octet number holding a flag showing whether the signature is nested.  A zero value indicates that the next packet is another One-Pass Signature packet that describes another signature to be applied to the same message data.
+
+	/**
+	 * parsing function for a one-pass signature packet (tag 4).
+	 * @param input [string] payload of a tag 4 packet
+	 * @param position [integer] position to start reading from the input string
+	 * @param len [integer] length of the packet or the remaining length of input at position
+	 * @return [openpgp_packet_encrypteddata] object representation
+	 */
+	function read_packet(input, position, len) {
+		this.packetLength = len;
+		var mypos = position;
+		// A one-octet version number.  The current version is 3.
+		this.version = input.charCodeAt(mypos++);
+
+	     // A one-octet signature type.  Signature types are described in
+	     //   Section 5.2.1.
+		this.type = input.charCodeAt(mypos++);
+
+	     // A one-octet number describing the hash algorithm used.
+		this.hashAlgorithm = input.charCodeAt(mypos++);
+
+	     // A one-octet number describing the public-key algorithm used.
+		this.publicKeyAlgorithm = input.charCodeAt(mypos++);
+	     // An eight-octet number holding the Key ID of the signing key.
+		this.signingKeyId = new openpgp_type_keyid();
+		this.signingKeyId.read_packet(input,mypos);
+		mypos += 8;
+		
+	     // A one-octet number holding a flag showing whether the signature
+	     //   is nested.  A zero value indicates that the next packet is
+	     //   another One-Pass Signature packet that describes another
+	     //   signature to be applied to the same message data.
+		this.flags = input.charCodeAt(mypos++);
+		return this;
+	}
+
+	/**
+	 * creates a string representation of a one-pass signature packet
+	 * @param type [integer] Signature types as described in RFC4880 Section 5.2.1.
+	 * @param hashalgorithm [integer] the hash algorithm used within the signature
+	 * @param privatekey [openpgp_msg_privatekey] the private key used to generate the signature
+	 * @param length [integer] length of data to be signed
+	 * @param nested [boolean] boolean showing whether the signature is nested. 
+	 *  "true" indicates that the next packet is another One-Pass Signature packet
+	 *   that describes another signature to be applied to the same message data. 
+	 * @return [String] a string representation of a one-pass signature packet
+	 */
+	function write_packet(type, hashalgorithm, privatekey,length, nested) {
+		var result =""; 
+		
+		result += openpgp_packet.write_packet_header(4,13);
+		result += String.fromCharCode(3);
+		result += String.fromCharCode(type);
+		result += String.fromCharCode(hashalgorithm);
+		result += String.fromCharCode(privatekey.privateKeyPacket.publicKey.publicKeyAlgorithm);
+		result += privatekey.getKeyId();
+		if (nested)
+			result += String.fromCharCode(0);
+		else
+			result += String.fromCharCode(1);
+		
+		return result;
+	}
+	
+	/**
+	 * generates debug output (pretty print)
+	 * @return String which gives some information about the one-pass signature packet
+	 */
+	function toString() {
+		return '5.4.  One-Pass Signature Packets (Tag 4)\n'+
+			   '    length: '+this.packetLength+'\n'+
+			   '    type:   '+this.type+'\n'+
+			   '    keyID:  '+this.signingKeyId.toString()+'\n'+
+			   '    hashA:  '+this.hashAlgorithm+'\n'+
+			   '    pubKeyA:'+this.publicKeyAlgorithm+'\n'+
+			   '    flags:  '+this.flags+'\n'+
+			   '    version:'+this.version+'\n';
+	}
+	
+	this.read_packet = read_packet;
+	this.toString = toString;
+	this.write_packet = write_packet;
+};// GPG4Browsers - An OpenPGP implementation in javascript
+// Copyright (C) 2011 Recurity Labs GmbH
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -10259,7 +3927,7 @@ function openpgp_config() {
 			keyserver: "keyserver.linux.it" // "pgp.mit.edu:11371"
 	};
 
-	this.versionstring ="OpenPGP.js v.1.20120821";
+	this.versionstring ="OpenPGP.js v.1.20120827";
 	this.commentstring ="http://openpgpjs.org";
 	/**
 	 * reads the config out of the HTML5 local storage
@@ -10310,590 +3978,724 @@ function openpgp_config() {
 // License along with this library; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
-function openpgp_msg_privatekey() {
-	this.subKeys = new Array();
-	this.privateKeyPacket = null;
-	this.userIds = new Array();
-	this.userAttributes = new Array();
-	this.revocationSignatures = new Array();
-	this.subKeys = new Array();
+/**
+ * Implementation of the String-to-key specifier (RFC4880 3.7)
+ * String-to-key (S2K) specifiers are used to convert passphrase strings
+   into symmetric-key encryption/decryption keys.  They are used in two
+   places, currently: to encrypt the secret part of private keys in the
+   private keyring, and to convert passphrases to encryption keys for
+   symmetrically encrypted messages.
+ */
+function openpgp_type_s2k() {
+	/**
+	 * parsing function for a string-to-key specifier (RFC 4880 3.7).
+	 * @param input [string] payload of string-to-key specifier
+	 * @param position [integer] position to start reading from the input string
+	 * @return [openpgp_type_s2k] object representation
+	 */
+	function read(input, position) {
+		var mypos = position;
+		this.type = input[mypos++].charCodeAt();
+		switch (this.type) {
+		case 0: // Simple S2K
+			// Octet 1: hash algorithm
+			this.hashAlgorithm = input[mypos++].charCodeAt();
+			this.s2kLength = 1;
+			break;
+
+		case 1: // Salted S2K
+			// Octet 1: hash algorithm
+			this.hashAlgorithm = input[mypos++].charCodeAt();
+
+			// Octets 2-9: 8-octet salt value
+			this.saltValue = input.substring(mypos, mypos+8);
+			mypos += 8;
+			this.s2kLength = 9;
+			break;
+
+		case 3: // Iterated and Salted S2K
+			// Octet 1: hash algorithm
+			this.hashAlgorithm = input[mypos++].charCodeAt();
+
+			// Octets 2-9: 8-octet salt value
+			this.saltValue = input.substring(mypos, mypos+8);
+			mypos += 8;
+
+			// Octet 10: count, a one-octet, coded value
+			this.EXPBIAS = 6;
+			var c = input[mypos++].charCodeAt();
+			this.count = (16 + (c & 15)) << ((c >> 4) + this.EXPBIAS);
+			this.s2kLength = 10;
+			break;
+
+		case 2: // Reserved value
+		default:
+			util.print_error("unknown s2k type! "+this.type);
+			break;
+		}
+		return this;
+	}
+	
+	
+	/**
+	 * writes an s2k hash based on the inputs.
+	 * @return [String] produced key of hashAlgorithm hash length
+	 */
+	function write(type, hash, passphrase, salt, c){
+	    this.type = type;
+	    if(this.type == 3){this.saltValue = salt;
+	        this.hashAlgorithm = hash;
+	        this.count = (16 + (c & 15)) << ((c >> 4) + 6);
+	        this.s2kLength = 10;
+	    }
+	    return this.produce_key(passphrase);
+	}
 
 	/**
-	 * 
-	 * @return last position
+	 * produces a key using the specified passphrase and the defined hashAlgorithm 
+	 * @param passphrase [String] passphrase containing user input
+	 * @return [String] produced key with a length corresponding to hashAlgorithm hash length
 	 */
-	function read_nodes(parent_node, input, position, len) {
-		this.privateKeyPacket = parent_node;
+	function produce_key(passphrase, numBytes) {
+		if (this.type == 0) {
+			return openpgp_crypto_hashData(this.hashAlgorithm,passphrase);
+		} else if (this.type == 1) {
+			return openpgp_crypto_hashData(this.hashAlgorithm,this.saltValue+passphrase);
+		} else if (this.type == 3) {
+			var isp = [];
+			isp[0] = this.saltValue+passphrase;
+			while (isp.length*(this.saltValue+passphrase).length < this.count)
+				isp.push(this.saltValue+passphrase);
+			isp = isp.join('');			
+			if (isp.length > this.count)
+				isp = isp.substr(0, this.count);
+			if(numBytes && (numBytes == 24 || numBytes == 32)){ //This if accounts for RFC 4880 3.7.1.1 -- If hash size is greater than block size, use leftmost bits.  If blocksize larger than hash size, we need to rehash isp and prepend with 0.
+			    var key = openpgp_crypto_hashData(this.hashAlgorithm,isp);
+			    return key + openpgp_crypto_hashData(this.hashAlgorithm,String.fromCharCode(0)+isp);
+			}
+			return openpgp_crypto_hashData(this.hashAlgorithm,isp);
+		} else return null;
+	}
+	
+	this.read = read;
+	this.write = write;
+	this.produce_key = produce_key;
+}
+// GPG4Browsers - An OpenPGP implementation in javascript
+// Copyright (C) 2011 Recurity Labs GmbH
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+// Hint: We hold our MPIs as an array of octets in big endian format preceeding a two
+// octet scalar: MPI: [a,b,c,d,e,f]
+// - MPI size: (a << 8) | b 
+// - MPI = c | d << 8 | e << ((MPI.length -2)*8) | f ((MPI.length -2)*8)
+
+/**
+ *  Implementation of type MPI (RFC4880 3.2)
+ *  Multiprecision integers (also called MPIs) are unsigned integers used
+ *  to hold large integers such as the ones used in cryptographic
+ *  calculations.
+ *  An MPI consists of two pieces: a two-octet scalar that is the length
+ *  of the MPI in bits followed by a string of octets that contain the
+ *  actual integer.
+ */
+function openpgp_type_mpi() {
+	this.MPI = null;
+	this.mpiBitLength = null;
+	this.mpiByteLength = null;
+	this.data = null;
+	/**
+	 * parsing function for a mpi (RFC 4880 3.2).
+	 * @param input [string] payload of mpi data
+	 * @param position [integer] position to start reading from the input string
+	 * @param len [integer] length of the packet or the remaining length of input at position
+	 * @return [openpgp_type_mpi] object representation
+	 */
+	function read(input, position, len) {
+		var mypos = position;
 		
-		var pos = position;
-		while (input.length > pos) {
-			var result = openpgp_packet.read_packet(input, pos, input.length - pos);
-			if (result == null) {
-				util.print_error("openpgp.msg.messge decrypt:\n"+'[pub/priv_key]parsing ends here @:' + pos + " l:" + len);
-				break;
-			} else {
-				switch (result.tagType) {
-				case 2: // public key revocation signature
-					if (result.signatureType == 32)
-						this.revocationSignatures[this.revocationSignatures.length] = result;
-					else if (result.signatureType > 15 && result.signatureType < 20) {
-						if (this.certificationsignatures == null)
-							this.certificationSignatures = new Array();
-						this.certificationSignatures[this.certificationSignatures.length] = result;
-					} else
-						util.print_error("openpgp.msg.messge decrypt:\n"+"unknown signature type directly on key "+result.signatureType+" @"+pos);
-					pos += result.packetLength + result.headerLength;
-					break;
-				case 7: // PrivateSubkey Packet
-					this.subKeys[this.subKeys.length] = result;
-					pos += result.packetLength + result.headerLength;
-					pos += result.read_nodes(this.privateKeyPacket,input, pos, input.length - pos);
-					break;
-				case 17: // User Attribute Packet
-					this.userAttributes[this.userAttributes.length] = result;
-					pos += result.packetLength + result.headerLength;
-					pos += result.read_nodes(this.privateKeyPacket,input, pos, input.length - pos);
-					break;
-				case 13: // User ID Packet
-					this.userIds[this.userIds.length] = result;
-					pos += result.packetLength + result.headerLength;
-					pos += result.read_nodes(this.privateKeyPacket, input, pos, input.length - pos);
-					break;
-				default:
-					this.position = position - this.privateKeyPacket.packetLength - this.privateKeyPacket.headerLength;
-					this.len = pos - position;
-					return this.len;
+		this.mpiBitLength = (input[mypos++].charCodeAt() << 8) | input[mypos++].charCodeAt();
+		
+		// Additional rules:
+		//
+		//    The size of an MPI is ((MPI.length + 7) / 8) + 2 octets.
+		//
+		//    The length field of an MPI describes the length starting from its
+		//	  most significant non-zero bit.  Thus, the MPI [00 02 01] is not
+		//    formed correctly.  It should be [00 01 01].
+
+		// TODO: Verification of this size method! This size calculation as
+		// 		 specified above is not applicable in JavaScript
+		this.mpiByteLength = (this.mpiBitLength - (this.mpiBitLength % 8)) / 8;
+		if (this.mpiBitLength % 8 != 0)
+			this.mpiByteLength++;
+		
+		this.MPI = input.substring(mypos,mypos+this.mpiByteLength);
+		this.data = input.substring(position, position+2+this.mpiByteLength);
+		this.packetLength = this.mpiByteLength +2;
+		return this;
+	}
+	
+	/**
+	 * generates debug output (pretty print)
+	 * @return String which gives some information about the mpi
+	 */
+	function toString() {
+		var r = "    MPI("+this.mpiBitLength+"b/"+this.mpiByteLength+"B) : 0x";
+		r+=util.hexstrdump(this.MPI);
+		return r+'\n';
+	}
+	
+	/**
+	 * converts the mpi to an BigInteger object
+	 * @return [BigInteger]
+	 */
+	function getBigInteger() {
+		return new BigInteger(util.hexstrdump(this.MPI),16); 
+	}
+
+	
+	function getBits(num) {
+		for (var i = 0; i < 9; i++)
+		if (num >> i == 0)
+		return i;
+	}
+	
+	/**
+	 * gets the length of the mpi in bytes
+	 * @return [integer] mpi byte length
+	 */
+	function getByteLength() {
+		return this.mpiByteLength;
+	}
+	
+	/**
+	 * creates an mpi from the specified string
+	 * @param data [String] data to read the mpi from
+	 * @return [openpgp_type_mpi] 
+	 */
+	function create(data) {
+		this.MPI = data;
+		this.mpiBitLength = (data.length -1) *8 + getBits(data.charCodeAt(0));
+		this.mpiByteLength = data.length;
+		return this;
+	}
+	
+	/**
+	 * converts the mpi object to a string as specified in RFC4880 3.2
+	 * @return [String] mpi byte representation
+	 */
+	function toBin() {
+		var result = String.fromCharCode((this.mpiBitLength >> 8) & 0xFF);
+		result += String.fromCharCode(this.mpiBitLength & 0xFF);
+		result += this.MPI;
+		return result;
+	}
+	
+	this.read = read;
+	this.toBigInteger = getBigInteger;
+	this.toString = toString;
+	this.create = create;
+	this.toBin = toBin;
+	this.getByteLength = getByteLength;
+}
+
+// GPG4Browsers - An OpenPGP implementation in javascript
+// Copyright (C) 2011 Recurity Labs GmbH
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+/**
+ * Implementation of type key id (RFC4880 3.3)
+ *  A Key ID is an eight-octet scalar that identifies a key.
+   Implementations SHOULD NOT assume that Key IDs are unique.  The
+   section "Enhanced Key Formats" below describes how Key IDs are
+   formed.
+ */
+function openpgp_type_keyid() {
+	/**
+	 * parsing method for a key id
+	 * @param input [String] input to read the key id from 
+	 * @param position [integer] position where to start reading the key id from input
+	 * @return this object
+	 */
+	function read_packet(input, position) {
+		this.bytes = input.substring(position, position+8);
+		return this;
+	}
+	
+	/**
+	 * generates debug output (pretty print)
+	 * @return [String] Key Id as hexadecimal string
+	 */
+	function toString() {
+		return util.hexstrdump(this.bytes);
+	}
+	
+	this.read_packet = read_packet;
+	this.toString = toString;
+};
+// GPG4Browsers - An OpenPGP implementation in javascript
+// Copyright (C) 2011 Recurity Labs GmbH
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+function openpgp_msg_message() {
+	
+	// -1 = no valid passphrase submitted
+	// -2 = no private key found
+	// -3 = decryption error
+	// text = valid decryption
+	this.text = "";
+	
+	/**
+	 * Decrypts a message and generates user interface message out of the found.
+	 * MDC will be verified as well as message signatures
+	 * @param private_key [openpgp_msg_privatekey] the private the message is encrypted with (corresponding to the session key)
+	 * @param sessionkey [openpgp_packet_encryptedsessionkey] the session key to be used to decrypt the message
+	 * @return [String] plaintext of the message or null on error
+	 */
+	function decrypt(private_key, sessionkey) {
+        return this.decryptAndVerifySignature(private_key, sessionkey).text;
+	}
+
+	/**
+	 * Decrypts a message and generates user interface message out of the found.
+	 * MDC will be verified as well as message signatures
+	 * @param private_key [openpgp_msg_privatekey] the private the message is encrypted with (corresponding to the session key)
+	 * @param sessionkey [openpgp_packet_encryptedsessionkey] the session key to be used to decrypt the message
+	 * @param pubkey [openpgp_msg_publickey] Array of public keys to check signature against. If not provided, checks local keystore.
+	 * @return [String] plaintext of the message or null on error
+	 */
+	function decryptAndVerifySignature(private_key, sessionkey, pubkey) {
+		if (private_key == null || sessionkey == null || sessionkey == "")
+			return null;
+		var decrypted = sessionkey.decrypt(this, private_key.keymaterial);
+		if (decrypted == null)
+			return null;
+		var packet;
+		var position = 0;
+		var len = decrypted.length;
+		var validSignatures = new Array();
+		util.print_debug_hexstr_dump("openpgp.msg.messge decrypt:\n",decrypted);
+
+		while (position != decrypted.length && (packet = openpgp_packet.read_packet(decrypted, position, len)) != null) {
+			if (packet.tagType == 8) {
+				this.text = packet.decompress();
+				decrypted = packet.decompress();
+			}
+			util.print_debug(packet.toString());
+			position += packet.headerLength+packet.packetLength;
+			if (position > 38)
+				util.print_debug_hexstr_dump("openpgp.msg.messge decrypt:\n",decrypted.substring(position));
+			len = decrypted.length - position;
+			if (packet.tagType == 11) {
+				this.text = packet.data;
+				util.print_info("message successfully decrypted");
+			}
+			if (packet.tagType == 19)
+				// ignore.. we checked that already in a more strict way.
+				continue;
+			if (packet.tagType == 2 && packet.signatureType < 3) {
+			    if(!pubkey || pubkey.length == 0 ){
+				    var pubkey = openpgp.keyring.getPublicKeysForKeyId(packet.issuerKeyId);
+				}
+				if (pubkey.length == 0) {
+					util.print_warning("Unable to verify signature of issuer: "+util.hexstrdump(packet.issuerKeyId)+". Public key not found in keyring.");
+					validSignatures[validSignatures.length] = false;
+				} else {
+					if(packet.verify(this.text.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"),pubkey[0]) && pubkey[0].obj.validate()){
+						util.print_info("Found Good Signature from "+pubkey[0].obj.userIds[0].text+" (0x"+util.hexstrdump(pubkey[0].obj.getKeyId()).substring(8)+")");
+    					validSignatures[validSignatures.length] = true;
+						}
+					else{
+						util.print_error("Signature verification failed: Bad Signature from "+pubkey[0].obj.userIds[0].text+" (0x"+util.hexstrdump(pubkey[0].obj.getKeyId()).substring(8)+")");
+    					validSignatures[validSignatures.length] = false;
+						}
 				}
 			}
 		}
-		this.position = position - this.privateKeyPacket.packetLength - this.privateKeyPacket.headerLength;
-		this.len = pos - position;
-		
-		return this.len;
+		if (this.text == "") {
+			this.text = decrypted;
+		}
+		return {text:this.text, validSignatures:validSignatures};
 	}
 	
-	function getKeyId() {
-		return this.privateKeyPacket.publicKey.getKeyId();
-	}
-	
-	
-	function getSubKeyIds() {
-		if (this.privateKeyPacket.publicKey.version == 4) // V3 keys MUST NOT have subkeys.
-		var result = new Array();
-		for (var i = 0; i < this.subKeys.length; i++) {
-			result[i] = str_sha1(this.subKeys[i].publicKey.header+this.subKeys[i].publicKey.data).substring(12,20);
+	/**
+	 * Verifies a message signature. This function can be called after read_message if the message was signed only.
+	 * @param pubkey [openpgp_msg_publickey] Array of public keys to check signature against. If not provided, checks local keystore.
+	 * @return [boolean] true if the signature was correct; otherwise false
+	 */
+	function verifySignature(pubkey) {
+		var result = false;
+		if (this.type == 2) {
+		    if(!pubkey || pubkey.length == 0){
+			    var pubkey;
+			    if (this.signature.version == 4) {
+				    pubkey = openpgp.keyring.getPublicKeysForKeyId(this.signature.issuerKeyId);
+			    } else if (this.signature.version == 3) {
+				    pubkey = openpgp.keyring.getPublicKeysForKeyId(this.signature.keyId);
+			    } else {
+				    util.print_error("unknown signature type on message!");
+				    return false;
+			    }
+			}
+			if (pubkey.length == 0)
+				util.print_warning("Unable to verify signature of issuer: "+util.hexstrdump(this.signature.issuerKeyId)+". Public key not found in keyring.");
+			else {
+				for (var i = 0 ; i < pubkey.length; i++) {
+					var tohash = this.text.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n");
+					if (this.signature.verify(tohash.substring(0, tohash.length -2), pubkey[i])) {
+						util.print_info("Found Good Signature from "+pubkey[i].obj.userIds[i].text+" (0x"+util.hexstrdump(pubkey[i].obj.getKeyId()).substring(8)+")");
+						result = true;
+					} else {
+						util.print_error("Signature verification failed: Bad Signature from "+pubkey[i].obj.userIds[0].text+" (0x"+util.hexstrdump(pubkey[0].obj.getKeyId()).substring(8)+")");
+					}
+				}
+			}
 		}
 		return result;
 	}
 	
-	
-	function getSigningKey() {
-		if ((this.privateKeyPacket.publicKey.publicKeyAlgorithm == 17 ||
-			 this.privateKeyPacket.publicKey.publicKeyAlgorithm != 2)
-			&& this.privateKeyPacket.publicKey.verifyKey() == 3)
-			return this.privateKeyPacket;
-		else if (this.privateKeyPacket.publicKey.version == 4) // V3 keys MUST NOT have subkeys.
-			for (var j = 0; j < this.privateKeyPacket.subKeys.length; j++) {
-				if ((this.privateKeyPacket.subKeys[j].publicKey.publicKeyAlgorithm == 17 ||
-					 this.privateKeyPacket.subKeys[j].publicKey.publicKeyAlgorithm != 2) &&
-					 this.privateKeyPacket.subKeys[j].publicKey.verifyKey() == 3)
-					return this.privateKeyPacket.subKeys[j];
-			}
-		return null;
-	}
-	
-	function getPreferredSignatureHashAlgorithm() {
-		var pkey = this.getSigningKey();
-		if (pkey == null) {
-			util.print_error("private key is for encryption only! Cannot create a signature.")
-			return null;
+	function toString() {
+		var result = "Session Keys:\n";
+		if (this.sessionKeys !=null)
+		for (var i = 0; i < this.sessionKeys.length; i++) {
+			result += this.sessionKeys[i].toString();
 		}
-		if (pkey.publicKey.publicKeyAlgorithm == 17) {
-			var dsa = new DSA();
-			return dsa.select_hash_algorithm(pkey.publicKey.MPIs[1].toBigInteger()); // q
-		}
-		return openpgp.config.config.prefer_hash_algorithm;
-			
-	}
-
-	function decryptSecretMPIs(str_passphrase) {
-		return this.privateKeyPacket.decryptSecretMPIs(str_passphrase);
-	}
-	
-	function getFingerprint() {
-		return this.privateKeyPacket.publicKey.getFingerprint();
-	}
-
-	// TODO need to implement this
-	function revoke() {
+		result += "\n\n EncryptedData:\n";
+		if(this.encryptedData != null)
+		result += this.encryptedData.toString();
 		
+		result += "\n\n Signature:\n";
+		if(this.signature != null)
+		result += this.signature.toString();
+		
+		result += "\n\n Text:\n"
+		if(this.signature != null)
+			result += this.text;
+		return result;
 	}
-	this.getSigningKey = getSigningKey;
-	this.getFingerprint = getFingerprint;
-	this.getPreferredSignatureHashAlgorithm = getPreferredSignatureHashAlgorithm;
-	this.read_nodes = read_nodes;
-	this.decryptSecretMPIs = decryptSecretMPIs;
-	this.getSubKeyIds = getSubKeyIds;
-	this.getKeyId = getKeyId;
-	
-}// GPG4Browsers - An OpenPGP implementation in javascript
-// Copyright (C) 2011 Recurity Labs GmbH
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-/**
- * Wrapper function for the base64 codec. 
- * This function encodes a String (message) in base64 (radix-64)
- * @param message [String] the message to encode
- * @return [String] the base64 encoded data
- */
-function openpgp_encoding_base64_encode(message) {
-	return s2r(message);
+	this.decrypt = decrypt;
+	this.decryptAndVerifySignature = decryptAndVerifySignature;
+	this.verifySignature = verifySignature;
+	this.toString = toString;
 }
-
-
-/**
- * Wrapper function for the base64 codec.
- * This function decodes a String(message) in base64 (radix-64)
- * @param message [String] base64 encoded data
- * @return [String] raw data after decoding
- */
-function openpgp_encoding_base64_decode(message) {
-	return r2s(message);
-}
-
-/**
- * Wrapper function for jquery library.
- * This function escapes HTML characters within a string. This is used to prevent XSS.
- * @param message [String] message to escape
- * @return [String] html encoded string
- */
-function openpgp_encoding_html_encode(message) {
-	if (message == null)
-		return "";
-	return $('<div/>').text(message).html();
-}
-
-/**
- * create a EME-PKCS1-v1_5 padding (See RFC4880 13.1.1)
- * @param message [String] message to be padded
- * @param length [Integer] length to the resulting message
- * @return [String] EME-PKCS1 padded message
- */
-function openpgp_encoding_eme_pkcs1_encode(message, length) {
-	if (message.length > length-11)
-		return -1;
-	var result = "";
-	result += String.fromCharCode(0);
-	result += String.fromCharCode(2);
-	for (var i = 0; i < length - message.length - 3; i++) {
-		result += String.fromCharCode(openpgp_crypto_getPseudoRandom(1,255));
-	}
-	result += String.fromCharCode(0);
-	result += message;
-	return result;
-}
-
-/**
- * decodes a EME-PKCS1-v1_5 padding (See RFC4880 13.1.2)
- * @param message [String] EME-PKCS1 padded message
- * @return [String] decoded message 
- */
-function openpgp_encoding_eme_pkcs1_decode(message, len) {
-	if (message.length < len)
-	    message = String.fromCharCode(0)+message;
-	if (message.length < 12 || message.charCodeAt(0) != 0 || message.charCodeAt(1) != 2)
-		return -1;
-	var i = 2;
-	while (message.charCodeAt(i) != 0 && message.length > i)
-	    i++;
-	return message.substring(i+1, message.length);
-}
-/**
- * ASN1 object identifiers for hashes (See RFC4880 5.2.2)
- */
-hash_headers = new Array();
-hash_headers[1]  = [0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x04,0x10];
-hash_headers[3]  = [0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x24,0x03,0x02,0x01,0x05,0x00,0x04,0x14];
-hash_headers[2]  = [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14];
-hash_headers[8]  = [0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20];
-hash_headers[9]  = [0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30];
-hash_headers[10] = [0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40];
-hash_headers[11] = [0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04,0x05,0x00,0x04,0x1C];
-
-/**
- * create a EMSA-PKCS1-v1_5 padding (See RFC4880 13.1.3)
- * @param algo [Integer] hash algorithm type used
- * @param data [String] data to be hashed
- * @param keylength [Integer] key size of the public mpi in bytes
- * @return the [String] hashcode with pkcs1padding as string
- */
-function openpgp_encoding_emsa_pkcs1_encode(algo, data, keylength) {
-	var data2 = "";
-	data2 += String.fromCharCode(0x00);
-	data2 += String.fromCharCode(0x01);
-	for (var i = 0; i < (keylength - hash_headers[algo].length - 3 - openpgp_crypto_getHashByteLength(algo)); i++)
-		data2 += String.fromCharCode(0xff);
-	data2 += String.fromCharCode(0x00);
-	
-	for (var i = 0; i < hash_headers[algo].length; i++)
-		data2 += String.fromCharCode(hash_headers[algo][i]);
-	
-	data2 += openpgp_crypto_hashData(algo, data);
-	return new BigInteger(util.hexstrdump(data2),16);
-}
-
-/**
- * extract the hash out of an EMSA-PKCS1-v1.5 padding (See RFC4880 13.1.3) 
- * @param data [String] hash in pkcs1 encoding
- * @return the hash as string
- */
-function openpgp_encoding_emsa_pkcs1_decode(algo, data) { 
-	var i = 0;
-	if (data.charCodeAt(0) == 0) i++;
-	else if (data.charCodeAt(0) != 1) return -1;
-	else i++;
-
-	while (data.charCodeAt(i) == 0xFF) i++;
-	if (data.charCodeAt(i++) != 0) return -1;
-	var j = 0;
-	for (j = 0; j < hash_headers[algo].length && j+i < data.length; j++) {
-		if (data.charCodeAt(j+i) != hash_headers[algo][j]) return -1;
-	}
-	i+= j;	
-	if (data.substring(i).length < openpgp_crypto_getHashByteLength(algo)) return -1;
-	return data.substring(i);
-}/* OpenPGP radix-64/base64 string encoding/decoding
- * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de
- * version 1.0, check www.haneWIN.de for the latest version
- *
- * This software is provided as-is, without express or implied warranty.  
- * Permission to use, copy, modify, distribute or sell this software, with or
- * without fee, for any purpose and by any individual or organization, is hereby
- * granted, provided that the above copyright notice and this paragraph appear 
- * in all copies. Distribution as a part of an application or binary must
- * include the above copyright notice in the documentation and/or other materials
- * provided with the application or distribution.
- */
-
-var b64s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
-
-function s2r(t) {
-	var a, c, n;
-	var r = '', l = 0, s = 0;
-	var tl = t.length;
-
-	for (n = 0; n < tl; n++) {
-		c = t.charCodeAt(n);
-		if (s == 0) {
-			r += b64s.charAt((c >> 2) & 63);
-			a = (c & 3) << 4;
-		} else if (s == 1) {
-			r += b64s.charAt((a | (c >> 4) & 15));
-			a = (c & 15) << 2;
-		} else if (s == 2) {
-			r += b64s.charAt(a | ((c >> 6) & 3));
-			l += 1;
-			if ((l % 60) == 0)
-				r += "\n";
-			r += b64s.charAt(c & 63);
-		}
-		l += 1;
-		if ((l % 60) == 0)
-			r += "\n";
-
-		s += 1;
-		if (s == 3)
-			s = 0;
-	}
-	if (s > 0) {
-		r += b64s.charAt(a);
-		l += 1;
-		if ((l % 60) == 0)
-			r += "\n";
-		r += '=';
-		l += 1;
-	}
-	if (s == 1) {
-		if ((l % 60) == 0)
-			r += "\n";
-		r += '=';
-	}
-
-	return r;
-}
-
-function r2s(t) {
-	var c, n;
-	var r = '', s = 0, a = 0;
-	var tl = t.length;
-
-	for (n = 0; n < tl; n++) {
-		c = b64s.indexOf(t.charAt(n));
-		if (c >= 0) {
-			if (s)
-				r += String.fromCharCode(a | (c >> (6 - s)) & 255);
-			s = (s + 2) & 7;
-			a = (c << s) & 255;
-		}
-	}
-	return r;
-}
 // GPG4Browsers - An OpenPGP implementation in javascript
 // Copyright (C) 2011 Recurity Labs GmbH
-//
+// 
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // License as published by the Free Software Foundation; either
 // version 2.1 of the License, or (at your option) any later version.
-//
+// 
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 // Lesser General Public License for more details.
-//
+// 
 // You should have received a copy of the GNU Lesser General Public
 // License along with this library; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
-/**
- * DeArmor an OpenPGP armored message; verify the checksum and return the encoded bytes
- * @text [String] OpenPGP armored message
- * @return either the bytes of the decoded message or an object with attribute "text" containing the message text
- * and an attribute "openpgp" containing the bytes.
- */
-function openpgp_encoding_deArmor(text) {
-	var type = getPGPMessageType(text);
-	if (type != 2) {
-	var splittedtext = text.split('-----');
-	data = { openpgp: openpgp_encoding_base64_decode(splittedtext[2].split('\n\n')[1].split("\n=")[0].replace(/\n- /g,"\n")),
-			type: type};
-	if (verifyCheckSum(data.openpgp, splittedtext[2].split('\n\n')[1].split("\n=")[1].split('\n')[0]))
-		return data;
-	else
-		util.print_error("Ascii armor integrity check on message failed: '"+splittedtext[2].split('\n\n')[1].split("\n=")[1].split('\n')[0]+"' should be '"+getCheckSum(data))+"'";
-	} else {
-		var splittedtext = text.split('-----');
-		var result = { text: splittedtext[2].replace(/\n- /g,"\n").split("\n\n")[1],
-		               openpgp: openpgp_encoding_base64_decode(splittedtext[4].split("\n\n")[1].split("\n=")[0]),
-		               type: type};
-		if (verifyCheckSum(result.openpgp, splittedtext[4].split("\n\n")[1].split("\n=")[1]))
-				return result;
-		else
-			util.print_error("Ascii armor integrity check on message failed");
-	}
-}
+var Util = function() {
+
+    this.emailRegEx = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
+	
+	this.hexdump = function(str) {
+	    var r=[];
+	    var e=str.length;
+	    var c=0;
+	    var h;
+	    var i = 0;
+	    while(c<e){
+	        h=str.charCodeAt(c++).toString(16);
+	        while(h.length<2) h="0"+h;
+	        r.push(" "+h);
+	        i++;
+	        if (i % 32 == 0)
+	        	r.push("\n           ");
+	    }
+	    return r.join('');
+	};
+	
+	/**
+	 * create hexstring from a binary
+	 * @param str [String] string to convert
+	 * @return [String] string containing the hexadecimal values
+	 */
+	this.hexstrdump = function(str) {
+		if (str == null)
+			return "";
+	    var r=[];
+	    var e=str.length;
+	    var c=0;
+	    var h;
+	    while(c<e){
+	        h=str[c++].charCodeAt().toString(16);
+	        while(h.length<2) h="0"+h;
+	        r.push(""+h);
+	    }
+	    return r.join('');
+	};
+	
+	/**
+	 * create binary string from a hex encoded string
+	 * @param str [String] hex string to convert
+	 * @return [String] string containing the binary values
+	 */
+	this.hex2bin = function(hex) {
+	    var str = '';
+	    for (var i = 0; i < hex.length; i += 2)
+	        str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
+	    return str;
+	};
+	
+	/**
+	 * creating a hex string from an binary array of integers (0..255)
+	 * @param [Array[integer 0..255]] array to convert
+	 * @return [String] hexadecimal representation of the array
+	 */
+	this.hexidump = function(str) {
+	    var r=[];
+	    var e=str.length;
+	    var c=0;
+	    var h;
+	    while(c<e){
+	        h=str[c++].toString(16);
+	        while(h.length<2) h="0"+h;
+	        r.push(""+h);
+	    }
+	    return r.join('');
+	};
+	
+	/**
+	 * convert a string to an array of integers(0.255)
+	 * @param [String] string to convert
+	 * @return [Array [Integer 0..255]] array of (binary) integers
+	 */
+	this.str2bin = function(str) {
+		var result = new Array();
+		for (var i = 0; i < str.length; i++) {
+			result[i] = str.charCodeAt(i);
+		}
+		
+		return result;
+	};
+
+	/**
+	 * convert an array of integers(0.255) to a string 
+	 * @param [Array [Integer 0..255]] array of (binary) integers to convert
+	 * @return [String] string representation of the array
+	 */
+	this.bin2str = function(bin) {
+		var result = [];
+		for (var i = 0; i < bin.length; i++) {
+			result.push(String.fromCharCode(bin[i]));
+		}
+		return result.join('');
+	};
+	
+	/**
+	 * convert a string to a Uint8Array
+	 * @param [String] string to convert
+	 * @return [Uint8Array] array of (binary) integers
+	 */
+	this.str2Uint8Array = function(str){
+        var uintArray = new Uint8Array(new ArrayBuffer(str.length));
+        for(var n = 0; n < str.length; n++){
+            uintArray[n] = str.charCodeAt(n);
+        }
+        return uintArray;
+	};
+	
+	/**
+	 * convert a Uint8Array to a string. This currently functions the same as bin2str. 
+	 * @param [Uint8Array] array of (binary) integers to convert
+	 * @return [String] string representation of the array
+	 */
+	this.Uint8Array2str = function(bin) {
+        var result = [];
+        for(n = 0; n< bin.length; n++){
+            result[n] = String.fromCharCode(bin[n]);
+        }
+        return result.join('');
+	};
+	
+	/**
+	 * calculates a 16bit sum of a string by adding each character codes modulus 65535
+	 * @param text [String] string to create a sum of
+	 * @return [Integer] an integer containing the sum of all character codes % 65535
+	 */
+	this.calc_checksum = function(text) {
+		var checksum = {  s: 0, add: function (sadd) { this.s = (this.s + sadd) % 65536; }};
+		for (var i = 0; i < text.length; i++) {
+			checksum.add(text.charCodeAt(i));
+		}
+		return checksum.s;
+	};
+	
+	/**
+	 * Helper function to print a debug message. Debug 
+	 * messages are only printed if
+	 * openpgp.config.debug is set to true. The calling
+	 * Javascript context MUST define
+	 * a "showMessages(text)" function. Line feeds ('\n')
+	 * are automatically converted to HTML line feeds '<br/>'
+	 * @param str [String] string of the debug message
+	 * @return [String] an HTML tt entity containing a paragraph with a style attribute where the debug message is HTMLencoded in. 
+	 */
+	this.print_debug = function(str) {
+		if (openpgp.config.debug) {
+			str = openpgp_encoding_html_encode(str);
+			showMessages("<tt><p style=\"background-color: #ffffff; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;\">"+str.replace(/\n/g,"<br>")+"</p></tt>");
+		}
+	};
+	
+	/**
+	 * Helper function to print a debug message. Debug 
+	 * messages are only printed if
+	 * openpgp.config.debug is set to true. The calling
+	 * Javascript context MUST define
+	 * a "showMessages(text)" function. Line feeds ('\n')
+	 * are automatically converted to HTML line feeds '<br/>'
+	 * Different than print_debug because will call hexstrdump iff necessary.
+	 * @param str [String] string of the debug message
+	 * @return [String] an HTML tt entity containing a paragraph with a style attribute where the debug message is HTMLencoded in. 
+	 */
+	this.print_debug_hexstr_dump = function(str,strToHex) {
+		if (openpgp.config.debug) {
+			str = str + this.hexstrdump(strToHex);
+			str = openpgp_encoding_html_encode(str);
+			showMessages("<tt><p style=\"background-color: #ffffff; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;\">"+str.replace(/\n/g,"<br>")+"</p></tt>");
+		}
+	};
+	
+	/**
+	 * Helper function to print an error message. 
+	 * The calling Javascript context MUST define
+	 * a "showMessages(text)" function. Line feeds ('\n')
+	 * are automatically converted to HTML line feeds '<br/>'
+	 * @param str [String] string of the error message
+	 * @return [String] a HTML paragraph entity with a style attribute containing the HTML encoded error message
+	 */
+	this.print_error = function(str) {
+		str = openpgp_encoding_html_encode(str);
+		showMessages("<p style=\"font-size: 80%; background-color: #FF8888; margin:0; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;\"><span style=\"color: #888;\"><b>ERROR:</b></span>	"+str.replace(/\n/g,"<br>")+"</p>");
+	};
+	
+	/**
+	 * Helper function to print an info message. 
+	 * The calling Javascript context MUST define
+	 * a "showMessages(text)" function. Line feeds ('\n')
+	 * are automatically converted to HTML line feeds '<br/>'.
+	 * @param str [String] string of the info message
+	 * @return [String] a HTML paragraph entity with a style attribute containing the HTML encoded info message
+	 */
+	this.print_info = function(str) {
+		str = openpgp_encoding_html_encode(str);
+		showMessages("<p style=\"font-size: 80%; background-color: #88FF88; margin:0; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;\"><span style=\"color: #888;\"><b>INFO:</b></span>	"+str.replace(/\n/g,"<br>")+"</p>");
+	};
+	
+	this.print_warning = function(str) {
+		str = openpgp_encoding_html_encode(str);
+		showMessages("<p style=\"font-size: 80%; background-color: #FFAA88; margin:0; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;\"><span style=\"color: #888;\"><b>WARNING:</b></span>	"+str.replace(/\n/g,"<br>")+"</p>");
+	};
+	
+	this.getLeftNBits = function (string, bitcount) {
+		var rest = bitcount % 8;
+		if (rest == 0)
+			return string.substring(0, bitcount / 8);
+		var bytes = (bitcount - rest) / 8 +1;
+		var result = string.substring(0, bytes);
+		return this.shiftRight(result, 8-rest); // +String.fromCharCode(string.charCodeAt(bytes -1) << (8-rest) & 0xFF);
+	};
+	/**
+	 * Shifting a string to n bits right
+	 * @param value [String] the string to shift
+	 * @param bitcount [Integer] amount of bits to shift (MUST be smaller than 9)
+	 * @return [String] resulting string. 
+	 */
+	this.shiftRight = function(value, bitcount) {
+		var temp = util.str2bin(value);
+        if (bitcount % 8 != 0) {
+        	for (var i = temp.length-1; i >= 0; i--) {
+        		temp[i] >>= bitcount % 8;
+        		if (i > 0)
+        			temp[i] |= (temp[i - 1] << (8 - (bitcount % 8))) & 0xFF;
+        	}
+        } else {
+        	return value;
+        }
+        return util.bin2str(temp);
+	};
+	
+	/**
+	 * Return the algorithm type as string
+	 * @return [String] String representing the message type
+	 */
+	this.get_hashAlgorithmString = function(algo) {
+		switch(algo) {
+		case 1:
+			return "MD5";
+		case 2:
+			return "SHA1";
+		case 3:
+			return "RIPEMD160";
+		case 8:
+			return "SHA256";
+		case 9:
+			return "SHA384";
+		case 10:
+			return "SHA512";
+		case 11:
+			return "SHA224";
+		}
+		return "unknown";
+	};
+};
 
 /**
- * Finds out which Ascii Armoring type is used. This is an internal function
- * @param text [String] ascii armored text
- * @return 0 = MESSAGE PART n of m
- *         1 = MESSAGE PART n
- *         2 = SIGNED MESSAGE
- *         3 = PGP MESSAGE
- *         4 = PUBLIC KEY BLOCK
- *         5 = PRIVATE KEY BLOCK
- *         null = unknown
+ * an instance that should be used. 
  */
-function getPGPMessageType(text) {
-	var splittedtext = text.split('-----');
-	// BEGIN PGP MESSAGE, PART X/Y
-	// Used for multi-part messages, where the armor is split amongst Y
-	// parts, and this is the Xth part out of Y.
-	if (splittedtext[1].match(/BEGIN PGP MESSAGE, PART \d+\/\d+/)) {
-		return 0;
-	} else
-		// BEGIN PGP MESSAGE, PART X
-		// Used for multi-part messages, where this is the Xth part of an
-		// unspecified number of parts. Requires the MESSAGE-ID Armor
-		// Header to be used.
-	if (splittedtext[1].match(/BEGIN PGP MESSAGE, PART \d+/)) {
-		return 1;
-
-	} else
-		// BEGIN PGP SIGNATURE
-		// Used for detached signatures, OpenPGP/MIME signatures, and
-		// cleartext signatures. Note that PGP 2.x uses BEGIN PGP MESSAGE
-		// for detached signatures.
-	if (splittedtext[1].match(/BEGIN PGP SIGNED MESSAGE/)) {
-		return 2;
-
-	} else
-  	    // BEGIN PGP MESSAGE
-	    // Used for signed, encrypted, or compressed files.
-	if (splittedtext[1].match(/BEGIN PGP MESSAGE/)) {
-		return 3;
-
-	} else
-		// BEGIN PGP PUBLIC KEY BLOCK
-		// Used for armoring public keys.
-	if (splittedtext[1].match(/BEGIN PGP PUBLIC KEY BLOCK/)) {
-		return 4;
-
-	} else
-		// BEGIN PGP PRIVATE KEY BLOCK
-		// Used for armoring private keys.
-	if (splittedtext[1].match(/BEGIN PGP PRIVATE KEY BLOCK/)) {
-		return 5;
-	}
-}
-
-/**
- * Add additional information to the armor version of an OpenPGP binary
- * packet block.
- * @author  Alex
- * @version 2011-12-16
- * @return  The header information
- */
-function openpgp_encoding_armor_addheader() {
-    var result = "";
-	if (openpgp.config.config.show_version) {
-        result += "Version: "+openpgp.config.versionstring+'\r\n';
-    }
-	if (openpgp.config.config.show_comment) {
-        result += "Comment: "+openpgp.config.commentstring+'\r\n';
-    }
-    result += '\r\n';
-    return result;
-}
-
-/**
- * Armor an OpenPGP binary packet block
- * @param messagetype type of the message
- * @param data
- * @param partindex
- * @param parttotal
- * @return {string} Armored text
- */
-function openpgp_encoding_armor(messagetype, data, partindex, parttotal) {
-	var result = "";
-	switch(messagetype) {
-	case 0:
-		result += "-----BEGIN PGP MESSAGE, PART "+partindex+"/"+parttotal+"-----\r\n";
-		result += openpgp_encoding_armor_addheader();
-		result += openpgp_encoding_base64_encode(data);
-		result += "\r\n="+getCheckSum(data)+"\r\n";
-		result += "-----END PGP MESSAGE, PART "+partindex+"/"+parttotal+"-----\r\n";
-		break;
-	case 1:
-		result += "-----BEGIN PGP MESSAGE, PART "+partindex+"-----\r\n";
-		result += openpgp_encoding_armor_addheader();
-		result += openpgp_encoding_base64_encode(data);
-		result += "\r\n="+getCheckSum(data)+"\r\n";
-		result += "-----END PGP MESSAGE, PART "+partindex+"-----\r\n";
-		break;
-	case 2:
-		result += "\r\n-----BEGIN PGP SIGNED MESSAGE-----\r\nHash: "+data.hash+"\r\n\r\n";
-		result += data.text.replace(/\n-/g,"\n- -");
-		result += "\r\n-----BEGIN PGP SIGNATURE-----\r\n";
-		result += openpgp_encoding_armor_addheader();
-		result += openpgp_encoding_base64_encode(data.openpgp);
-		result += "\r\n="+getCheckSum(data.openpgp)+"\r\n";
-		result += "-----END PGP SIGNATURE-----\r\n";
-		break;
-	case 3:
-		result += "-----BEGIN PGP MESSAGE-----\r\n";
-		result += openpgp_encoding_armor_addheader();
-		result += openpgp_encoding_base64_encode(data);
-		result += "\r\n="+getCheckSum(data)+"\r\n";
-		result += "-----END PGP MESSAGE-----\r\n";
-		break;
-	case 4:
-		result += "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n";
-		result += openpgp_encoding_armor_addheader();
-		result += openpgp_encoding_base64_encode(data);
-		result += "\r\n="+getCheckSum(data)+"\r\n";
-		result += "-----END PGP PUBLIC KEY BLOCK-----\r\n\r\n";
-		break;
-	case 5:
-		result += "-----BEGIN PGP PRIVATE KEY BLOCK-----\r\n";
-		result += openpgp_encoding_armor_addheader();
-		result += openpgp_encoding_base64_encode(data);
-		result += "\r\n="+getCheckSum(data)+"\r\n";
-		result += "-----END PGP PRIVATE KEY BLOCK-----\r\n";
-		break;
-	}
-
-	return result;
-}
-
-/**
- * Calculates a checksum over the given data and returns it base64 encoded
- * @param data [String] data to create a CRC-24 checksum for
- * @return [String] base64 encoded checksum
- */
-function getCheckSum(data) {
-	var c = createcrc24(data);
-	var str = "" + String.fromCharCode(c >> 16)+
-				   String.fromCharCode((c >> 8) & 0xFF)+
-				   String.fromCharCode(c & 0xFF);
-	return openpgp_encoding_base64_encode(str);
-}
-
-/**
- * Calculates the checksum over the given data and compares it with the given base64 encoded checksum
- * @param data [String] data to create a CRC-24 checksum for
- * @param checksum [String] base64 encoded checksum
- * @return true if the given checksum is correct; otherwise false
- */
-function verifyCheckSum(data, checksum) {
-	var c = getCheckSum(data);
-	var d = checksum;
-	return c[0] == d[0] && c[1] == d[1] && c[2] == d[2];
-}
-/**
- * Internal function to calculate a CRC-24 checksum over a given string (data)
- * @param data [String] data to create a CRC-24 checksum for
- * @return [Integer] the CRC-24 checksum as number
- */
-var crc_table = [
-0x00000000, 0x00864cfb, 0x018ad50d, 0x010c99f6, 0x0393e6e1, 0x0315aa1a, 0x021933ec, 0x029f7f17, 0x07a18139, 0x0727cdc2, 0x062b5434, 0x06ad18cf, 0x043267d8, 0x04b42b23, 0x05b8b2d5, 0x053efe2e, 0x0fc54e89, 0x0f430272, 0x0e4f9b84, 0x0ec9d77f, 0x0c56a868, 0x0cd0e493, 0x0ddc7d65, 0x0d5a319e, 0x0864cfb0, 0x08e2834b, 0x09ee1abd, 0x09685646, 0x0bf72951, 0x0b7165aa, 0x0a7dfc5c, 0x0afbb0a7, 0x1f0cd1e9, 0x1f8a9d12, 0x1e8604e4, 0x1e00481f, 0x1c9f3708, 0x1c197bf3, 0x1d15e205, 0x1d93aefe, 0x18ad50d0, 0x182b1c2b, 0x192785dd, 0x19a1c926, 0x1b3eb631, 0x1bb8faca, 0x1ab4633c, 0x1a322fc7, 0x10c99f60, 0x104fd39b, 0x11434a6d, 0x11c50696, 0x135a7981, 0x13dc357a, 0x12d0ac8c, 0x1256e077, 0x17681e59, 0x17ee52a2, 0x16e2cb54, 0x166487af, 0x14fbf8b8, 0x147db443, 0x15712db5, 0x15f7614e, 0x3e19a3d2, 0x3e9fef29, 0x3f9376df, 0x3f153a24, 0x3d8a4533, 0x3d0c09c8, 0x3c00903e, 0x3c86dcc5, 0x39b822eb, 0x393e6e10, 0x3832f7e6, 0x38b4bb1d, 0x3a2bc40a, 0x3aad88f1, 0x3ba11107, 0x3b275dfc, 0x31dced5b, 0x315aa1a0,
-0x30563856, 0x30d074ad, 0x324f0bba, 0x32c94741, 0x33c5deb7, 0x3343924c, 0x367d6c62, 0x36fb2099, 0x37f7b96f, 0x3771f594, 0x35ee8a83, 0x3568c678, 0x34645f8e, 0x34e21375, 0x2115723b, 0x21933ec0, 0x209fa736, 0x2019ebcd, 0x228694da, 0x2200d821, 0x230c41d7, 0x238a0d2c, 0x26b4f302, 0x2632bff9, 0x273e260f, 0x27b86af4, 0x252715e3, 0x25a15918, 0x24adc0ee, 0x242b8c15, 0x2ed03cb2, 0x2e567049, 0x2f5ae9bf, 0x2fdca544, 0x2d43da53, 0x2dc596a8, 0x2cc90f5e, 0x2c4f43a5, 0x2971bd8b, 0x29f7f170, 0x28fb6886, 0x287d247d, 0x2ae25b6a, 0x2a641791, 0x2b688e67, 0x2beec29c, 0x7c3347a4, 0x7cb50b5f, 0x7db992a9, 0x7d3fde52, 0x7fa0a145, 0x7f26edbe, 0x7e2a7448, 0x7eac38b3, 0x7b92c69d, 0x7b148a66, 0x7a181390, 0x7a9e5f6b, 0x7801207c, 0x78876c87, 0x798bf571, 0x790db98a, 0x73f6092d, 0x737045d6, 0x727cdc20, 0x72fa90db, 0x7065efcc, 0x70e3a337, 0x71ef3ac1, 0x7169763a, 0x74578814, 0x74d1c4ef, 0x75dd5d19, 0x755b11e2, 0x77c46ef5, 0x7742220e, 0x764ebbf8, 0x76c8f703, 0x633f964d, 0x63b9dab6, 0x62b54340, 0x62330fbb,
-0x60ac70ac, 0x602a3c57, 0x6126a5a1, 0x61a0e95a, 0x649e1774, 0x64185b8f, 0x6514c279, 0x65928e82, 0x670df195, 0x678bbd6e, 0x66872498, 0x66016863, 0x6cfad8c4, 0x6c7c943f, 0x6d700dc9, 0x6df64132, 0x6f693e25, 0x6fef72de, 0x6ee3eb28, 0x6e65a7d3, 0x6b5b59fd, 0x6bdd1506, 0x6ad18cf0, 0x6a57c00b, 0x68c8bf1c, 0x684ef3e7, 0x69426a11, 0x69c426ea, 0x422ae476, 0x42aca88d, 0x43a0317b, 0x43267d80, 0x41b90297, 0x413f4e6c, 0x4033d79a, 0x40b59b61, 0x458b654f, 0x450d29b4, 0x4401b042, 0x4487fcb9, 0x461883ae, 0x469ecf55, 0x479256a3, 0x47141a58, 0x4defaaff, 0x4d69e604, 0x4c657ff2, 0x4ce33309, 0x4e7c4c1e, 0x4efa00e5, 0x4ff69913, 0x4f70d5e8, 0x4a4e2bc6, 0x4ac8673d, 0x4bc4fecb, 0x4b42b230, 0x49ddcd27, 0x495b81dc, 0x4857182a, 0x48d154d1, 0x5d26359f, 0x5da07964, 0x5cace092, 0x5c2aac69, 0x5eb5d37e, 0x5e339f85, 0x5f3f0673, 0x5fb94a88, 0x5a87b4a6, 0x5a01f85d, 0x5b0d61ab, 0x5b8b2d50, 0x59145247, 0x59921ebc, 0x589e874a, 0x5818cbb1, 0x52e37b16, 0x526537ed, 0x5369ae1b, 0x53efe2e0, 0x51709df7, 0x51f6d10c,
-0x50fa48fa, 0x507c0401, 0x5542fa2f, 0x55c4b6d4, 0x54c82f22, 0x544e63d9, 0x56d11cce, 0x56575035, 0x575bc9c3, 0x57dd8538];
-
-function createcrc24(input) {
-  var crc = 0xB704CE;
-  var index = 0;
-
-  while((input.length - index) > 16)  {
-   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index)) & 0xff];
-   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+1)) & 0xff];
-   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+2)) & 0xff];
-   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+3)) & 0xff];
-   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+4)) & 0xff];
-   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+5)) & 0xff];
-   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+6)) & 0xff];
-   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+7)) & 0xff];
-   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+8)) & 0xff];
-   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+9)) & 0xff];
-   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+10)) & 0xff];
-   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+11)) & 0xff];
-   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+12)) & 0xff];
-   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+13)) & 0xff];
-   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+14)) & 0xff];
-   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+15)) & 0xff];
-   index += 16;
-  }
-
-  for(var j = index; j < input.length; j++) {
-   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index++)) & 0xff]
-  }
-  return crc & 0xffffff;
-}
-
+var util = new Util();
 JXG = {exists: (function(undefined){return function(v){return !(v===undefined || v===null);}})()};
 JXG.decompress = function(str) {return unescape((new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(str))).unzip()[0][0]);};
 /*
@@ -11521,7 +5323,20 @@ JXG.Util.Unzip.prototype.unzipFile = function(name) {
 	}
 	
   };
-    
+
+JXG.Util.Unzip.prototype.deflate = function() {
+    outputArr = [];
+    var tmp = [];
+    modeZIP = false;
+    DeflateLoop();
+    if (debug)
+        alert(outputArr.join(''));
+    unzipped[files] = new Array(2);
+    unzipped[files][0] = outputArr.join('');
+    unzipped[files][1] = "DEFLATE";
+    files++;
+    return unzipped;
+}    
     
 JXG.Util.Unzip.prototype.unzip = function() {
 	//convertToByteArray(input);
@@ -14299,447 +8114,6072 @@ JXG.Util.genUUID = function() {
 // 
 // You should have received a copy of the GNU Lesser General Public
 // License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA 
 
-function openpgp_msg_message() {
-	
-	// -1 = no valid passphrase submitted
-	// -2 = no private key found
-	// -3 = decryption error
-	// text = valid decryption
-	this.text = "";
-	
-	/**
-	 * Decrypts a message and generates user interface message out of the found.
-	 * MDC will be verified as well as message signatures
-	 * @param private_key [openpgp_msg_privatekey] the private the message is encrypted with (corresponding to the session key)
-	 * @param sessionkey [openpgp_packet_encryptedsessionkey] the session key to be used to decrypt the message
-	 * @return [String] plaintext of the message or null on error
-	 */
-	function decrypt(private_key, sessionkey) {
-        return this.decryptAndVerifySignature(private_key, sessionkey).text;
-	}
+// The GPG4Browsers symmetric crypto interface
 
-	/**
-	 * Decrypts a message and generates user interface message out of the found.
-	 * MDC will be verified as well as message signatures
-	 * @param private_key [openpgp_msg_privatekey] the private the message is encrypted with (corresponding to the session key)
-	 * @param sessionkey [openpgp_packet_encryptedsessionkey] the session key to be used to decrypt the message
-	 * @param pubkey [openpgp_msg_publickey] Array of public keys to check signature against. If not provided, checks local keystore.
-	 * @return [String] plaintext of the message or null on error
-	 */
-	function decryptAndVerifySignature(private_key, sessionkey, pubkey) {
-		if (private_key == null || sessionkey == null || sessionkey == "")
+/**
+ * Symmetrically encrypts data using prefixedrandom, a key with length 
+ * depending on the algorithm in openpgp_cfb mode with or without resync
+ * (MDC style)
+ * @param prefixrandom secure random bytes as string in length equal to the
+ * block size of the algorithm used (use openpgp_crypto_getPrefixRandom(algo)
+ * to retrieve that string
+ * @param algo [Integer] algorithm to use (see RFC4880 9.2)
+ * @param key [String] key as string. length is depending on the algorithm used
+ * @param data [String] data to encrypt
+ * @param openpgp_cfb [boolean]
+ * @return [String] encrypted data
+ */
+function openpgp_crypto_symmetricEncrypt(prefixrandom, algo, key, data, openpgp_cfb) {
+	switch(algo) {
+		case 0: // Plaintext or unencrypted data
+			return data; // blockcipherencryptfn, plaintext, block_size, key
+		case 2: // TripleDES (DES-EDE, [SCHNEIER] [HAC] - 168 bit key derived from 192)
+			return openpgp_cfb_encrypt(prefixrandom, desede, data,8,key, openpgp_cfb).substring(0, data.length + 10);
+		case 3: // CAST5 (128 bit key, as per [RFC2144])
+			return openpgp_cfb_encrypt(prefixrandom, cast5_encrypt, data,8,key, openpgp_cfb).substring(0, data.length + 10);
+		case 4: // Blowfish (128 bit key, 16 rounds) [BLOWFISH]
+			return openpgp_cfb_encrypt(prefixrandom, BFencrypt, data,8,key, openpgp_cfb).substring(0, data.length + 10);
+		case 7: // AES with 128-bit key [AES]
+		case 8: // AES with 192-bit key
+		case 9: // AES with 256-bit key
+			return openpgp_cfb_encrypt(prefixrandom, AESencrypt, data, 16, keyExpansion(key), openpgp_cfb).substring(0, data.length + 18);
+		case 10: // Twofish with 256-bit key [TWOFISH]
+			return openpgp_cfb_encrypt(prefixrandom, TFencrypt, data,16, key, openpgp_cfb).substring(0, data.length + 18);
+		case 1: // IDEA [IDEA]
+			util.print_error("IDEA Algorithm not implemented");
 			return null;
-		var decrypted = sessionkey.decrypt(this, private_key.keymaterial);
-		if (decrypted == null)
-			return null;
-		var packet;
-		var position = 0;
-		var len = decrypted.length;
-		var validSignatures = new Array();
-		util.print_debug_hexstr_dump("openpgp.msg.messge decrypt:\n",decrypted);
-
-		while (position != decrypted.length && (packet = openpgp_packet.read_packet(decrypted, position, len)) != null) {
-			if (packet.tagType == 8) {
-				this.text = packet.decompress();
-				decrypted = packet.decompress();
-			}
-			util.print_debug(packet.toString());
-			position += packet.headerLength+packet.packetLength;
-			if (position > 38)
-				util.print_debug_hexstr_dump("openpgp.msg.messge decrypt:\n",decrypted.substring(position));
-			len = decrypted.length - position;
-			if (packet.tagType == 11) {
-				this.text = packet.data;
-				util.print_info("message successfully decrypted");
-			}
-			if (packet.tagType == 19)
-				// ignore.. we checked that already in a more strict way.
-				continue;
-			if (packet.tagType == 2 && packet.signatureType < 3) {
-			    if(!pubkey || pubkey.length == 0 ){
-				    var pubkey = openpgp.keyring.getPublicKeysForKeyId(packet.issuerKeyId);
-				}
-				if (pubkey.length == 0) {
-					util.print_warning("Unable to verify signature of issuer: "+util.hexstrdump(packet.issuerKeyId)+". Public key not found in keyring.");
-					validSignatures[validSignatures.length] = false;
-				} else {
-					if(packet.verify(this.text.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"),pubkey[0]) && pubkey[0].obj.validate()){
-						util.print_info("Found Good Signature from "+pubkey[0].obj.userIds[0].text+" (0x"+util.hexstrdump(pubkey[0].obj.getKeyId()).substring(8)+")");
-    					validSignatures[validSignatures.length] = true;
-						}
-					else{
-						util.print_error("Signature verification failed: Bad Signature from "+pubkey[0].obj.userIds[0].text+" (0x"+util.hexstrdump(pubkey[0].obj.getKeyId()).substring(8)+")");
-    					validSignatures[validSignatures.length] = false;
-						}
-				}
-			}
-		}
-		if (this.text == "") {
-			this.text = decrypted;
-		}
-		return {text:this.text, validSignatures:validSignatures};
-	}
-	
-	/**
-	 * Verifies a message signature. This function can be called after read_message if the message was signed only.
-	 * @param pubkey [openpgp_msg_publickey] Array of public keys to check signature against. If not provided, checks local keystore.
-	 * @return [boolean] true if the signature was correct; otherwise false
-	 */
-	function verifySignature(pubkey) {
-		var result = false;
-		if (this.type == 2) {
-		    if(!pubkey || pubkey.length == 0){
-			    var pubkey;
-			    if (this.signature.version == 4) {
-				    pubkey = openpgp.keyring.getPublicKeysForKeyId(this.signature.issuerKeyId);
-			    } else if (this.signature.version == 3) {
-				    pubkey = openpgp.keyring.getPublicKeysForKeyId(this.signature.keyId);
-			    } else {
-				    util.print_error("unknown signature type on message!");
-				    return false;
-			    }
-			}
-			if (pubkey.length == 0)
-				util.print_warning("Unable to verify signature of issuer: "+util.hexstrdump(this.signature.issuerKeyId)+". Public key not found in keyring.");
-			else {
-				for (var i = 0 ; i < pubkey.length; i++) {
-					var tohash = this.text.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n");
-					if (this.signature.verify(tohash.substring(0, tohash.length -2), pubkey[i])) {
-						util.print_info("Found Good Signature from "+pubkey[i].obj.userIds[i].text+" (0x"+util.hexstrdump(pubkey[i].obj.getKeyId()).substring(8)+")");
-						result = true;
-					} else {
-						util.print_error("Signature verification failed: Bad Signature from "+pubkey[i].obj.userIds[0].text+" (0x"+util.hexstrdump(pubkey[0].obj.getKeyId()).substring(8)+")");
-					}
-				}
-			}
-		}
-		return result;
-	}
-	
-	function toString() {
-		var result = "Session Keys:\n";
-		if (this.sessionKeys !=null)
-		for (var i = 0; i < this.sessionKeys.length; i++) {
-			result += this.sessionKeys[i].toString();
-		}
-		result += "\n\n EncryptedData:\n";
-		if(this.encryptedData != null)
-		result += this.encryptedData.toString();
-		
-		result += "\n\n Signature:\n";
-		if(this.signature != null)
-		result += this.signature.toString();
-		
-		result += "\n\n Text:\n"
-		if(this.signature != null)
-			result += this.text;
-		return result;
-	}
-	this.decrypt = decrypt;
-	this.decryptAndVerifySignature = decryptAndVerifySignature;
-	this.verifySignature = verifySignature;
-	this.toString = toString;
-}
-// GPG4Browsers - An OpenPGP implementation in javascript
-// Copyright (C) 2011 Recurity Labs GmbH
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-// Hint: We hold our MPIs as an array of octets in big endian format preceeding a two
-// octet scalar: MPI: [a,b,c,d,e,f]
-// - MPI size: (a << 8) | b 
-// - MPI = c | d << 8 | e << ((MPI.length -2)*8) | f ((MPI.length -2)*8)
-
-/**
- *  Implementation of type MPI (RFC4880 3.2)
- *  Multiprecision integers (also called MPIs) are unsigned integers used
- *  to hold large integers such as the ones used in cryptographic
- *  calculations.
- *  An MPI consists of two pieces: a two-octet scalar that is the length
- *  of the MPI in bits followed by a string of octets that contain the
- *  actual integer.
- */
-function openpgp_type_mpi() {
-	this.MPI = null;
-	this.mpiBitLength = null;
-	this.mpiByteLength = null;
-	this.data = null;
-	/**
-	 * parsing function for a mpi (RFC 4880 3.2).
-	 * @param input [string] payload of mpi data
-	 * @param position [integer] position to start reading from the input string
-	 * @param len [integer] length of the packet or the remaining length of input at position
-	 * @return [openpgp_type_mpi] object representation
-	 */
-	function read(input, position, len) {
-		var mypos = position;
-		
-		this.mpiBitLength = (input[mypos++].charCodeAt() << 8) | input[mypos++].charCodeAt();
-		
-		// Additional rules:
-		//
-		//    The size of an MPI is ((MPI.length + 7) / 8) + 2 octets.
-		//
-		//    The length field of an MPI describes the length starting from its
-		//	  most significant non-zero bit.  Thus, the MPI [00 02 01] is not
-		//    formed correctly.  It should be [00 01 01].
-
-		// TODO: Verification of this size method! This size calculation as
-		// 		 specified above is not applicable in JavaScript
-		this.mpiByteLength = (this.mpiBitLength - (this.mpiBitLength % 8)) / 8;
-		if (this.mpiBitLength % 8 != 0)
-			this.mpiByteLength++;
-		
-		this.MPI = input.substring(mypos,mypos+this.mpiByteLength);
-		this.data = input.substring(position, position+2+this.mpiByteLength);
-		this.packetLength = this.mpiByteLength +2;
-		return this;
-	}
-	
-	/**
-	 * generates debug output (pretty print)
-	 * @return String which gives some information about the mpi
-	 */
-	function toString() {
-		var r = "    MPI("+this.mpiBitLength+"b/"+this.mpiByteLength+"B) : 0x";
-		r+=util.hexstrdump(this.MPI);
-		return r+'\n';
-	}
-	
-	/**
-	 * converts the mpi to an BigInteger object
-	 * @return [BigInteger]
-	 */
-	function getBigInteger() {
-		return new BigInteger(util.hexstrdump(this.MPI),16); 
-	}
-
-	
-	function getBits(num) {
-		for (var i = 0; i < 9; i++)
-		if (num >> i == 0)
-		return i;
-	}
-	
-	/**
-	 * gets the length of the mpi in bytes
-	 * @return [integer] mpi byte length
-	 */
-	function getByteLength() {
-		return this.mpiByteLength;
-	}
-	
-	/**
-	 * creates an mpi from the specified string
-	 * @param data [String] data to read the mpi from
-	 * @return [openpgp_type_mpi] 
-	 */
-	function create(data) {
-		this.MPI = data;
-		this.mpiBitLength = (data.length -1) *8 + getBits(data.charCodeAt(0));
-		this.mpiByteLength = data.length;
-		return this;
-	}
-	
-	/**
-	 * converts the mpi object to a string as specified in RFC4880 3.2
-	 * @return [String] mpi byte representation
-	 */
-	function toBin() {
-		var result = String.fromCharCode((this.mpiBitLength >> 8) & 0xFF);
-		result += String.fromCharCode(this.mpiBitLength & 0xFF);
-		result += this.MPI;
-		return result;
-	}
-	
-	this.read = read;
-	this.toBigInteger = getBigInteger;
-	this.toString = toString;
-	this.create = create;
-	this.toBin = toBin;
-	this.getByteLength = getByteLength;
-}
-
-// GPG4Browsers - An OpenPGP implementation in javascript
-// Copyright (C) 2011 Recurity Labs GmbH
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-/**
- * Implementation of type key id (RFC4880 3.3)
- *  A Key ID is an eight-octet scalar that identifies a key.
-   Implementations SHOULD NOT assume that Key IDs are unique.  The
-   section "Enhanced Key Formats" below describes how Key IDs are
-   formed.
- */
-function openpgp_type_keyid() {
-	/**
-	 * parsing method for a key id
-	 * @param input [String] input to read the key id from 
-	 * @param position [integer] position where to start reading the key id from input
-	 * @return this object
-	 */
-	function read_packet(input, position) {
-		this.bytes = input.substring(position, position+8);
-		return this;
-	}
-	
-	/**
-	 * generates debug output (pretty print)
-	 * @return [String] Key Id as hexadecimal string
-	 */
-	function toString() {
-		return util.hexstrdump(this.bytes);
-	}
-	
-	this.read_packet = read_packet;
-	this.toString = toString;
-};
-// GPG4Browsers - An OpenPGP implementation in javascript
-// Copyright (C) 2011 Recurity Labs GmbH
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-/**
- * Implementation of the String-to-key specifier (RFC4880 3.7)
- * String-to-key (S2K) specifiers are used to convert passphrase strings
-   into symmetric-key encryption/decryption keys.  They are used in two
-   places, currently: to encrypt the secret part of private keys in the
-   private keyring, and to convert passphrases to encryption keys for
-   symmetrically encrypted messages.
- */
-function openpgp_type_s2k() {
-	/**
-	 * parsing function for a string-to-key specifier (RFC 4880 3.7).
-	 * @param input [string] payload of string-to-key specifier
-	 * @param position [integer] position to start reading from the input string
-	 * @return [openpgp_type_s2k] object representation
-	 */
-	function read(input, position) {
-		var mypos = position;
-		this.type = input[mypos++].charCodeAt();
-		switch (this.type) {
-		case 0: // Simple S2K
-			// Octet 1: hash algorithm
-			this.hashAlgorithm = input[mypos++].charCodeAt();
-			this.s2kLength = 1;
-			break;
-
-		case 1: // Salted S2K
-			// Octet 1: hash algorithm
-			this.hashAlgorithm = input[mypos++].charCodeAt();
-
-			// Octets 2-9: 8-octet salt value
-			this.saltValue = input.substring(mypos, mypos+8);
-			mypos += 8;
-			this.s2kLength = 9;
-			break;
-
-		case 3: // Iterated and Salted S2K
-			// Octet 1: hash algorithm
-			this.hashAlgorithm = input[mypos++].charCodeAt();
-
-			// Octets 2-9: 8-octet salt value
-			this.saltValue = input.substring(mypos, mypos+8);
-			mypos += 8;
-
-			// Octet 10: count, a one-octet, coded value
-			this.EXPBIAS = 6;
-			var c = input[mypos++].charCodeAt();
-			this.count = (16 + (c & 15)) << ((c >> 4) + this.EXPBIAS);
-			this.s2kLength = 10;
-			break;
-
-		case 2: // Reserved value
 		default:
-			util.print_error("unknown s2k type! "+this.type);
-			break;
-		}
-		return this;
+			return null;
+	}
+}
+
+/**
+ * Symmetrically decrypts data using a key with length depending on the
+ * algorithm in openpgp_cfb mode with or without resync (MDC style)
+ * @param algo [Integer] algorithm to use (see RFC4880 9.2)
+ * @param key [String] key as string. length is depending on the algorithm used
+ * @param data [String] data to be decrypted
+ * @param openpgp_cfb [boolean] if true use the resync (for encrypteddata); 
+ * otherwise use without the resync (for MDC encrypted data)
+ * @return [String] plaintext data
+ */
+function openpgp_crypto_symmetricDecrypt(algo, key, data, openpgp_cfb) {
+	util.print_debug_hexstr_dump("openpgp_crypto_symmetricDecrypt:\nalgo:"+algo+"\nencrypteddata:",data);
+	var n = 0;
+	if (!openpgp_cfb)
+		n = 2;
+	switch(algo) {
+	case 0: // Plaintext or unencrypted data
+		return data;
+	case 2: // TripleDES (DES-EDE, [SCHNEIER] [HAC] - 168 bit key derived from 192)
+		return openpgp_cfb_decrypt(desede, 8, key, data, openpgp_cfb).substring(n, (data.length+n)-10);
+	case 3: // CAST5 (128 bit key, as per [RFC2144])
+		return openpgp_cfb_decrypt(cast5_encrypt, 8, key, data, openpgp_cfb).substring(n, (data.length+n)-10);
+	case 4: // Blowfish (128 bit key, 16 rounds) [BLOWFISH]
+		return openpgp_cfb_decrypt(BFencrypt, 8, key, data, openpgp_cfb).substring(n, (data.length+n)-10);
+	case 7: // AES with 128-bit key [AES]
+	case 8: // AES with 192-bit key
+	case 9: // AES with 256-bit key
+		return openpgp_cfb_decrypt(AESencrypt, 16, keyExpansion(key), data, openpgp_cfb).substring(n, (data.length+n)-18);
+	case 10: // Twofish with 256-bit key [TWOFISH]
+		var result = openpgp_cfb_decrypt(TFencrypt, 16, key, data, openpgp_cfb).substring(n, (data.length+n)-18);
+		return result;
+	case 1: // IDEA [IDEA]
+		util.print_error(""+ (algo == 1 ? "IDEA Algorithm not implemented" : "Twofish Algorithm not implemented"));
+		return null;
+	default:
+	}
+	return null;
+}// GPG4Browsers - An OpenPGP implementation in javascript
+// Copyright (C) 2011 Recurity Labs GmbH
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA 
+
+// The GPG4Browsers crypto interface
+
+/**
+ * Encrypts data using the specified public key multiprecision integers 
+ * and the specified algorithm.
+ * @param algo [Integer] Algorithm to be used (See RFC4880 9.1)
+ * @param publicMPIs [Array[openpgp_type_mpi]] algorithm dependent multiprecision integers
+ * @param data [openpgp_type_mpi] data to be encrypted as MPI
+ * @return [Object] if RSA an openpgp_type_mpi; if elgamal encryption an array of two
+ * openpgp_type_mpi is returned; otherwise null
+ */
+function openpgp_crypto_asymetricEncrypt(algo, publicMPIs, data) {
+	switch(algo) {
+	case 1: // RSA (Encrypt or Sign) [HAC]
+	case 2: // RSA Encrypt-Only [HAC]
+	case 3: // RSA Sign-Only [HAC]
+		var rsa = new RSA();
+		var n = publicMPIs[0].toBigInteger();
+		var e = publicMPIs[1].toBigInteger();
+		var m = data.toBigInteger();
+		return rsa.encrypt(m,e,n).toMPI();
+	case 16: // Elgamal (Encrypt-Only) [ELGAMAL] [HAC]
+		var elgamal = new Elgamal();
+		var p = publicMPIs[0].toBigInteger();
+		var g = publicMPIs[1].toBigInteger();
+		var y = publicMPIs[2].toBigInteger();
+		var m = data.toBigInteger();
+		return elgamal.encrypt(m,g,p,y);
+	default:
+		return null;
+	}
+}
+
+/**
+ * Decrypts data using the specified public key multiprecision integers of the private key,
+ * the specified secretMPIs of the private key and the specified algorithm.
+ * @param algo [Integer] Algorithm to be used (See RFC4880 9.1)
+ * @param publicMPIs [Array[openpgp_type_mpi]] algorithm dependent multiprecision integers of the public key part of the private key
+ * @param secretMPIs [Array[openpgp_type_mpi]] algorithm dependent multiprecision integers of the private key used
+ * @param data [openpgp_type_mpi] data to be encrypted as MPI
+ * @return [BigInteger] returns a big integer containing the decrypted data; otherwise null
+ */
+
+function openpgp_crypto_asymetricDecrypt(algo, publicMPIs, secretMPIs, dataMPIs) {
+	switch(algo) {
+	case 1: // RSA (Encrypt or Sign) [HAC]  
+	case 2: // RSA Encrypt-Only [HAC]
+	case 3: // RSA Sign-Only [HAC]
+		var rsa = new RSA();
+		var d = secretMPIs[0].toBigInteger();
+		var p = secretMPIs[1].toBigInteger();
+		var q = secretMPIs[2].toBigInteger();
+		var u = secretMPIs[3].toBigInteger();
+		var m = dataMPIs[0].toBigInteger();
+		return rsa.decrypt(m, d, p, q, u);
+	case 16: // Elgamal (Encrypt-Only) [ELGAMAL] [HAC]
+		var elgamal = new Elgamal();
+		var x = secretMPIs[0].toBigInteger();
+		var c1 = dataMPIs[0].toBigInteger();
+		var c2 = dataMPIs[1].toBigInteger();
+		var p = publicMPIs[0].toBigInteger();
+		return elgamal.decrypt(c1,c2,p,x);
+	default:
+		return null;
 	}
 	
+}
+
+/**
+ * generate random byte prefix as string for the specified algorithm
+ * @param algo [Integer] algorithm to use (see RFC4880 9.2)
+ * @return [String] random bytes with length equal to the block
+ * size of the cipher
+ */
+function openpgp_crypto_getPrefixRandom(algo) {
+	switch(algo) {
+	case 2:
+	case 3:
+	case 4:
+		return openpgp_crypto_getRandomBytes(8);
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+		return openpgp_crypto_getRandomBytes(16);
+	default:
+		return null;
+	}
+}
+
+/**
+ * retrieve the MDC prefixed bytes by decrypting them
+ * @param algo [Integer] algorithm to use (see RFC4880 9.2)
+ * @param key [String] key as string. length is depending on the algorithm used
+ * @param data [String] encrypted data where the prefix is decrypted from
+ * @return [String] plain text data of the prefixed data
+ */
+function openpgp_crypto_MDCSystemBytes(algo, key, data) {
+	util.print_debug_hexstr_dump("openpgp_crypto_symmetricDecrypt:\nencrypteddata:",data);
+	switch(algo) {
+	case 0: // Plaintext or unencrypted data
+		return data;
+	case 2: // TripleDES (DES-EDE, [SCHNEIER] [HAC] - 168 bit key derived from 192)
+		return openpgp_cfb_mdc(desede, 8, key, data, openpgp_cfb);
+	case 3: // CAST5 (128 bit key, as per [RFC2144])
+		return openpgp_cfb_mdc(cast5_encrypt, 8, key, data);
+	case 4: // Blowfish (128 bit key, 16 rounds) [BLOWFISH]
+		return openpgp_cfb_mdc(BFencrypt, 8, key, data);
+	case 7: // AES with 128-bit key [AES]
+	case 8: // AES with 192-bit key
+	case 9: // AES with 256-bit key
+		return openpgp_cfb_mdc(AESencrypt, 16, keyExpansion(key), data);
+	case 10: 
+		return openpgp_cfb_mdc(TFencrypt, 16, key, data);
+	case 1: // IDEA [IDEA]
+		util.print_error(""+ (algo == 1 ? "IDEA Algorithm not implemented" : "Twofish Algorithm not implemented"));
+		return null;
+	default:
+	}
+	return null;
+}
+/**
+ * Generating a session key for the specified symmetric algorithm
+ * @param algo [Integer] algorithm to use (see RFC4880 9.2)
+ * @return [String] random bytes as a string to be used as a key
+ */
+function openpgp_crypto_generateSessionKey(algo) {
+	switch (algo) {
+	case 2: // TripleDES (DES-EDE, [SCHNEIER] [HAC] - 168 bit key derived from 192)
+	case 8: // AES with 192-bit key
+		return openpgp_crypto_getRandomBytes(24); 
+	case 3: // CAST5 (128 bit key, as per [RFC2144])
+	case 4: // Blowfish (128 bit key, 16 rounds) [BLOWFISH]
+	case 7: // AES with 128-bit key [AES]
+		util.print_debug("length = 16:\n"+util.hexstrdump(openpgp_crypto_getRandomBytes(16)));
+		return openpgp_crypto_getRandomBytes(16);
+	case 9: // AES with 256-bit key
+	case 10:// Twofish with 256-bit key [TWOFISH]
+		return openpgp_crypto_getRandomBytes(32);
+	}
+	return null;
+}
+
+/**
+ * 
+ * @param algo [Integer] public key algorithm
+ * @param hash_algo [Integer] hash algorithm
+ * @param msg_MPIs [Array[openpgp_type_mpi]] signature multiprecision integers
+ * @param publickey_MPIs [Array[openpgp_type_mpi]] public key multiprecision integers 
+ * @param data [String] data on where the signature was computed on.
+ * @return true if signature (sig_data was equal to data over hash)
+ */
+function openpgp_crypto_verifySignature(algo, hash_algo, msg_MPIs, publickey_MPIs, data) {
+	var calc_hash = openpgp_crypto_hashData(hash_algo, data);
+	switch(algo) {
+	case 1: // RSA (Encrypt or Sign) [HAC]  
+	case 2: // RSA Encrypt-Only [HAC]
+	case 3: // RSA Sign-Only [HAC]
+		var rsa = new RSA();
+		var n = publickey_MPIs[0].toBigInteger();
+		var e = publickey_MPIs[1].toBigInteger();
+		var x = msg_MPIs[0].toBigInteger();
+		var dopublic = rsa.verify(x,e,n);
+		var hash  = openpgp_encoding_emsa_pkcs1_decode(hash_algo,dopublic.toMPI().substring(2));
+		if (hash == -1) {
+			util.print_error("PKCS1 padding in message or key incorrect. Aborting...");
+			return false;
+		}
+		return hash == calc_hash;
+		
+	case 16: // Elgamal (Encrypt-Only) [ELGAMAL] [HAC]
+		util.print_error("signing with Elgamal is not defined in the OpenPGP standard.");
+		return null;
+	case 17: // DSA (Digital Signature Algorithm) [FIPS186] [HAC]
+		var dsa = new DSA();
+		var s1 = msg_MPIs[0].toBigInteger();
+		var s2 = msg_MPIs[1].toBigInteger();
+		var p = publickey_MPIs[0].toBigInteger();
+		var q = publickey_MPIs[1].toBigInteger();
+		var g = publickey_MPIs[2].toBigInteger();
+		var y = publickey_MPIs[3].toBigInteger();
+		var m = data;
+		var dopublic = dsa.verify(hash_algo,s1,s2,m,p,q,g,y);
+		return dopublic.compareTo(s1) == 0;
+	default:
+		return null;
+	}
+	
+}
+   
+/**
+ * Create a signature on data using the specified algorithm
+ * @param hash_algo [Integer] hash algorithm to use (See RFC4880 9.4)
+ * @param algo [Integer] asymmetric cipher algorithm to use (See RFC4880 9.1)
+ * @param publicMPIs [Array[openpgp_type_mpi]] public key multiprecision integers of the private key 
+ * @param secretMPIs [Array[openpgp_type_mpi]] private key multiprecision integers which is used to sign the data
+ * @param data [String] data to be signed
+ * @return [String or openpgp_type_mpi] 
+ */
+function openpgp_crypto_signData(hash_algo, algo, publicMPIs, secretMPIs, data) {
+	
+	switch(algo) {
+	case 1: // RSA (Encrypt or Sign) [HAC]  
+	case 2: // RSA Encrypt-Only [HAC]
+	case 3: // RSA Sign-Only [HAC]
+		var rsa = new RSA();
+		var d = secretMPIs[0].toBigInteger();
+		var n = publicMPIs[0].toBigInteger();
+		var m = openpgp_encoding_emsa_pkcs1_encode(hash_algo, data,publicMPIs[0].mpiByteLength);
+		util.print_debug("signing using RSA");
+		return rsa.sign(m, d, n).toMPI();
+	case 17: // DSA (Digital Signature Algorithm) [FIPS186] [HAC]
+		var dsa = new DSA();
+		util.print_debug("DSA Sign: q size in Bytes:"+publicMPIs[1].getByteLength());
+		var p = publicMPIs[0].toBigInteger();
+		var q = publicMPIs[1].toBigInteger();
+		var g = publicMPIs[2].toBigInteger();
+		var y = publicMPIs[3].toBigInteger();
+		var x = secretMPIs[0].toBigInteger();
+		var m = data;
+		var result = dsa.sign(hash_algo,m, g, p, q, x);
+		util.print_debug("signing using DSA\n result:"+util.hexstrdump(result[0])+"|"+util.hexstrdump(result[1]));
+		return result[0]+result[1];
+	case 16: // Elgamal (Encrypt-Only) [ELGAMAL] [HAC]
+			util.print_debug("signing with Elgamal is not defined in the OpenPGP standard.");
+			return null;
+	default:
+		return null;
+	}	
+}
+
+/**
+ * create a hash on the specified data using the specified algorithm
+ * @param algo [Integer] hash algorithm type (see RFC4880 9.4)
+ * @param data [String] data to be hashed
+ * @return [String] hash value
+ */
+function openpgp_crypto_hashData(algo, data) {
+	var hash = null;
+	switch(algo) {
+	case 1: // - MD5 [HAC]
+		hash = MD5(data);
+		break;
+	case 2: // - SHA-1 [FIPS180]
+		hash = str_sha1(data);
+		break;
+	case 3: // - RIPE-MD/160 [HAC]
+		hash = RMDstring(data);
+		break;
+	case 8: // - SHA256 [FIPS180]
+		hash = str_sha256(data);
+		break;
+	case 9: // - SHA384 [FIPS180]
+		hash = str_sha384(data);
+		break;
+	case 10:// - SHA512 [FIPS180]
+		hash = str_sha512(data);
+		break;
+	case 11:// - SHA224 [FIPS180]
+		hash = str_sha224(data);
+	default:
+		break;
+	}
+	return hash;
+}
+
+/**
+ * returns the hash size in bytes of the specified hash algorithm type
+ * @param algo [Integer] hash algorithm type (See RFC4880 9.4)
+ * @return [Integer] size in bytes of the resulting hash
+ */
+function openpgp_crypto_getHashByteLength(algo) {
+	var hash = null;
+	switch(algo) {
+	case 1: // - MD5 [HAC]
+		return 16;
+	case 2: // - SHA-1 [FIPS180]
+	case 3: // - RIPE-MD/160 [HAC]
+		return 20;
+	case 8: // - SHA256 [FIPS180]
+		return 32;
+	case 9: // - SHA384 [FIPS180]
+		return 48
+	case 10:// - SHA512 [FIPS180]
+		return 64;
+	case 11:// - SHA224 [FIPS180]
+		return 28;
+	}
+	return null;
+}
+
+/**
+ * retrieve secure random byte string of the specified length
+ * @param length [Integer] length in bytes to generate
+ * @return [String] random byte string
+ */
+function openpgp_crypto_getRandomBytes(length) {
+	var result = '';
+	for (var i = 0; i < length; i++) {
+		result += String.fromCharCode(openpgp_crypto_getSecureRandomOctet());
+	}
+	return result;
+}
+
+/**
+ * return a pseudo-random number in the specified range
+ * @param from [Integer] min of the random number
+ * @param to [Integer] max of the random number (max 32bit)
+ * @return [Integer] a pseudo random number
+ */
+function openpgp_crypto_getPseudoRandom(from, to) {
+	return Math.round(Math.random()*(to-from))+from;
+}
+
+/**
+ * return a secure random number in the specified range
+ * @param from [Integer] min of the random number
+ * @param to [Integer] max of the random number (max 32bit)
+ * @return [Integer] a secure random number
+ */
+function openpgp_crypto_getSecureRandom(from, to) {
+	var buf = new Uint32Array(1);
+	window.crypto.getRandomValues(buf);
+	var bits = ((to-from)).toString(2).length;
+	while ((buf[0] & (Math.pow(2, bits) -1)) > (to-from))
+		window.crypto.getRandomValues(buf);
+	return from+(Math.abs(buf[0] & (Math.pow(2, bits) -1)));
+}
+
+function openpgp_crypto_getSecureRandomOctet() {
+	var buf = new Uint32Array(1);
+	window.crypto.getRandomValues(buf);
+	return buf[0] & 0xFF;
+}
+
+/**
+ * create a secure random big integer of bits length
+ * @param bits [Integer] bit length of the MPI to create
+ * @return [BigInteger] resulting big integer
+ */
+function openpgp_crypto_getRandomBigInteger(bits) {
+	if (bits < 0)
+	   return null;
+	var numBytes = Math.floor((bits+7)/8);
+
+	var randomBits = openpgp_crypto_getRandomBytes(numBytes);
+	if (bits % 8 > 0) {
+		
+		randomBits = String.fromCharCode(
+						(Math.pow(2,bits % 8)-1) &
+						randomBits.charCodeAt(0)) +
+			randomBits.substring(1);
+	}
+	return new openpgp_type_mpi().create(randomBits).toBigInteger();
+}
+
+function openpgp_crypto_getRandomBigIntegerInRange(min, max) {
+	if (max.compareTo(min) <= 0)
+		return;
+	var range = max.subtract(min);
+	var r = openpgp_crypto_getRandomBigInteger(range.bitLength());
+	while (r > range) {
+		r = openpgp_crypto_getRandomBigInteger(range.bitLength());
+	}
+	return min.add(r);
+}
+
+
+//This is a test method to ensure that encryption/decryption with a given 1024bit RSAKey object functions as intended
+function openpgp_crypto_testRSA(key){
+	debugger;
+    var rsa = new RSA();
+	var mpi = new openpgp_type_mpi();
+	mpi.create(openpgp_encoding_eme_pkcs1_encode('ABABABAB', 128));
+	var msg = rsa.encrypt(mpi.toBigInteger(),key.ee,key.n);
+	var result = rsa.decrypt(msg, key.d, key.p, key.q, key.u);
+}
+/**
+ * calls the necessary crypto functions to generate a keypair. Called directly by openpgp.js
+ * @keyType [int] follows OpenPGP algorithm convention.
+ * @numBits [int] number of bits to make the key to be generated
+ * @return {privateKey: [openpgp_packet_keymaterial] , publicKey: [openpgp_packet_keymaterial]}
+ */
+function openpgp_crypto_generateKeyPair(keyType, numBits, passphrase, s2kHash, symmetricEncryptionAlgorithm){
+	var privKeyPacket;
+	var publicKeyPacket;
+	var d = new Date();
+	d = d.getTime()/1000;
+	var timePacket = String.fromCharCode(Math.floor(d/0x1000000%0x100)) + String.fromCharCode(Math.floor(d/0x10000%0x100)) + String.fromCharCode(Math.floor(d/0x100%0x100)) + String.fromCharCode(Math.floor(d%0x100));
+	switch(keyType){
+	case 1:
+	    var rsa = new RSA();
+	    var key = rsa.generate(numBits,"10001");
+	    privKeyPacket = new openpgp_packet_keymaterial().write_private_key(keyType, key, passphrase, s2kHash, symmetricEncryptionAlgorithm, timePacket);
+	    publicKeyPacket =  new openpgp_packet_keymaterial().write_public_key(keyType, key, timePacket);
+	    break;
+	default:
+		util.print_error("Unknown keytype "+keyType)
+	}
+	return {privateKey: privKeyPacket, publicKey: publicKeyPacket};
+}
+/*
+ * Copyright (c) 2003-2005  Tom Wu (tjw@cs.Stanford.EDU) 
+ * All Rights Reserved.
+ *
+ * Modified by Recurity Labs GmbH 
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ *
+ * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following condition applies:
+ *
+ * All redistributions must retain an intact copy of this copyright notice
+ * and disclaimer.
+ */
+
+// Basic JavaScript BN library - subset useful for RSA encryption.
+
+// Bits per digit
+var dbits;
+
+// JavaScript engine analysis
+var canary = 0xdeadbeefcafe;
+var j_lm = ((canary&0xffffff)==0xefcafe);
+
+// (public) Constructor
+function BigInteger(a,b,c) {
+  if(a != null)
+    if("number" == typeof a) this.fromNumber(a,b,c);
+    else if(b == null && "string" != typeof a) this.fromString(a,256);
+    else this.fromString(a,b);
+}
+
+// return new, unset BigInteger
+function nbi() { return new BigInteger(null); }
+
+// am: Compute w_j += (x*this_i), propagate carries,
+// c is initial carry, returns final carry.
+// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
+// We need to select the fastest one that works in this environment.
+
+// am1: use a single mult and divide to get the high bits,
+// max digit bits should be 26 because
+// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
+function am1(i,x,w,j,c,n) {
+  while(--n >= 0) {
+    var v = x*this[i++]+w[j]+c;
+    c = Math.floor(v/0x4000000);
+    w[j++] = v&0x3ffffff;
+  }
+  return c;
+}
+// am2 avoids a big mult-and-extract completely.
+// Max digit bits should be <= 30 because we do bitwise ops
+// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
+function am2(i,x,w,j,c,n) {
+  var xl = x&0x7fff, xh = x>>15;
+  while(--n >= 0) {
+    var l = this[i]&0x7fff;
+    var h = this[i++]>>15;
+    var m = xh*l+h*xl;
+    l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
+    c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
+    w[j++] = l&0x3fffffff;
+  }
+  return c;
+}
+// Alternately, set max digit bits to 28 since some
+// browsers slow down when dealing with 32-bit numbers.
+function am3(i,x,w,j,c,n) {
+  var xl = x&0x3fff, xh = x>>14;
+  while(--n >= 0) {
+    var l = this[i]&0x3fff;
+    var h = this[i++]>>14;
+    var m = xh*l+h*xl;
+    l = xl*l+((m&0x3fff)<<14)+w[j]+c;
+    c = (l>>28)+(m>>14)+xh*h;
+    w[j++] = l&0xfffffff;
+  }
+  return c;
+}
+if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
+  BigInteger.prototype.am = am2;
+  dbits = 30;
+}
+else if(j_lm && (navigator.appName != "Netscape")) {
+  BigInteger.prototype.am = am1;
+  dbits = 26;
+}
+else { // Mozilla/Netscape seems to prefer am3
+  BigInteger.prototype.am = am3;
+  dbits = 28;
+}
+
+BigInteger.prototype.DB = dbits;
+BigInteger.prototype.DM = ((1<<dbits)-1);
+BigInteger.prototype.DV = (1<<dbits);
+
+var BI_FP = 52;
+BigInteger.prototype.FV = Math.pow(2,BI_FP);
+BigInteger.prototype.F1 = BI_FP-dbits;
+BigInteger.prototype.F2 = 2*dbits-BI_FP;
+
+// Digit conversions
+var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
+var BI_RC = new Array();
+var rr,vv;
+rr = "0".charCodeAt(0);
+for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
+rr = "a".charCodeAt(0);
+for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
+rr = "A".charCodeAt(0);
+for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
+
+function int2char(n) { return BI_RM.charAt(n); }
+function intAt(s,i) {
+  var c = BI_RC[s.charCodeAt(i)];
+  return (c==null)?-1:c;
+}
+
+// (protected) copy this to r
+function bnpCopyTo(r) {
+  for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
+  r.t = this.t;
+  r.s = this.s;
+}
+
+// (protected) set from integer value x, -DV <= x < DV
+function bnpFromInt(x) {
+  this.t = 1;
+  this.s = (x<0)?-1:0;
+  if(x > 0) this[0] = x;
+  else if(x < -1) this[0] = x+DV;
+  else this.t = 0;
+}
+
+// return bigint initialized to value
+function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
+
+// (protected) set from string and radix
+function bnpFromString(s,b) {
+  var k;
+  if(b == 16) k = 4;
+  else if(b == 8) k = 3;
+  else if(b == 256) k = 8; // byte array
+  else if(b == 2) k = 1;
+  else if(b == 32) k = 5;
+  else if(b == 4) k = 2;
+  else { this.fromRadix(s,b); return; }
+  this.t = 0;
+  this.s = 0;
+  var i = s.length, mi = false, sh = 0;
+  while(--i >= 0) {
+    var x = (k==8)?s[i]&0xff:intAt(s,i);
+    if(x < 0) {
+      if(s.charAt(i) == "-") mi = true;
+      continue;
+    }
+    mi = false;
+    if(sh == 0)
+      this[this.t++] = x;
+    else if(sh+k > this.DB) {
+      this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
+      this[this.t++] = (x>>(this.DB-sh));
+    }
+    else
+      this[this.t-1] |= x<<sh;
+    sh += k;
+    if(sh >= this.DB) sh -= this.DB;
+  }
+  if(k == 8 && (s[0]&0x80) != 0) {
+    this.s = -1;
+    if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
+  }
+  this.clamp();
+  if(mi) BigInteger.ZERO.subTo(this,this);
+}
+
+// (protected) clamp off excess high words
+function bnpClamp() {
+  var c = this.s&this.DM;
+  while(this.t > 0 && this[this.t-1] == c) --this.t;
+}
+
+// (public) return string representation in given radix
+function bnToString(b) {
+  if(this.s < 0) return "-"+this.negate().toString(b);
+  var k;
+  if(b == 16) k = 4;
+  else if(b == 8) k = 3;
+  else if(b == 2) k = 1;
+  else if(b == 32) k = 5;
+  else if(b == 4) k = 2;
+  else return this.toRadix(b);
+  var km = (1<<k)-1, d, m = false, r = "", i = this.t;
+  var p = this.DB-(i*this.DB)%k;
+  if(i-- > 0) {
+    if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
+    while(i >= 0) {
+      if(p < k) {
+        d = (this[i]&((1<<p)-1))<<(k-p);
+        d |= this[--i]>>(p+=this.DB-k);
+      }
+      else {
+        d = (this[i]>>(p-=k))&km;
+        if(p <= 0) { p += this.DB; --i; }
+      }
+      if(d > 0) m = true;
+      if(m) r += int2char(d);
+    }
+  }
+  return m?r:"0";
+}
+
+// (public) -this
+function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
+
+// (public) |this|
+function bnAbs() { return (this.s<0)?this.negate():this; }
+
+// (public) return + if this > a, - if this < a, 0 if equal
+function bnCompareTo(a) {
+  var r = this.s-a.s;
+  if(r != 0) return r;
+  var i = this.t;
+  r = i-a.t;
+  if(r != 0) return r;
+  while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
+  return 0;
+}
+
+// returns bit length of the integer x
+function nbits(x) {
+  var r = 1, t;
+  if((t=x>>>16) != 0) { x = t; r += 16; }
+  if((t=x>>8) != 0) { x = t; r += 8; }
+  if((t=x>>4) != 0) { x = t; r += 4; }
+  if((t=x>>2) != 0) { x = t; r += 2; }
+  if((t=x>>1) != 0) { x = t; r += 1; }
+  return r;
+}
+
+// (public) return the number of bits in "this"
+function bnBitLength() {
+  if(this.t <= 0) return 0;
+  return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
+}
+
+// (protected) r = this << n*DB
+function bnpDLShiftTo(n,r) {
+  var i;
+  for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
+  for(i = n-1; i >= 0; --i) r[i] = 0;
+  r.t = this.t+n;
+  r.s = this.s;
+}
+
+// (protected) r = this >> n*DB
+function bnpDRShiftTo(n,r) {
+  for(var i = n; i < this.t; ++i) r[i-n] = this[i];
+  r.t = Math.max(this.t-n,0);
+  r.s = this.s;
+}
+
+// (protected) r = this << n
+function bnpLShiftTo(n,r) {
+  var bs = n%this.DB;
+  var cbs = this.DB-bs;
+  var bm = (1<<cbs)-1;
+  var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
+  for(i = this.t-1; i >= 0; --i) {
+    r[i+ds+1] = (this[i]>>cbs)|c;
+    c = (this[i]&bm)<<bs;
+  }
+  for(i = ds-1; i >= 0; --i) r[i] = 0;
+  r[ds] = c;
+  r.t = this.t+ds+1;
+  r.s = this.s;
+  r.clamp();
+}
+
+// (protected) r = this >> n
+function bnpRShiftTo(n,r) {
+  r.s = this.s;
+  var ds = Math.floor(n/this.DB);
+  if(ds >= this.t) { r.t = 0; return; }
+  var bs = n%this.DB;
+  var cbs = this.DB-bs;
+  var bm = (1<<bs)-1;
+  r[0] = this[ds]>>bs;
+  for(var i = ds+1; i < this.t; ++i) {
+    r[i-ds-1] |= (this[i]&bm)<<cbs;
+    r[i-ds] = this[i]>>bs;
+  }
+  if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
+  r.t = this.t-ds;
+  r.clamp();
+}
+
+// (protected) r = this - a
+function bnpSubTo(a,r) {
+  var i = 0, c = 0, m = Math.min(a.t,this.t);
+  while(i < m) {
+    c += this[i]-a[i];
+    r[i++] = c&this.DM;
+    c >>= this.DB;
+  }
+  if(a.t < this.t) {
+    c -= a.s;
+    while(i < this.t) {
+      c += this[i];
+      r[i++] = c&this.DM;
+      c >>= this.DB;
+    }
+    c += this.s;
+  }
+  else {
+    c += this.s;
+    while(i < a.t) {
+      c -= a[i];
+      r[i++] = c&this.DM;
+      c >>= this.DB;
+    }
+    c -= a.s;
+  }
+  r.s = (c<0)?-1:0;
+  if(c < -1) r[i++] = this.DV+c;
+  else if(c > 0) r[i++] = c;
+  r.t = i;
+  r.clamp();
+}
+
+// (protected) r = this * a, r != this,a (HAC 14.12)
+// "this" should be the larger one if appropriate.
+function bnpMultiplyTo(a,r) {
+  var x = this.abs(), y = a.abs();
+  var i = x.t;
+  r.t = i+y.t;
+  while(--i >= 0) r[i] = 0;
+  for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
+  r.s = 0;
+  r.clamp();
+  if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
+}
+
+// (protected) r = this^2, r != this (HAC 14.16)
+function bnpSquareTo(r) {
+  var x = this.abs();
+  var i = r.t = 2*x.t;
+  while(--i >= 0) r[i] = 0;
+  for(i = 0; i < x.t-1; ++i) {
+    var c = x.am(i,x[i],r,2*i,0,1);
+    if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
+      r[i+x.t] -= x.DV;
+      r[i+x.t+1] = 1;
+    }
+  }
+  if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
+  r.s = 0;
+  r.clamp();
+}
+
+// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
+// r != q, this != m.  q or r may be null.
+function bnpDivRemTo(m,q,r) {
+  var pm = m.abs();
+  if(pm.t <= 0) return;
+  var pt = this.abs();
+  if(pt.t < pm.t) {
+    if(q != null) q.fromInt(0);
+    if(r != null) this.copyTo(r);
+    return;
+  }
+  if(r == null) r = nbi();
+  var y = nbi(), ts = this.s, ms = m.s;
+  var nsh = this.DB-nbits(pm[pm.t-1]);	// normalize modulus
+  if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
+  else { pm.copyTo(y); pt.copyTo(r); }
+  var ys = y.t;
+  var y0 = y[ys-1];
+  if(y0 == 0) return;
+  var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
+  var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
+  var i = r.t, j = i-ys, t = (q==null)?nbi():q;
+  y.dlShiftTo(j,t);
+  if(r.compareTo(t) >= 0) {
+    r[r.t++] = 1;
+    r.subTo(t,r);
+  }
+  BigInteger.ONE.dlShiftTo(ys,t);
+  t.subTo(y,y);	// "negative" y so we can replace sub with am later
+  while(y.t < ys) y[y.t++] = 0;
+  while(--j >= 0) {
+    // Estimate quotient digit
+    var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
+    if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) {	// Try it out
+      y.dlShiftTo(j,t);
+      r.subTo(t,r);
+      while(r[i] < --qd) r.subTo(t,r);
+    }
+  }
+  if(q != null) {
+    r.drShiftTo(ys,q);
+    if(ts != ms) BigInteger.ZERO.subTo(q,q);
+  }
+  r.t = ys;
+  r.clamp();
+  if(nsh > 0) r.rShiftTo(nsh,r);	// Denormalize remainder
+  if(ts < 0) BigInteger.ZERO.subTo(r,r);
+}
+
+// (public) this mod a
+function bnMod(a) {
+  var r = nbi();
+  this.abs().divRemTo(a,null,r);
+  if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
+  return r;
+}
+
+// Modular reduction using "classic" algorithm
+function Classic(m) { this.m = m; }
+function cConvert(x) {
+  if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
+  else return x;
+}
+function cRevert(x) { return x; }
+function cReduce(x) { x.divRemTo(this.m,null,x); }
+function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
+function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
+
+Classic.prototype.convert = cConvert;
+Classic.prototype.revert = cRevert;
+Classic.prototype.reduce = cReduce;
+Classic.prototype.mulTo = cMulTo;
+Classic.prototype.sqrTo = cSqrTo;
+
+// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
+// justification:
+//         xy == 1 (mod m)
+//         xy =  1+km
+//   xy(2-xy) = (1+km)(1-km)
+// x[y(2-xy)] = 1-k^2m^2
+// x[y(2-xy)] == 1 (mod m^2)
+// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
+// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
+// JS multiply "overflows" differently from C/C++, so care is needed here.
+function bnpInvDigit() {
+  if(this.t < 1) return 0;
+  var x = this[0];
+  if((x&1) == 0) return 0;
+  var y = x&3;		// y == 1/x mod 2^2
+  y = (y*(2-(x&0xf)*y))&0xf;	// y == 1/x mod 2^4
+  y = (y*(2-(x&0xff)*y))&0xff;	// y == 1/x mod 2^8
+  y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff;	// y == 1/x mod 2^16
+  // last step - calculate inverse mod DV directly;
+  // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
+  y = (y*(2-x*y%this.DV))%this.DV;		// y == 1/x mod 2^dbits
+  // we really want the negative inverse, and -DV < y < DV
+  return (y>0)?this.DV-y:-y;
+}
+
+// Montgomery reduction
+function Montgomery(m) {
+  this.m = m;
+  this.mp = m.invDigit();
+  this.mpl = this.mp&0x7fff;
+  this.mph = this.mp>>15;
+  this.um = (1<<(m.DB-15))-1;
+  this.mt2 = 2*m.t;
+}
+
+// xR mod m
+function montConvert(x) {
+  var r = nbi();
+  x.abs().dlShiftTo(this.m.t,r);
+  r.divRemTo(this.m,null,r);
+  if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
+  return r;
+}
+
+// x/R mod m
+function montRevert(x) {
+  var r = nbi();
+  x.copyTo(r);
+  this.reduce(r);
+  return r;
+}
+
+// x = x/R mod m (HAC 14.32)
+function montReduce(x) {
+  while(x.t <= this.mt2)	// pad x so am has enough room later
+    x[x.t++] = 0;
+  for(var i = 0; i < this.m.t; ++i) {
+    // faster way of calculating u0 = x[i]*mp mod DV
+    var j = x[i]&0x7fff;
+    var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
+    // use am to combine the multiply-shift-add into one call
+    j = i+this.m.t;
+    x[j] += this.m.am(0,u0,x,i,0,this.m.t);
+    // propagate carry
+    while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
+  }
+  x.clamp();
+  x.drShiftTo(this.m.t,x);
+  if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
+}
+
+// r = "x^2/R mod m"; x != r
+function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
+
+// r = "xy/R mod m"; x,y != r
+function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
+
+Montgomery.prototype.convert = montConvert;
+Montgomery.prototype.revert = montRevert;
+Montgomery.prototype.reduce = montReduce;
+Montgomery.prototype.mulTo = montMulTo;
+Montgomery.prototype.sqrTo = montSqrTo;
+
+// (protected) true iff this is even
+function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
+
+// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
+function bnpExp(e,z) {
+  if(e > 0xffffffff || e < 1) return BigInteger.ONE;
+  var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
+  g.copyTo(r);
+  while(--i >= 0) {
+    z.sqrTo(r,r2);
+    if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
+    else { var t = r; r = r2; r2 = t; }
+  }
+  return z.revert(r);
+}
+
+// (public) this^e % m, 0 <= e < 2^32
+function bnModPowInt(e,m) {
+  var z;
+  if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
+  return this.exp(e,z);
+}
+
+// protected
+BigInteger.prototype.copyTo = bnpCopyTo;
+BigInteger.prototype.fromInt = bnpFromInt;
+BigInteger.prototype.fromString = bnpFromString;
+BigInteger.prototype.clamp = bnpClamp;
+BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
+BigInteger.prototype.drShiftTo = bnpDRShiftTo;
+BigInteger.prototype.lShiftTo = bnpLShiftTo;
+BigInteger.prototype.rShiftTo = bnpRShiftTo;
+BigInteger.prototype.subTo = bnpSubTo;
+BigInteger.prototype.multiplyTo = bnpMultiplyTo;
+BigInteger.prototype.squareTo = bnpSquareTo;
+BigInteger.prototype.divRemTo = bnpDivRemTo;
+BigInteger.prototype.invDigit = bnpInvDigit;
+BigInteger.prototype.isEven = bnpIsEven;
+BigInteger.prototype.exp = bnpExp;
+
+// public
+BigInteger.prototype.toString = bnToString;
+BigInteger.prototype.negate = bnNegate;
+BigInteger.prototype.abs = bnAbs;
+BigInteger.prototype.compareTo = bnCompareTo;
+BigInteger.prototype.bitLength = bnBitLength;
+BigInteger.prototype.mod = bnMod;
+BigInteger.prototype.modPowInt = bnModPowInt;
+
+// "constants"
+BigInteger.ZERO = nbv(0);
+BigInteger.ONE = nbv(1);
+
+// GPG4Browsers - An OpenPGP implementation in javascript
+// Copyright (C) 2011 Recurity Labs GmbH
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// RSA implementation
+
+function SecureRandom(){
+    function nextBytes(byteArray){
+        for(var n = 0; n < byteArray.length;n++){
+            byteArray[n] = openpgp_crypto_getSecureRandomOctet();
+        }
+    }
+    this.nextBytes = nextBytes;
+}
+
+function RSA() {
+	/**
+	 * This function uses jsbn Big Num library to decrypt RSA
+	 * @param m
+	 *            message
+	 * @param d
+	 *            RSA d as BigInteger
+	 * @param p
+	 *            RSA p as BigInteger
+	 * @param q
+	 *            RSA q as BigInteger
+	 * @param u
+	 *            RSA u as BigInteger
+	 * @return {BigInteger} The decrypted value of the message
+	 */
+	function decrypt(m, d, p, q, u) {
+		var xp = m.mod(p).modPow(d.mod(p.subtract(BigInteger.ONE)), p);
+		var xq = m.mod(q).modPow(d.mod(q.subtract(BigInteger.ONE)), q);
+		util.print_debug("rsa.js decrypt\nxpn:"+util.hexstrdump(xp.toMPI())+"\nxqn:"+util.hexstrdump(xq.toMPI()));
+
+		var t = xq.subtract(xp);
+		if (t[0] == 0) {
+			t = xp.subtract(xq);
+			t = t.multiply(u).mod(q);
+			t = q.subtract(t);
+		} else {
+			t = t.multiply(u).mod(q);
+		}
+		return t.multiply(p).add(xp);
+	}
 	
 	/**
-	 * writes an s2k hash based on the inputs.
-	 * @return [String] produced key of hashAlgorithm hash length
+	 * encrypt message
+	 * @param m message as BigInteger
+	 * @param e public MPI part as BigInteger
+	 * @param n public MPI part as BigInteger
+	 * @return BigInteger
 	 */
-	function write(type, hash, passphrase, salt, c){
-	    this.type = type;
-	    if(this.type == 3){this.saltValue = salt;
-	        this.hashAlgorithm = hash;
-	        this.count = (16 + (c & 15)) << ((c >> 4) + 6);
-	        this.s2kLength = 10;
-	    }
-	    return this.produce_key(passphrase);
+	function encrypt(m,e,n) {
+		return m.modPowInt(e, n);
+	}
+	
+	/* Sign and Verify */
+	function sign(m,d,n) {
+		return m.modPow(d, n);
+	}
+		
+	function verify(x,e,n) {
+		return x.modPowInt(e, n);
+	}
+	
+	// "empty" RSA key constructor
+    function keyObject() {
+        this.n = null;
+        this.e = 0;
+        this.ee = null;
+        this.d = null;
+        this.p = null;
+        this.q = null;
+        this.dmp1 = null;
+        this.dmq1 = null;
+        this.u = null;
+    }
+	
+	// Generate a new random private key B bits long, using public expt E
+    function generate(B,E) {
+        var key = new keyObject();
+        var rng = new SecureRandom();
+        var qs = B>>1;
+        key.e = parseInt(E,16);
+        key.ee = new BigInteger(E,16);
+        for(;;) {
+            for(;;) {
+                key.p = new BigInteger(B-qs,1,rng);
+                if(key.p.subtract(BigInteger.ONE).gcd(key.ee).compareTo(BigInteger.ONE) == 0 && key.p.isProbablePrime(10)) break;
+            }
+            for(;;) {
+                key.q = new BigInteger(qs,1,rng);
+                if(key.q.subtract(BigInteger.ONE).gcd(key.ee).compareTo(BigInteger.ONE) == 0 && key.q.isProbablePrime(10)) break;
+            }
+            if(key.p.compareTo(key.q) <= 0) {
+                var t = key.p;
+                key.p = key.q;
+                key.q = t;
+            }
+            var p1 = key.p.subtract(BigInteger.ONE);
+            var q1 = key.q.subtract(BigInteger.ONE);
+            var phi = p1.multiply(q1);
+            if(phi.gcd(key.ee).compareTo(BigInteger.ONE) == 0) {
+                key.n = key.p.multiply(key.q);
+                key.d = key.ee.modInverse(phi);
+                key.dmp1 = key.d.mod(p1);
+                key.dmq1 = key.d.mod(q1);
+                key.u = key.p.modInverse(key.q);
+                break;
+            }
+        }
+        return key;
+    }
+		
+	this.encrypt = encrypt;
+	this.decrypt = decrypt;
+	this.verify = verify;
+	this.sign = sign;
+	this.generate = generate;
+	this.keyObject = keyObject;
+}
+/*
+ * Copyright (c) 2003-2005  Tom Wu (tjw@cs.Stanford.EDU) 
+ * All Rights Reserved.
+ *
+ * Modified by Recurity Labs GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+ *
+ * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following condition applies:
+ *
+ * All redistributions must retain an intact copy of this copyright notice
+ * and disclaimer.
+ */
+// Extended JavaScript BN functions, required for RSA private ops.
+
+// Version 1.1: new BigInteger("0", 10) returns "proper" zero
+// Version 1.2: square() API, isProbablePrime fix
+
+// (public)
+function bnClone() { var r = nbi(); this.copyTo(r); return r; }
+
+// (public) return value as integer
+function bnIntValue() {
+  if(this.s < 0) {
+    if(this.t == 1) return this[0]-this.DV;
+    else if(this.t == 0) return -1;
+  }
+  else if(this.t == 1) return this[0];
+  else if(this.t == 0) return 0;
+  // assumes 16 < DB < 32
+  return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];
+}
+
+// (public) return value as byte
+function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }
+
+// (public) return value as short (assumes DB>=16)
+function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }
+
+// (protected) return x s.t. r^x < DV
+function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }
+
+// (public) 0 if this == 0, 1 if this > 0
+function bnSigNum() {
+  if(this.s < 0) return -1;
+  else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
+  else return 1;
+}
+
+// (protected) convert to radix string
+function bnpToRadix(b) {
+  if(b == null) b = 10;
+  if(this.signum() == 0 || b < 2 || b > 36) return "0";
+  var cs = this.chunkSize(b);
+  var a = Math.pow(b,cs);
+  var d = nbv(a), y = nbi(), z = nbi(), r = "";
+  this.divRemTo(d,y,z);
+  while(y.signum() > 0) {
+    r = (a+z.intValue()).toString(b).substr(1) + r;
+    y.divRemTo(d,y,z);
+  }
+  return z.intValue().toString(b) + r;
+}
+
+// (protected) convert from radix string
+function bnpFromRadix(s,b) {
+  this.fromInt(0);
+  if(b == null) b = 10;
+  var cs = this.chunkSize(b);
+  var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
+  for(var i = 0; i < s.length; ++i) {
+    var x = intAt(s,i);
+    if(x < 0) {
+      if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
+      continue;
+    }
+    w = b*w+x;
+    if(++j >= cs) {
+      this.dMultiply(d);
+      this.dAddOffset(w,0);
+      j = 0;
+      w = 0;
+    }
+  }
+  if(j > 0) {
+    this.dMultiply(Math.pow(b,j));
+    this.dAddOffset(w,0);
+  }
+  if(mi) BigInteger.ZERO.subTo(this,this);
+}
+
+// (protected) alternate constructor
+function bnpFromNumber(a,b,c) {
+  if("number" == typeof b) {
+    // new BigInteger(int,int,RNG)
+    if(a < 2) this.fromInt(1);
+    else {
+      this.fromNumber(a,c);
+      if(!this.testBit(a-1))	// force MSB set
+        this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);
+      if(this.isEven()) this.dAddOffset(1,0); // force odd
+      while(!this.isProbablePrime(b)) {
+        this.dAddOffset(2,0);
+        if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);
+      }
+    }
+  }
+  else {
+    // new BigInteger(int,RNG)
+    var x = new Array(), t = a&7;
+    x.length = (a>>3)+1;
+    b.nextBytes(x);
+    if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
+    this.fromString(x,256);
+  }
+}
+
+// (public) convert to bigendian byte array
+function bnToByteArray() {
+  var i = this.t, r = new Array();
+  r[0] = this.s;
+  var p = this.DB-(i*this.DB)%8, d, k = 0;
+  if(i-- > 0) {
+    if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)
+      r[k++] = d|(this.s<<(this.DB-p));
+    while(i >= 0) {
+      if(p < 8) {
+        d = (this[i]&((1<<p)-1))<<(8-p);
+        d |= this[--i]>>(p+=this.DB-8);
+      }
+      else {
+        d = (this[i]>>(p-=8))&0xff;
+        if(p <= 0) { p += this.DB; --i; }
+      }
+      //if((d&0x80) != 0) d |= -256;
+      //if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
+      if(k > 0 || d != this.s) r[k++] = d;
+    }
+  }
+  return r;
+}
+
+function bnEquals(a) { return(this.compareTo(a)==0); }
+function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
+function bnMax(a) { return(this.compareTo(a)>0)?this:a; }
+
+// (protected) r = this op a (bitwise)
+function bnpBitwiseTo(a,op,r) {
+  var i, f, m = Math.min(a.t,this.t);
+  for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);
+  if(a.t < this.t) {
+    f = a.s&this.DM;
+    for(i = m; i < this.t; ++i) r[i] = op(this[i],f);
+    r.t = this.t;
+  }
+  else {
+    f = this.s&this.DM;
+    for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);
+    r.t = a.t;
+  }
+  r.s = op(this.s,a.s);
+  r.clamp();
+}
+
+// (public) this & a
+function op_and(x,y) { return x&y; }
+function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }
+
+// (public) this | a
+function op_or(x,y) { return x|y; }
+function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }
+
+// (public) this ^ a
+function op_xor(x,y) { return x^y; }
+function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }
+
+// (public) this & ~a
+function op_andnot(x,y) { return x&~y; }
+function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }
+
+// (public) ~this
+function bnNot() {
+  var r = nbi();
+  for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];
+  r.t = this.t;
+  r.s = ~this.s;
+  return r;
+}
+
+// (public) this << n
+function bnShiftLeft(n) {
+  var r = nbi();
+  if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);
+  return r;
+}
+
+// (public) this >> n
+function bnShiftRight(n) {
+  var r = nbi();
+  if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);
+  return r;
+}
+
+// return index of lowest 1-bit in x, x < 2^31
+function lbit(x) {
+  if(x == 0) return -1;
+  var r = 0;
+  if((x&0xffff) == 0) { x >>= 16; r += 16; }
+  if((x&0xff) == 0) { x >>= 8; r += 8; }
+  if((x&0xf) == 0) { x >>= 4; r += 4; }
+  if((x&3) == 0) { x >>= 2; r += 2; }
+  if((x&1) == 0) ++r;
+  return r;
+}
+
+// (public) returns index of lowest 1-bit (or -1 if none)
+function bnGetLowestSetBit() {
+  for(var i = 0; i < this.t; ++i)
+    if(this[i] != 0) return i*this.DB+lbit(this[i]);
+  if(this.s < 0) return this.t*this.DB;
+  return -1;
+}
+
+// return number of 1 bits in x
+function cbit(x) {
+  var r = 0;
+  while(x != 0) { x &= x-1; ++r; }
+  return r;
+}
+
+// (public) return number of set bits
+function bnBitCount() {
+  var r = 0, x = this.s&this.DM;
+  for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);
+  return r;
+}
+
+// (public) true iff nth bit is set
+function bnTestBit(n) {
+  var j = Math.floor(n/this.DB);
+  if(j >= this.t) return(this.s!=0);
+  return((this[j]&(1<<(n%this.DB)))!=0);
+}
+
+// (protected) this op (1<<n)
+function bnpChangeBit(n,op) {
+  var r = BigInteger.ONE.shiftLeft(n);
+  this.bitwiseTo(r,op,r);
+  return r;
+}
+
+// (public) this | (1<<n)
+function bnSetBit(n) { return this.changeBit(n,op_or); }
+
+// (public) this & ~(1<<n)
+function bnClearBit(n) { return this.changeBit(n,op_andnot); }
+
+// (public) this ^ (1<<n)
+function bnFlipBit(n) { return this.changeBit(n,op_xor); }
+
+// (protected) r = this + a
+function bnpAddTo(a,r) {
+  var i = 0, c = 0, m = Math.min(a.t,this.t);
+  while(i < m) {
+    c += this[i]+a[i];
+    r[i++] = c&this.DM;
+    c >>= this.DB;
+  }
+  if(a.t < this.t) {
+    c += a.s;
+    while(i < this.t) {
+      c += this[i];
+      r[i++] = c&this.DM;
+      c >>= this.DB;
+    }
+    c += this.s;
+  }
+  else {
+    c += this.s;
+    while(i < a.t) {
+      c += a[i];
+      r[i++] = c&this.DM;
+      c >>= this.DB;
+    }
+    c += a.s;
+  }
+  r.s = (c<0)?-1:0;
+  if(c > 0) r[i++] = c;
+  else if(c < -1) r[i++] = this.DV+c;
+  r.t = i;
+  r.clamp();
+}
+
+// (public) this + a
+function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }
+
+// (public) this - a
+function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }
+
+// (public) this * a
+function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }
+
+// (public) this^2
+function bnSquare() { var r = nbi(); this.squareTo(r); return r; }
+
+// (public) this / a
+function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }
+
+// (public) this % a
+function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }
+
+// (public) [this/a,this%a]
+function bnDivideAndRemainder(a) {
+  var q = nbi(), r = nbi();
+  this.divRemTo(a,q,r);
+  return new Array(q,r);
+}
+
+// (protected) this *= n, this >= 0, 1 < n < DV
+function bnpDMultiply(n) {
+  this[this.t] = this.am(0,n-1,this,0,0,this.t);
+  ++this.t;
+  this.clamp();
+}
+
+// (protected) this += n << w words, this >= 0
+function bnpDAddOffset(n,w) {
+  if(n == 0) return;
+  while(this.t <= w) this[this.t++] = 0;
+  this[w] += n;
+  while(this[w] >= this.DV) {
+    this[w] -= this.DV;
+    if(++w >= this.t) this[this.t++] = 0;
+    ++this[w];
+  }
+}
+
+// A "null" reducer
+function NullExp() {}
+function nNop(x) { return x; }
+function nMulTo(x,y,r) { x.multiplyTo(y,r); }
+function nSqrTo(x,r) { x.squareTo(r); }
+
+NullExp.prototype.convert = nNop;
+NullExp.prototype.revert = nNop;
+NullExp.prototype.mulTo = nMulTo;
+NullExp.prototype.sqrTo = nSqrTo;
+
+// (public) this^e
+function bnPow(e) { return this.exp(e,new NullExp()); }
+
+// (protected) r = lower n words of "this * a", a.t <= n
+// "this" should be the larger one if appropriate.
+function bnpMultiplyLowerTo(a,n,r) {
+  var i = Math.min(this.t+a.t,n);
+  r.s = 0; // assumes a,this >= 0
+  r.t = i;
+  while(i > 0) r[--i] = 0;
+  var j;
+  for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);
+  for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);
+  r.clamp();
+}
+
+// (protected) r = "this * a" without lower n words, n > 0
+// "this" should be the larger one if appropriate.
+function bnpMultiplyUpperTo(a,n,r) {
+  --n;
+  var i = r.t = this.t+a.t-n;
+  r.s = 0; // assumes a,this >= 0
+  while(--i >= 0) r[i] = 0;
+  for(i = Math.max(n-this.t,0); i < a.t; ++i)
+    r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);
+  r.clamp();
+  r.drShiftTo(1,r);
+}
+
+// Barrett modular reduction
+function Barrett(m) {
+  // setup Barrett
+  this.r2 = nbi();
+  this.q3 = nbi();
+  BigInteger.ONE.dlShiftTo(2*m.t,this.r2);
+  this.mu = this.r2.divide(m);
+  this.m = m;
+}
+
+function barrettConvert(x) {
+  if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);
+  else if(x.compareTo(this.m) < 0) return x;
+  else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
+}
+
+function barrettRevert(x) { return x; }
+
+// x = x mod m (HAC 14.42)
+function barrettReduce(x) {
+  x.drShiftTo(this.m.t-1,this.r2);
+  if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }
+  this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);
+  this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);
+  while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);
+  x.subTo(this.r2,x);
+  while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
+}
+
+// r = x^2 mod m; x != r
+function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
+
+// r = x*y mod m; x,y != r
+function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
+
+Barrett.prototype.convert = barrettConvert;
+Barrett.prototype.revert = barrettRevert;
+Barrett.prototype.reduce = barrettReduce;
+Barrett.prototype.mulTo = barrettMulTo;
+Barrett.prototype.sqrTo = barrettSqrTo;
+
+// (public) this^e % m (HAC 14.85)
+function bnModPow(e,m) {
+  var i = e.bitLength(), k, r = nbv(1), z;
+  if(i <= 0) return r;
+  else if(i < 18) k = 1;
+  else if(i < 48) k = 3;
+  else if(i < 144) k = 4;
+  else if(i < 768) k = 5;
+  else k = 6;
+  if(i < 8)
+    z = new Classic(m);
+  else if(m.isEven())
+    z = new Barrett(m);
+  else
+    z = new Montgomery(m);
+
+  // precomputation
+  var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;
+  g[1] = z.convert(this);
+  if(k > 1) {
+    var g2 = nbi();
+    z.sqrTo(g[1],g2);
+    while(n <= km) {
+      g[n] = nbi();
+      z.mulTo(g2,g[n-2],g[n]);
+      n += 2;
+    }
+  }
+
+  var j = e.t-1, w, is1 = true, r2 = nbi(), t;
+  i = nbits(e[j])-1;
+  while(j >= 0) {
+    if(i >= k1) w = (e[j]>>(i-k1))&km;
+    else {
+      w = (e[j]&((1<<(i+1))-1))<<(k1-i);
+      if(j > 0) w |= e[j-1]>>(this.DB+i-k1);
+    }
+
+    n = k;
+    while((w&1) == 0) { w >>= 1; --n; }
+    if((i -= n) < 0) { i += this.DB; --j; }
+    if(is1) {	// ret == 1, don't bother squaring or multiplying it
+      g[w].copyTo(r);
+      is1 = false;
+    }
+    else {
+      while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }
+      if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }
+      z.mulTo(r2,g[w],r);
+    }
+
+    while(j >= 0 && (e[j]&(1<<i)) == 0) {
+      z.sqrTo(r,r2); t = r; r = r2; r2 = t;
+      if(--i < 0) { i = this.DB-1; --j; }
+    }
+  }
+  return z.revert(r);
+}
+
+// (public) gcd(this,a) (HAC 14.54)
+function bnGCD(a) {
+  var x = (this.s<0)?this.negate():this.clone();
+  var y = (a.s<0)?a.negate():a.clone();
+  if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }
+  var i = x.getLowestSetBit(), g = y.getLowestSetBit();
+  if(g < 0) return x;
+  if(i < g) g = i;
+  if(g > 0) {
+    x.rShiftTo(g,x);
+    y.rShiftTo(g,y);
+  }
+  while(x.signum() > 0) {
+    if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);
+    if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);
+    if(x.compareTo(y) >= 0) {
+      x.subTo(y,x);
+      x.rShiftTo(1,x);
+    }
+    else {
+      y.subTo(x,y);
+      y.rShiftTo(1,y);
+    }
+  }
+  if(g > 0) y.lShiftTo(g,y);
+  return y;
+}
+
+// (protected) this % n, n < 2^26
+function bnpModInt(n) {
+  if(n <= 0) return 0;
+  var d = this.DV%n, r = (this.s<0)?n-1:0;
+  if(this.t > 0)
+    if(d == 0) r = this[0]%n;
+    else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;
+  return r;
+}
+
+// (public) 1/this % m (HAC 14.61)
+function bnModInverse(m) {
+  var ac = m.isEven();
+  if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
+  var u = m.clone(), v = this.clone();
+  var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
+  while(u.signum() != 0) {
+    while(u.isEven()) {
+      u.rShiftTo(1,u);
+      if(ac) {
+        if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
+        a.rShiftTo(1,a);
+      }
+      else if(!b.isEven()) b.subTo(m,b);
+      b.rShiftTo(1,b);
+    }
+    while(v.isEven()) {
+      v.rShiftTo(1,v);
+      if(ac) {
+        if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
+        c.rShiftTo(1,c);
+      }
+      else if(!d.isEven()) d.subTo(m,d);
+      d.rShiftTo(1,d);
+    }
+    if(u.compareTo(v) >= 0) {
+      u.subTo(v,u);
+      if(ac) a.subTo(c,a);
+      b.subTo(d,b);
+    }
+    else {
+      v.subTo(u,v);
+      if(ac) c.subTo(a,c);
+      d.subTo(b,d);
+    }
+  }
+  if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
+  if(d.compareTo(m) >= 0) return d.subtract(m);
+  if(d.signum() < 0) d.addTo(m,d); else return d;
+  if(d.signum() < 0) return d.add(m); else return d;
+}
+
+var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,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];
+var lplim = (1<<26)/lowprimes[lowprimes.length-1];
+
+// (public) test primality with certainty >= 1-.5^t
+function bnIsProbablePrime(t) {
+  var i, x = this.abs();
+  if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {
+    for(i = 0; i < lowprimes.length; ++i)
+      if(x[0] == lowprimes[i]) return true;
+    return false;
+  }
+  if(x.isEven()) return false;
+  i = 1;
+  while(i < lowprimes.length) {
+    var m = lowprimes[i], j = i+1;
+    while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];
+    m = x.modInt(m);
+    while(i < j) if(m%lowprimes[i++] == 0) return false;
+  }
+  return x.millerRabin(t);
+}
+
+/* added by Recurity Labs */
+
+function nbits(x) {
+	var n = 1, t;
+	if ((t = x >>> 16) != 0) {
+		x = t;
+		n += 16;
+	}
+	if ((t = x >> 8) != 0) {
+		x = t;
+		n += 8;
+	}
+	if ((t = x >> 4) != 0) {
+		x = t;
+		n += 4;
+	}
+	if ((t = x >> 2) != 0) {
+		x = t;
+		n += 2;
+	}
+	if ((t = x >> 1) != 0) {
+		x = t;
+		n += 1;
+	}
+	return n;
+}
+
+function bnToMPI () {
+	var ba = this.toByteArray();
+	var size = (ba.length-1)*8+nbits(ba[0]);
+	var result = "";
+	result += String.fromCharCode((size & 0xFF00) >> 8);
+	result += String.fromCharCode(size & 0xFF);
+	result += util.bin2str(ba);
+	return result;
+}
+/* END of addition */
+
+// (protected) true if probably prime (HAC 4.24, Miller-Rabin)
+function bnpMillerRabin(t) {
+  var n1 = this.subtract(BigInteger.ONE);
+  var k = n1.getLowestSetBit();
+  if(k <= 0) return false;
+  var r = n1.shiftRight(k);
+  t = (t+1)>>1;
+  if(t > lowprimes.length) t = lowprimes.length;
+  var a = nbi();
+  for(var i = 0; i < t; ++i) {
+    //Pick bases at random, instead of starting at 2
+    a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);
+    var y = a.modPow(r,this);
+    if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
+      var j = 1;
+      while(j++ < k && y.compareTo(n1) != 0) {
+        y = y.modPowInt(2,this);
+        if(y.compareTo(BigInteger.ONE) == 0) return false;
+      }
+      if(y.compareTo(n1) != 0) return false;
+    }
+  }
+  return true;
+}
+
+// protected
+BigInteger.prototype.chunkSize = bnpChunkSize;
+BigInteger.prototype.toRadix = bnpToRadix;
+BigInteger.prototype.fromRadix = bnpFromRadix;
+BigInteger.prototype.fromNumber = bnpFromNumber;
+BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
+BigInteger.prototype.changeBit = bnpChangeBit;
+BigInteger.prototype.addTo = bnpAddTo;
+BigInteger.prototype.dMultiply = bnpDMultiply;
+BigInteger.prototype.dAddOffset = bnpDAddOffset;
+BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
+BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
+BigInteger.prototype.modInt = bnpModInt;
+BigInteger.prototype.millerRabin = bnpMillerRabin;
+
+// public
+BigInteger.prototype.clone = bnClone;
+BigInteger.prototype.intValue = bnIntValue;
+BigInteger.prototype.byteValue = bnByteValue;
+BigInteger.prototype.shortValue = bnShortValue;
+BigInteger.prototype.signum = bnSigNum;
+BigInteger.prototype.toByteArray = bnToByteArray;
+BigInteger.prototype.equals = bnEquals;
+BigInteger.prototype.min = bnMin;
+BigInteger.prototype.max = bnMax;
+BigInteger.prototype.and = bnAnd;
+BigInteger.prototype.or = bnOr;
+BigInteger.prototype.xor = bnXor;
+BigInteger.prototype.andNot = bnAndNot;
+BigInteger.prototype.not = bnNot;
+BigInteger.prototype.shiftLeft = bnShiftLeft;
+BigInteger.prototype.shiftRight = bnShiftRight;
+BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
+BigInteger.prototype.bitCount = bnBitCount;
+BigInteger.prototype.testBit = bnTestBit;
+BigInteger.prototype.setBit = bnSetBit;
+BigInteger.prototype.clearBit = bnClearBit;
+BigInteger.prototype.flipBit = bnFlipBit;
+BigInteger.prototype.add = bnAdd;
+BigInteger.prototype.subtract = bnSubtract;
+BigInteger.prototype.multiply = bnMultiply;
+BigInteger.prototype.divide = bnDivide;
+BigInteger.prototype.remainder = bnRemainder;
+BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
+BigInteger.prototype.modPow = bnModPow;
+BigInteger.prototype.modInverse = bnModInverse;
+BigInteger.prototype.pow = bnPow;
+BigInteger.prototype.gcd = bnGCD;
+BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
+BigInteger.prototype.toMPI = bnToMPI;
+
+// JSBN-specific extension
+BigInteger.prototype.square = bnSquare;
+// GPG4Browsers - An OpenPGP implementation in javascript
+// Copyright (C) 2011 Recurity Labs GmbH
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// ElGamal implementation
+
+function Elgamal() {
+	
+	function encrypt(m,g,p,y) {
+		//  choose k in {2,...,p-2}
+		var two = BigInteger.ONE.add(BigInteger.ONE);
+		var pMinus2 = p.subtract(two);
+		var k = openpgp_crypto_getRandomBigIntegerInRange(two, pMinus2);
+		var k = k.mod(pMinus2).add(BigInteger.ONE);
+		var c = new Array();
+		c[0] = g.modPow(k, p);
+		c[1] = y.modPow(k, p).multiply(m).mod(p).toMPI();
+		c[0] = c[0].toMPI();
+		return c;
+	}
+	
+	function decrypt(c1,c2,p,x) {
+		util.print_debug("Elgamal Decrypt:\nc1:"+util.hexstrdump(c1.toMPI())+"\n"+
+			  "c2:"+util.hexstrdump(c2.toMPI())+"\n"+
+			  "p:"+util.hexstrdump(p.toMPI())+"\n"+
+			  "x:"+util.hexstrdump(x.toMPI()));
+		return (c1.modPow(x, p).modInverse(p)).multiply(c2).mod(p);
+		//var c = c1.pow(x).modInverse(p); // c0^-a mod p
+	    //return c.multiply(c2).mod(p);
+	}
+	
+	// signing and signature verification using Elgamal is not required by OpenPGP.
+	this.encrypt = encrypt;
+	this.decrypt = decrypt;
+}// GPG4Browsers - An OpenPGP implementation in javascript
+// Copyright (C) 2011 Recurity Labs GmbH
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// A Digital signature algorithm implementation
+
+function DSA() {
+	// s1 = ((g**s) mod p) mod q
+	// s1 = ((s**-1)*(sha-1(m)+(s1*x) mod q)
+	function sign(hashalgo, m, g, p, q, x) {
+		// If the output size of the chosen hash is larger than the number of
+		// bits of q, the hash result is truncated to fit by taking the number
+		// of leftmost bits equal to the number of bits of q.  This (possibly
+		// truncated) hash function result is treated as a number and used
+		// directly in the DSA signature algorithm.
+		var hashed_data = util.getLeftNBits(openpgp_crypto_hashData(hashalgo,m),q.bitLength());
+		var hash = new BigInteger(util.hexstrdump(hashed_data), 16);
+		var k = openpgp_crypto_getRandomBigIntegerInRange(BigInteger.ONE.add(BigInteger.ONE), q.subtract(BigInteger.ONE));
+		var s1 = (g.modPow(k,p)).mod(q); 
+		var s2 = (k.modInverse(q).multiply(hash.add(x.multiply(s1)))).mod(q);
+		var result = new Array();
+		result[0] = s1.toMPI();
+		result[1] = s2.toMPI();
+		return result;
+	}
+	function select_hash_algorithm(q) {
+		var usersetting = openpgp.config.config.prefer_hash_algorithm;
+		/*
+		 * 1024-bit key, 160-bit q, SHA-1, SHA-224, SHA-256, SHA-384, or SHA-512 hash
+		 * 2048-bit key, 224-bit q, SHA-224, SHA-256, SHA-384, or SHA-512 hash
+		 * 2048-bit key, 256-bit q, SHA-256, SHA-384, or SHA-512 hash
+		 * 3072-bit key, 256-bit q, SHA-256, SHA-384, or SHA-512 hash
+		 */
+		switch (Math.round(q.bitLength() / 8)) {
+		case 20: // 1024 bit
+			if (usersetting != 2 &&
+				usersetting > 11 &&
+				usersetting != 10 &&
+				usersetting < 8)
+				return 2; // prefer sha1
+			return usersetting;
+		case 28: // 2048 bit
+			if (usersetting > 11 &&
+					usersetting < 8)
+					return 11;
+			return usersetting;
+		case 32: // 4096 bit // prefer sha224
+			if (usersetting > 10 &&
+					usersetting < 8)
+					return 8; // prefer sha256
+			return usersetting;
+		default:
+			util.print_debug("DSA select hash algorithm: returning null for an unknown length of q");
+			return null;
+			
+		}
+	}
+	this.select_hash_algorithm = select_hash_algorithm;
+	
+	function verify(hashalgo, s1,s2,m,p,q,g,y) {
+		var hashed_data = util.getLeftNBits(openpgp_crypto_hashData(hashalgo,m),q.bitLength());
+		var hash = new BigInteger(util.hexstrdump(hashed_data), 16); 
+		if (BigInteger.ZERO.compareTo(s1) > 0 ||
+				s1.compareTo(q) > 0 ||
+				BigInteger.ZERO.compareTo(s2) > 0 ||
+				s2.compareTo(q) > 0) {
+			util.print_error("invalid DSA Signature");
+			return null;
+		}
+		var w = s2.modInverse(q);
+		var u1 = hash.multiply(w).mod(q);
+		var u2 = s1.multiply(w).mod(q);
+		return g.modPow(u1,p).multiply(y.modPow(u2,p)).mod(p).mod(q);
+	}
+	
+	/*
+	 * unused code. This can be used as a start to write a key generator
+	 * function.
+	
+	function generateKey(bitcount) {
+	    var qi = new BigInteger(bitcount, primeCenterie);
+	    var pi = generateP(q, 512);
+	    var gi = generateG(p, q, bitcount);
+	    var xi;
+	    do {
+	        xi = new BigInteger(q.bitCount(), rand);
+	    } while (x.compareTo(BigInteger.ZERO) != 1 && x.compareTo(q) != -1);
+	    var yi = g.modPow(x, p);
+	    return {x: xi, q: qi, p: pi, g: gi, y: yi};
 	}
 
-	/**
-	 * produces a key using the specified passphrase and the defined hashAlgorithm 
-	 * @param passphrase [String] passphrase containing user input
-	 * @return [String] produced key with a length corresponding to hashAlgorithm hash length
-	 */
-	function produce_key(passphrase, numBytes) {
-		if (this.type == 0) {
-			return openpgp_crypto_hashData(this.hashAlgorithm,passphrase);
-		} else if (this.type == 1) {
-			return openpgp_crypto_hashData(this.hashAlgorithm,this.saltValue+passphrase);
-		} else if (this.type == 3) {
-			var isp = [];
-			isp[0] = this.saltValue+passphrase;
-			while (isp.length*(this.saltValue+passphrase).length < this.count)
-				isp.push(this.saltValue+passphrase);
-			isp = isp.join('');			
-			if (isp.length > this.count)
-				isp = isp.substr(0, this.count);
-			if(numBytes && (numBytes == 24 || numBytes == 32)){ //This if accounts for RFC 4880 3.7.1.1 -- If hash size is greater than block size, use leftmost bits.  If blocksize larger than hash size, we need to rehash isp and prepend with 0.
-			    var key = openpgp_crypto_hashData(this.hashAlgorithm,isp);
-			    return key + openpgp_crypto_hashData(this.hashAlgorithm,String.fromCharCode(0)+isp);
-			}
-			return openpgp_crypto_hashData(this.hashAlgorithm,isp);
-		} else return null;
+	function generateP(q, bitlength, randomfn) {
+	    if (bitlength % 64 != 0) {
+	    	return false;
+	    }
+	    var pTemp;
+	    var pTemp2;
+	    do {
+	        pTemp = randomfn(bitcount, true);
+	        pTemp2 = pTemp.subtract(BigInteger.ONE);
+	        pTemp = pTemp.subtract(pTemp2.remainder(q));
+	    } while (!pTemp.isProbablePrime(primeCenterie) || pTemp.bitLength() != l);
+	    return pTemp;
 	}
 	
-	this.read = read;
-	this.write = write;
-	this.produce_key = produce_key;
+	function generateG(p, q, bitlength, randomfn) {
+	    var aux = p.subtract(BigInteger.ONE);
+	    var pow = aux.divide(q);
+	    var gTemp;
+	    do {
+	        gTemp = randomfn(bitlength);
+	    } while (gTemp.compareTo(aux) != -1 && gTemp.compareTo(BigInteger.ONE) != 1);
+	    return gTemp.modPow(pow, p);
+	}
+
+	function generateK(q, bitlength, randomfn) {
+	    var tempK;
+	    do {
+	        tempK = randomfn(bitlength, false);
+	    } while (tempK.compareTo(q) != -1 && tempK.compareTo(BigInteger.ZERO) != 1);
+	    return tempK;
+	}
+
+	function generateR(q,p) {
+	    k = generateK(q);
+	    var r = g.modPow(k, p).mod(q);
+	    return r;
+	}
+
+	function generateS(hashfn,k,r,m,q,x) {
+        var hash = hashfn(m);
+        s = (k.modInverse(q).multiply(hash.add(x.multiply(r)))).mod(q);
+	    return s;
+	} */
+	this.sign = sign;
+	this.verify = verify;
+	// this.generate = generateKey;
+}
+//Paul Tero, July 2001
+//http://www.tero.co.uk/des/
+//
+//Optimised for performance with large blocks by Michael Hayworth, November 2001
+//http://www.netdealing.com
+//
+// Modified by Recurity Labs GmbH
+
+//THIS SOFTWARE IS PROVIDED "AS IS" AND
+//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+//IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+//FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+//DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+//OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+//HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+//OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+//SUCH DAMAGE.
+
+//des
+//this takes the key, the message, and whether to encrypt or decrypt
+
+// added by Recurity Labs
+function desede(block,key) {
+	var key1 = key.substring(0,8);
+	var key2 = key.substring(8,16);
+	var key3 = key.substring(16,24);
+	return util.str2bin(des(des_createKeys(key3),des(des_createKeys(key2),des(des_createKeys(key1),util.bin2str(block), true, 0,null,null), false, 0,null,null), true, 0,null,null));
+}
+
+
+function des (keys, message, encrypt, mode, iv, padding) {
+  //declaring this locally speeds things up a bit
+  var spfunction1 = new Array (0x1010400,0,0x10000,0x1010404,0x1010004,0x10404,0x4,0x10000,0x400,0x1010400,0x1010404,0x400,0x1000404,0x1010004,0x1000000,0x4,0x404,0x1000400,0x1000400,0x10400,0x10400,0x1010000,0x1010000,0x1000404,0x10004,0x1000004,0x1000004,0x10004,0,0x404,0x10404,0x1000000,0x10000,0x1010404,0x4,0x1010000,0x1010400,0x1000000,0x1000000,0x400,0x1010004,0x10000,0x10400,0x1000004,0x400,0x4,0x1000404,0x10404,0x1010404,0x10004,0x1010000,0x1000404,0x1000004,0x404,0x10404,0x1010400,0x404,0x1000400,0x1000400,0,0x10004,0x10400,0,0x1010004);
+  var spfunction2 = new Array (-0x7fef7fe0,-0x7fff8000,0x8000,0x108020,0x100000,0x20,-0x7fefffe0,-0x7fff7fe0,-0x7fffffe0,-0x7fef7fe0,-0x7fef8000,-0x80000000,-0x7fff8000,0x100000,0x20,-0x7fefffe0,0x108000,0x100020,-0x7fff7fe0,0,-0x80000000,0x8000,0x108020,-0x7ff00000,0x100020,-0x7fffffe0,0,0x108000,0x8020,-0x7fef8000,-0x7ff00000,0x8020,0,0x108020,-0x7fefffe0,0x100000,-0x7fff7fe0,-0x7ff00000,-0x7fef8000,0x8000,-0x7ff00000,-0x7fff8000,0x20,-0x7fef7fe0,0x108020,0x20,0x8000,-0x80000000,0x8020,-0x7fef8000,0x100000,-0x7fffffe0,0x100020,-0x7fff7fe0,-0x7fffffe0,0x100020,0x108000,0,-0x7fff8000,0x8020,-0x80000000,-0x7fefffe0,-0x7fef7fe0,0x108000);
+  var spfunction3 = new Array (0x208,0x8020200,0,0x8020008,0x8000200,0,0x20208,0x8000200,0x20008,0x8000008,0x8000008,0x20000,0x8020208,0x20008,0x8020000,0x208,0x8000000,0x8,0x8020200,0x200,0x20200,0x8020000,0x8020008,0x20208,0x8000208,0x20200,0x20000,0x8000208,0x8,0x8020208,0x200,0x8000000,0x8020200,0x8000000,0x20008,0x208,0x20000,0x8020200,0x8000200,0,0x200,0x20008,0x8020208,0x8000200,0x8000008,0x200,0,0x8020008,0x8000208,0x20000,0x8000000,0x8020208,0x8,0x20208,0x20200,0x8000008,0x8020000,0x8000208,0x208,0x8020000,0x20208,0x8,0x8020008,0x20200);
+  var spfunction4 = new Array (0x802001,0x2081,0x2081,0x80,0x802080,0x800081,0x800001,0x2001,0,0x802000,0x802000,0x802081,0x81,0,0x800080,0x800001,0x1,0x2000,0x800000,0x802001,0x80,0x800000,0x2001,0x2080,0x800081,0x1,0x2080,0x800080,0x2000,0x802080,0x802081,0x81,0x800080,0x800001,0x802000,0x802081,0x81,0,0,0x802000,0x2080,0x800080,0x800081,0x1,0x802001,0x2081,0x2081,0x80,0x802081,0x81,0x1,0x2000,0x800001,0x2001,0x802080,0x800081,0x2001,0x2080,0x800000,0x802001,0x80,0x800000,0x2000,0x802080);
+  var spfunction5 = new Array (0x100,0x2080100,0x2080000,0x42000100,0x80000,0x100,0x40000000,0x2080000,0x40080100,0x80000,0x2000100,0x40080100,0x42000100,0x42080000,0x80100,0x40000000,0x2000000,0x40080000,0x40080000,0,0x40000100,0x42080100,0x42080100,0x2000100,0x42080000,0x40000100,0,0x42000000,0x2080100,0x2000000,0x42000000,0x80100,0x80000,0x42000100,0x100,0x2000000,0x40000000,0x2080000,0x42000100,0x40080100,0x2000100,0x40000000,0x42080000,0x2080100,0x40080100,0x100,0x2000000,0x42080000,0x42080100,0x80100,0x42000000,0x42080100,0x2080000,0,0x40080000,0x42000000,0x80100,0x2000100,0x40000100,0x80000,0,0x40080000,0x2080100,0x40000100);
+  var spfunction6 = new Array (0x20000010,0x20400000,0x4000,0x20404010,0x20400000,0x10,0x20404010,0x400000,0x20004000,0x404010,0x400000,0x20000010,0x400010,0x20004000,0x20000000,0x4010,0,0x400010,0x20004010,0x4000,0x404000,0x20004010,0x10,0x20400010,0x20400010,0,0x404010,0x20404000,0x4010,0x404000,0x20404000,0x20000000,0x20004000,0x10,0x20400010,0x404000,0x20404010,0x400000,0x4010,0x20000010,0x400000,0x20004000,0x20000000,0x4010,0x20000010,0x20404010,0x404000,0x20400000,0x404010,0x20404000,0,0x20400010,0x10,0x4000,0x20400000,0x404010,0x4000,0x400010,0x20004010,0,0x20404000,0x20000000,0x400010,0x20004010);
+  var spfunction7 = new Array (0x200000,0x4200002,0x4000802,0,0x800,0x4000802,0x200802,0x4200800,0x4200802,0x200000,0,0x4000002,0x2,0x4000000,0x4200002,0x802,0x4000800,0x200802,0x200002,0x4000800,0x4000002,0x4200000,0x4200800,0x200002,0x4200000,0x800,0x802,0x4200802,0x200800,0x2,0x4000000,0x200800,0x4000000,0x200800,0x200000,0x4000802,0x4000802,0x4200002,0x4200002,0x2,0x200002,0x4000000,0x4000800,0x200000,0x4200800,0x802,0x200802,0x4200800,0x802,0x4000002,0x4200802,0x4200000,0x200800,0,0x2,0x4200802,0,0x200802,0x4200000,0x800,0x4000002,0x4000800,0x800,0x200002);
+  var spfunction8 = new Array (0x10001040,0x1000,0x40000,0x10041040,0x10000000,0x10001040,0x40,0x10000000,0x40040,0x10040000,0x10041040,0x41000,0x10041000,0x41040,0x1000,0x40,0x10040000,0x10000040,0x10001000,0x1040,0x41000,0x40040,0x10040040,0x10041000,0x1040,0,0,0x10040040,0x10000040,0x10001000,0x41040,0x40000,0x41040,0x40000,0x10041000,0x1000,0x40,0x10040040,0x1000,0x41040,0x10001000,0x40,0x10000040,0x10040000,0x10040040,0x10000000,0x40000,0x10001040,0,0x10041040,0x40040,0x10000040,0x10040000,0x10001000,0x10001040,0,0x10041040,0x41000,0x41000,0x1040,0x1040,0x40040,0x10000000,0x10041000);
+
+  //create the 16 or 48 subkeys we will need
+  var m=0, i, j, temp, temp2, right1, right2, left, right, looping;
+  var cbcleft, cbcleft2, cbcright, cbcright2
+  var endloop, loopinc;
+  var len = message.length;
+  var chunk = 0;
+  //set up the loops for single and triple des
+  var iterations = keys.length == 32 ? 3 : 9; //single or triple des
+  if (iterations == 3) {looping = encrypt ? new Array (0, 32, 2) : new Array (30, -2, -2);}
+  else {looping = encrypt ? new Array (0, 32, 2, 62, 30, -2, 64, 96, 2) : new Array (94, 62, -2, 32, 64, 2, 30, -2, -2);}
+
+  //pad the message depending on the padding parameter
+  if (padding == 2) message += "        "; //pad the message with spaces
+  else if (padding == 1) {temp = 8-(len%8); message += String.fromCharCode (temp,temp,temp,temp,temp,temp,temp,temp); if (temp==8) len+=8;} //PKCS7 padding
+  else if (!padding) message += "\0\0\0\0\0\0\0\0"; //pad the message out with null bytes
+
+  //store the result here
+  result = "";
+  tempresult = "";
+
+  if (mode == 1) { //CBC mode
+    cbcleft = (iv.charCodeAt(m++) << 24) | (iv.charCodeAt(m++) << 16) | (iv.charCodeAt(m++) << 8) | iv.charCodeAt(m++);
+    cbcright = (iv.charCodeAt(m++) << 24) | (iv.charCodeAt(m++) << 16) | (iv.charCodeAt(m++) << 8) | iv.charCodeAt(m++);
+    m=0;
+  }
+
+  //loop through each 64 bit chunk of the message
+  while (m < len) {
+    left = (message.charCodeAt(m++) << 24) | (message.charCodeAt(m++) << 16) | (message.charCodeAt(m++) << 8) | message.charCodeAt(m++);
+    right = (message.charCodeAt(m++) << 24) | (message.charCodeAt(m++) << 16) | (message.charCodeAt(m++) << 8) | message.charCodeAt(m++);
+
+    //for Cipher Block Chaining mode, xor the message with the previous result
+    if (mode == 1) {if (encrypt) {left ^= cbcleft; right ^= cbcright;} else {cbcleft2 = cbcleft; cbcright2 = cbcright; cbcleft = left; cbcright = right;}}
+
+    //first each 64 but chunk of the message must be permuted according to IP
+    temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4);
+    temp = ((left >>> 16) ^ right) & 0x0000ffff; right ^= temp; left ^= (temp << 16);
+    temp = ((right >>> 2) ^ left) & 0x33333333; left ^= temp; right ^= (temp << 2);
+    temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8);
+    temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
+
+    left = ((left << 1) | (left >>> 31)); 
+    right = ((right << 1) | (right >>> 31)); 
+
+    //do this either 1 or 3 times for each chunk of the message
+    for (j=0; j<iterations; j+=3) {
+      endloop = looping[j+1];
+      loopinc = looping[j+2];
+      //now go through and perform the encryption or decryption  
+      for (i=looping[j]; i!=endloop; i+=loopinc) { //for efficiency
+        right1 = right ^ keys[i]; 
+        right2 = ((right >>> 4) | (right << 28)) ^ keys[i+1];
+        //the result is attained by passing these bytes through the S selection functions
+        temp = left;
+        left = right;
+        right = temp ^ (spfunction2[(right1 >>> 24) & 0x3f] | spfunction4[(right1 >>> 16) & 0x3f]
+              | spfunction6[(right1 >>>  8) & 0x3f] | spfunction8[right1 & 0x3f]
+              | spfunction1[(right2 >>> 24) & 0x3f] | spfunction3[(right2 >>> 16) & 0x3f]
+              | spfunction5[(right2 >>>  8) & 0x3f] | spfunction7[right2 & 0x3f]);
+      }
+      temp = left; left = right; right = temp; //unreverse left and right
+    } //for either 1 or 3 iterations
+
+    //move then each one bit to the right
+    left = ((left >>> 1) | (left << 31)); 
+    right = ((right >>> 1) | (right << 31)); 
+
+    //now perform IP-1, which is IP in the opposite direction
+    temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
+    temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8);
+    temp = ((right >>> 2) ^ left) & 0x33333333; left ^= temp; right ^= (temp << 2);
+    temp = ((left >>> 16) ^ right) & 0x0000ffff; right ^= temp; left ^= (temp << 16);
+    temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4);
+
+    //for Cipher Block Chaining mode, xor the message with the previous result
+    if (mode == 1) {if (encrypt) {cbcleft = left; cbcright = right;} else {left ^= cbcleft2; right ^= cbcright2;}}
+    tempresult += String.fromCharCode ((left>>>24), ((left>>>16) & 0xff), ((left>>>8) & 0xff), (left & 0xff), (right>>>24), ((right>>>16) & 0xff), ((right>>>8) & 0xff), (right & 0xff));
+
+    chunk += 8;
+    if (chunk == 512) {result += tempresult; tempresult = ""; chunk = 0;}
+  } //for every 8 characters, or 64 bits in the message
+
+  //return the result as an array
+  result += tempresult;
+  result = result.replace(/\0*$/g, "");
+  return result;
+} //end of des
+
+
+
+//des_createKeys
+//this takes as input a 64 bit key (even though only 56 bits are used)
+//as an array of 2 integers, and returns 16 48 bit keys
+function des_createKeys (key) {
+  //declaring this locally speeds things up a bit
+  pc2bytes0  = new Array (0,0x4,0x20000000,0x20000004,0x10000,0x10004,0x20010000,0x20010004,0x200,0x204,0x20000200,0x20000204,0x10200,0x10204,0x20010200,0x20010204);
+  pc2bytes1  = new Array (0,0x1,0x100000,0x100001,0x4000000,0x4000001,0x4100000,0x4100001,0x100,0x101,0x100100,0x100101,0x4000100,0x4000101,0x4100100,0x4100101);
+  pc2bytes2  = new Array (0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808,0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808);
+  pc2bytes3  = new Array (0,0x200000,0x8000000,0x8200000,0x2000,0x202000,0x8002000,0x8202000,0x20000,0x220000,0x8020000,0x8220000,0x22000,0x222000,0x8022000,0x8222000);
+  pc2bytes4  = new Array (0,0x40000,0x10,0x40010,0,0x40000,0x10,0x40010,0x1000,0x41000,0x1010,0x41010,0x1000,0x41000,0x1010,0x41010);
+  pc2bytes5  = new Array (0,0x400,0x20,0x420,0,0x400,0x20,0x420,0x2000000,0x2000400,0x2000020,0x2000420,0x2000000,0x2000400,0x2000020,0x2000420);
+  pc2bytes6  = new Array (0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002,0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002);
+  pc2bytes7  = new Array (0,0x10000,0x800,0x10800,0x20000000,0x20010000,0x20000800,0x20010800,0x20000,0x30000,0x20800,0x30800,0x20020000,0x20030000,0x20020800,0x20030800);
+  pc2bytes8  = new Array (0,0x40000,0,0x40000,0x2,0x40002,0x2,0x40002,0x2000000,0x2040000,0x2000000,0x2040000,0x2000002,0x2040002,0x2000002,0x2040002);
+  pc2bytes9  = new Array (0,0x10000000,0x8,0x10000008,0,0x10000000,0x8,0x10000008,0x400,0x10000400,0x408,0x10000408,0x400,0x10000400,0x408,0x10000408);
+  pc2bytes10 = new Array (0,0x20,0,0x20,0x100000,0x100020,0x100000,0x100020,0x2000,0x2020,0x2000,0x2020,0x102000,0x102020,0x102000,0x102020);
+  pc2bytes11 = new Array (0,0x1000000,0x200,0x1000200,0x200000,0x1200000,0x200200,0x1200200,0x4000000,0x5000000,0x4000200,0x5000200,0x4200000,0x5200000,0x4200200,0x5200200);
+  pc2bytes12 = new Array (0,0x1000,0x8000000,0x8001000,0x80000,0x81000,0x8080000,0x8081000,0x10,0x1010,0x8000010,0x8001010,0x80010,0x81010,0x8080010,0x8081010);
+  pc2bytes13 = new Array (0,0x4,0x100,0x104,0,0x4,0x100,0x104,0x1,0x5,0x101,0x105,0x1,0x5,0x101,0x105);
+
+  //how many iterations (1 for des, 3 for triple des)
+  var iterations = key.length > 8 ? 3 : 1; //changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys
+  //stores the return keys
+  var keys = new Array (32 * iterations);
+  //now define the left shifts which need to be done
+  var shifts = new Array (0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0);
+  //other variables
+  var lefttemp, righttemp, m=0, n=0, temp;
+
+  for (var j=0; j<iterations; j++) { //either 1 or 3 iterations
+    left = (key.charCodeAt(m++) << 24) | (key.charCodeAt(m++) << 16) | (key.charCodeAt(m++) << 8) | key.charCodeAt(m++);
+    right = (key.charCodeAt(m++) << 24) | (key.charCodeAt(m++) << 16) | (key.charCodeAt(m++) << 8) | key.charCodeAt(m++);
+
+    temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4);
+    temp = ((right >>> -16) ^ left) & 0x0000ffff; left ^= temp; right ^= (temp << -16);
+    temp = ((left >>> 2) ^ right) & 0x33333333; right ^= temp; left ^= (temp << 2);
+    temp = ((right >>> -16) ^ left) & 0x0000ffff; left ^= temp; right ^= (temp << -16);
+    temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
+    temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8);
+    temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
+
+    //the right side needs to be shifted and to get the last four bits of the left side
+    temp = (left << 8) | ((right >>> 20) & 0x000000f0);
+    //left needs to be put upside down
+    left = (right << 24) | ((right << 8) & 0xff0000) | ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0);
+    right = temp;
+
+    //now go through and perform these shifts on the left and right keys
+    for (i=0; i < shifts.length; i++) {
+      //shift the keys either one or two bits to the left
+      if (shifts[i]) {left = (left << 2) | (left >>> 26); right = (right << 2) | (right >>> 26);}
+      else {left = (left << 1) | (left >>> 27); right = (right << 1) | (right >>> 27);}
+      left &= -0xf; right &= -0xf;
+
+      //now apply PC-2, in such a way that E is easier when encrypting or decrypting
+      //this conversion will look like PC-2 except only the last 6 bits of each byte are used
+      //rather than 48 consecutive bits and the order of lines will be according to 
+      //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7
+      lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf]
+              | pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[(left >>> 16) & 0xf]
+              | pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf]
+              | pc2bytes6[(left >>> 4) & 0xf];
+      righttemp = pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf]
+                | pc2bytes9[(right >>> 20) & 0xf] | pc2bytes10[(right >>> 16) & 0xf]
+                | pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf]
+                | pc2bytes13[(right >>> 4) & 0xf];
+      temp = ((righttemp >>> 16) ^ lefttemp) & 0x0000ffff; 
+      keys[n++] = lefttemp ^ temp; keys[n++] = righttemp ^ (temp << 16);
+    }
+  } //for each iterations
+  //return the keys we've created
+  return keys;
+} //end of des_createKeys
+
+
+
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Copyright 2010 pjacobs@xeekr.com . All rights reserved.
+
+// Modified by Recurity Labs GmbH
+
+// fixed/modified by Herbert Hanewinkel, www.haneWIN.de
+// check www.haneWIN.de for the latest version
+
+// cast5.js is a Javascript implementation of CAST-128, as defined in RFC 2144.
+// CAST-128 is a common OpenPGP cipher.
+
+
+// CAST5 constructor
+
+function cast5_encrypt(block, key) {
+	var cast5 = new openpgp_symenc_cast5();
+	cast5.setKey(util.str2bin(key));
+	return cast5.encrypt(block);
+}
+
+function openpgp_symenc_cast5() {
+	this.BlockSize= 8;
+	this.KeySize = 16;
+
+	this.setKey = function (key) {
+		 this.masking = new Array(16);
+		 this.rotate = new Array(16);
+
+		 this.reset();
+
+		 if (key.length == this.KeySize)
+		 {
+		   this.keySchedule(key);
+		 }
+		 else
+		 {
+		   util.print_error('cast5.js: CAST-128: keys must be 16 bytes');
+		   return false;
+		 }
+		 return true;
+	};
+	
+	this.reset = function() {
+		 for (var i = 0; i < 16; i++)
+		 {
+		  this.masking[i] = 0;
+		  this.rotate[i] = 0;
+		 }
+	};
+
+	this.getBlockSize = function() {
+		 return BlockSize;
+	};
+
+	this.encrypt = function(src) {
+		 var dst = new Array(src.length);
+
+		 for(i = 0; i < src.length; i+=8)
+		 {
+		  var l = src[i]<<24 | src[i+1]<<16 | src[i+2]<<8 | src[i+3];
+		  var r = src[i+4]<<24 | src[i+5]<<16 | src[i+6]<<8 | src[i+7];
+		  var t;
+
+		  t = r; r = l^f1(r, this.masking[0], this.rotate[0]); l = t;
+		  t = r; r = l^f2(r, this.masking[1], this.rotate[1]); l = t;
+		  t = r; r = l^f3(r, this.masking[2], this.rotate[2]); l = t;
+		  t = r; r = l^f1(r, this.masking[3], this.rotate[3]); l = t;
+
+		  t = r; r = l^f2(r, this.masking[4], this.rotate[4]); l = t;
+		  t = r; r = l^f3(r, this.masking[5], this.rotate[5]); l = t;
+		  t = r; r = l^f1(r, this.masking[6], this.rotate[6]); l = t;
+		  t = r; r = l^f2(r, this.masking[7], this.rotate[7]); l = t;
+
+		  t = r; r = l^f3(r, this.masking[8], this.rotate[8]); l = t;
+		  t = r; r = l^f1(r, this.masking[9], this.rotate[9]); l = t;
+		  t = r; r = l^f2(r, this.masking[10], this.rotate[10]); l = t;
+		  t = r; r = l^f3(r, this.masking[11], this.rotate[11]); l = t;
+
+		  t = r; r = l^f1(r, this.masking[12], this.rotate[12]); l = t;
+		  t = r; r = l^f2(r, this.masking[13], this.rotate[13]); l = t;
+		  t = r; r = l^f3(r, this.masking[14], this.rotate[14]); l = t;
+		  t = r; r = l^f1(r, this.masking[15], this.rotate[15]); l = t;
+
+		  dst[i]   = (r >>> 24)&255;
+		  dst[i+1] = (r >>> 16)&255;
+		  dst[i+2] = (r >>> 8)&255;
+		  dst[i+3] = r&255;
+		  dst[i+4] = (l >>> 24)&255;
+		  dst[i+5] = (l >>> 16)&255;
+		  dst[i+6] = (l >>> 8)&255;
+		  dst[i+7] = l&255;
+		 }
+
+		 return dst;
+	};
+	
+	this.decrypt = function(src) {
+		 var dst = new Array(src.length);
+
+		 for(i = 0; i < src.length; i+=8)
+		 {
+		  var l = src[i]<<24 | src[i+1]<<16 | src[i+2]<<8 | src[i+3];
+		  var r = src[i+4]<<24 | src[i+5]<<16 | src[i+6]<<8 | src[i+7];
+		  var t;
+
+		  t = r; r = l^f1(r, this.masking[15], this.rotate[15]); l = t;
+		  t = r; r = l^f3(r, this.masking[14], this.rotate[14]); l = t;
+		  t = r; r = l^f2(r, this.masking[13], this.rotate[13]); l = t;
+		  t = r; r = l^f1(r, this.masking[12], this.rotate[12]); l = t;
+
+		  t = r; r = l^f3(r, this.masking[11], this.rotate[11]); l = t;
+		  t = r; r = l^f2(r, this.masking[10], this.rotate[10]); l = t;
+		  t = r; r = l^f1(r, this.masking[9], this.rotate[9]); l = t;
+		  t = r; r = l^f3(r, this.masking[8], this.rotate[8]); l = t;
+
+		  t = r; r = l^f2(r, this.masking[7], this.rotate[7]); l = t;
+		  t = r; r = l^f1(r, this.masking[6], this.rotate[6]); l = t;
+		  t = r; r = l^f3(r, this.masking[5], this.rotate[5]); l = t;
+		  t = r; r = l^f2(r, this.masking[4], this.rotate[4]); l = t;
+
+		  t = r; r = l^f1(r, this.masking[3], this.rotate[3]); l = t;
+		  t = r; r = l^f3(r, this.masking[2], this.rotate[2]); l = t;
+		  t = r; r = l^f2(r, this.masking[1], this.rotate[1]); l = t;
+		  t = r; r = l^f1(r, this.masking[0], this.rotate[0]); l = t;
+
+		  dst[i]   = (r >>> 24)&255;
+		  dst[i+1] = (r >>> 16)&255;
+		  dst[i+2] = (r >>> 8)&255;
+		  dst[i+3] = r&255;
+		  dst[i+4] = (l >>> 24)&255;
+		  dst[i+5] = (l >> 16)&255;
+		  dst[i+6] = (l >> 8)&255;
+		  dst[i+7] = l&255;
+		 }
+
+		 return dst;
+		};
+		var scheduleA = new Array(4);
+
+		scheduleA[0] = new Array(4);
+		scheduleA[0][0] = new Array(4, 0, 0xd, 0xf, 0xc, 0xe, 0x8);
+		scheduleA[0][1] = new Array(5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa);
+		scheduleA[0][2] = new Array(6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9);
+		scheduleA[0][3] = new Array(7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb);
+
+		scheduleA[1] = new Array(4);
+		scheduleA[1][0] = new Array(0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0);
+		scheduleA[1][1] = new Array(1, 4, 0, 2, 1, 3, 16 + 2);
+		scheduleA[1][2] = new Array(2, 5, 7, 6, 5, 4, 16 + 1);
+		scheduleA[1][3] = new Array(3, 7, 0xa, 9, 0xb, 8, 16 + 3);
+
+		scheduleA[2] = new Array(4);
+		scheduleA[2][0] = new Array(4, 0, 0xd, 0xf, 0xc, 0xe, 8);
+		scheduleA[2][1] = new Array(5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa);
+		scheduleA[2][2] = new Array(6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9);
+		scheduleA[2][3] = new Array(7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb);
+
+
+		scheduleA[3] = new Array(4);
+		scheduleA[3][0] = new Array(0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0);
+		scheduleA[3][1] = new Array(1, 4, 0, 2, 1, 3, 16 + 2);
+		scheduleA[3][2] = new Array(2, 5, 7, 6, 5, 4, 16 + 1);
+		scheduleA[3][3] = new Array(3, 7, 0xa, 9, 0xb, 8, 16 + 3);
+
+		var scheduleB = new Array(4);
+
+		scheduleB[0] = new Array(4);
+		scheduleB[0][0] = new Array(16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2);
+		scheduleB[0][1] = new Array(16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6);
+		scheduleB[0][2] = new Array(16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9);
+		scheduleB[0][3] = new Array(16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc);
+
+		scheduleB[1] = new Array(4);
+		scheduleB[1][0] = new Array(3, 2, 0xc, 0xd, 8);
+		scheduleB[1][1] = new Array(1, 0, 0xe, 0xf, 0xd);
+		scheduleB[1][2] = new Array(7, 6, 8, 9, 3);
+		scheduleB[1][3] = new Array(5, 4, 0xa, 0xb, 7);
+
+
+		scheduleB[2] = new Array(4);
+		scheduleB[2][0] = new Array(16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9);
+		scheduleB[2][1] = new Array(16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc);
+		scheduleB[2][2] = new Array(16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2);
+		scheduleB[2][3] = new Array(16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6);
+
+
+		scheduleB[3] = new Array(4);
+		scheduleB[3][0] = new Array(8, 9, 7, 6, 3);
+		scheduleB[3][1] = new Array(0xa, 0xb, 5, 4, 7);
+		scheduleB[3][2] = new Array(0xc, 0xd, 3, 2, 8);
+		scheduleB[3][3] = new Array(0xe, 0xf, 1, 0, 0xd);
+
+		// changed 'in' to 'inn' (in javascript 'in' is a reserved word)
+		this.keySchedule = function(inn)
+		{
+		 var t = new Array(8);
+		 var k = new Array(32);
+
+		 for (var i = 0; i < 4; i++)
+		 {
+		  var j = i * 4;
+		  t[i] = inn[j]<<24 | inn[j+1]<<16 | inn[j+2]<<8 | inn[j+3];
+		 }
+
+		 var x = [6, 7, 4, 5];
+		 var ki = 0;
+
+		 for (var half = 0; half < 2; half++)
+		 {
+		  for (var round = 0; round < 4; round++)
+		  {
+		   for (var j = 0; j < 4; j++)
+		   {
+		    var a = scheduleA[round][j];
+		    var w = t[a[1]];
+
+		    w ^= sBox[4][(t[a[2]>>>2]>>>(24-8*(a[2]&3)))&0xff];
+		    w ^= sBox[5][(t[a[3]>>>2]>>>(24-8*(a[3]&3)))&0xff];
+		    w ^= sBox[6][(t[a[4]>>>2]>>>(24-8*(a[4]&3)))&0xff];
+		    w ^= sBox[7][(t[a[5]>>>2]>>>(24-8*(a[5]&3)))&0xff];
+		    w ^= sBox[x[j]][(t[a[6]>>>2]>>>(24-8*(a[6]&3)))&0xff];
+		    t[a[0]] = w;
+		   }
+
+		   for (var j = 0; j < 4; j++)
+		   {
+		    var b = scheduleB[round][j];
+		    var w = sBox[4][(t[b[0]>>>2]>>>(24-8*(b[0]&3)))&0xff];
+
+		    w ^= sBox[5][(t[b[1]>>>2]>>>(24-8*(b[1]&3)))&0xff];
+		    w ^= sBox[6][(t[b[2]>>>2]>>>(24-8*(b[2]&3)))&0xff];
+		    w ^= sBox[7][(t[b[3]>>>2]>>>(24-8*(b[3]&3)))&0xff];
+		    w ^= sBox[4+j][(t[b[4]>>>2]>>>(24-8*(b[4]&3)))&0xff];
+		    k[ki] = w;
+		    ki++;
+		   }
+		  }
+		 }
+
+		 for (var i = 0; i < 16; i++)
+		 {
+		  this.masking[i] = k[i];
+		  this.rotate[i]  = k[16+i] & 0x1f;
+		 }
+		};
+
+		// These are the three 'f' functions. See RFC 2144, section 2.2.
+
+		function f1(d, m, r)
+		{
+		 var t = m + d;
+		 var I = (t << r) | (t >>> (32 - r));
+		 return ((sBox[0][I>>>24] ^ sBox[1][(I>>>16)&255]) - sBox[2][(I>>>8)&255]) + sBox[3][I&255];
+		}
+
+		function f2(d, m, r)
+		{
+		 var t = m ^ d;
+		 var I = (t << r) | (t >>> (32 - r));
+		 return ((sBox[0][I>>>24] - sBox[1][(I>>>16)&255]) + sBox[2][(I>>>8)&255]) ^ sBox[3][I&255];
+		}
+
+		function f3(d, m, r)
+		{
+		 var t = m - d;
+		 var I = (t << r) | (t >>> (32 - r));
+		 return ((sBox[0][I>>>24] + sBox[1][(I>>>16)&255]) ^ sBox[2][(I>>>8)&255]) - sBox[3][I&255];
+		}
+
+		var sBox = new Array(8);
+		sBox[0] = new Array(
+		  0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
+		  0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
+		  0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
+		  0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
+		  0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
+		  0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
+		  0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
+		  0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
+		  0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
+		  0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
+		  0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
+		  0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
+		  0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
+		  0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
+		  0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
+		  0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
+		  0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
+		  0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
+		  0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
+		  0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
+		  0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
+		  0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
+		  0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
+		  0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
+		  0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
+		  0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
+		  0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
+		  0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
+		  0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
+		  0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
+		  0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
+		  0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf);
+
+		sBox[1] = new Array(
+		  0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
+		  0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
+		  0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
+		  0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
+		  0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
+		  0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
+		  0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
+		  0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
+		  0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
+		  0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
+		  0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
+		  0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
+		  0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
+		  0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
+		  0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
+		  0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
+		  0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
+		  0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
+		  0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
+		  0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
+		  0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
+		  0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
+		  0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
+		  0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
+		  0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
+		  0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
+		  0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
+		  0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
+		  0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
+		  0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
+		  0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
+		  0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1);
+
+		sBox[2] = new Array(
+		  0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
+		  0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
+		  0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
+		  0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
+		  0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
+		  0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
+		  0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
+		  0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
+		  0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
+		  0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
+		  0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
+		  0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
+		  0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
+		  0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
+		  0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
+		  0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
+		  0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
+		  0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
+		  0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
+		  0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
+		  0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
+		  0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
+		  0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
+		  0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
+		  0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
+		  0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
+		  0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
+		  0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
+		  0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
+		  0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
+		  0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
+		  0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783);
+
+		sBox[3] = new Array(
+		  0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
+		  0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
+		  0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
+		  0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
+		  0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
+		  0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
+		  0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
+		  0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
+		  0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
+		  0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
+		  0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
+		  0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
+		  0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
+		  0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
+		  0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
+		  0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
+		  0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
+		  0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
+		  0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
+		  0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
+		  0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
+		  0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
+		  0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
+		  0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
+		  0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
+		  0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
+		  0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
+		  0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
+		  0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
+		  0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
+		  0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
+		  0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2);
+
+		sBox[4] = new Array(
+		  0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
+		  0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
+		  0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
+		  0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
+		  0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
+		  0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
+		  0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
+		  0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
+		  0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
+		  0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
+		  0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
+		  0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
+		  0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
+		  0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
+		  0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
+		  0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
+		  0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
+		  0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
+		  0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
+		  0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
+		  0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
+		  0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
+		  0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
+		  0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
+		  0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
+		  0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
+		  0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
+		  0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
+		  0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
+		  0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
+		  0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
+		  0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4);
+
+		sBox[5] = new Array(
+		  0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
+		  0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
+		  0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
+		  0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
+		  0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
+		  0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
+		  0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
+		  0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
+		  0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
+		  0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
+		  0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
+		  0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
+		  0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
+		  0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
+		  0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
+		  0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
+		  0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
+		  0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
+		  0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
+		  0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
+		  0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
+		  0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
+		  0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
+		  0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
+		  0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
+		  0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
+		  0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
+		  0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
+		  0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
+		  0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
+		  0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
+		  0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f);
+
+		sBox[6] = new Array(
+		  0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
+		  0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
+		  0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
+		  0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
+		  0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
+		  0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
+		  0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
+		  0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
+		  0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
+		  0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
+		  0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
+		  0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
+		  0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
+		  0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
+		  0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
+		  0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
+		  0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
+		  0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
+		  0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
+		  0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
+		  0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
+		  0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
+		  0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
+		  0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
+		  0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
+		  0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
+		  0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
+		  0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
+		  0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
+		  0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
+		  0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
+		  0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3);
+
+		sBox[7] = new Array(
+		  0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
+		  0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
+		  0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
+		  0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
+		  0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
+		  0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
+		  0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
+		  0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
+		  0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
+		  0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
+		  0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
+		  0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
+		  0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
+		  0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
+		  0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
+		  0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
+		  0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
+		  0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
+		  0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
+		  0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
+		  0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
+		  0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
+		  0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
+		  0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
+		  0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
+		  0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
+		  0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
+		  0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
+		  0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
+		  0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
+		  0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
+		  0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e);
+
+};
+
+/* Modified by Recurity Labs GmbH 
+ * 
+ * Cipher.js
+ * A block-cipher algorithm implementation on JavaScript
+ * See Cipher.readme.txt for further information.
+ *
+ * Copyright(c) 2009 Atsushi Oka [ http://oka.nu/ ]
+ * This script file is distributed under the LGPL
+ *
+ * ACKNOWLEDGMENT
+ *
+ *     The main subroutines are written by Michiel van Everdingen.
+ * 
+ *     Michiel van Everdingen
+ *     http://home.versatel.nl/MAvanEverdingen/index.html
+ * 
+ *     All rights for these routines are reserved to Michiel van Everdingen.
+ *
+ */
+
+// added by Recurity Labs
+function TFencrypt(block, key) {
+	var block_copy = [].concat(block);
+	var tf = createTwofish();
+	tf.open(util.str2bin(key),0);
+	var result = tf.encrypt(block_copy, 0);
+	tf.close();
+	return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//Math
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+var MAXINT = 0xFFFFFFFF;
+
+function rotb(b,n){ return ( b<<n | b>>>( 8-n) ) & 0xFF; }
+function rotw(w,n){ return ( w<<n | w>>>(32-n) ) & MAXINT; }
+function getW(a,i){ return a[i]|a[i+1]<<8|a[i+2]<<16|a[i+3]<<24; }
+function setW(a,i,w){ a.splice(i,4,w&0xFF,(w>>>8)&0xFF,(w>>>16)&0xFF,(w>>>24)&0xFF); }
+function setWInv(a,i,w){ a.splice(i,4,(w>>>24)&0xFF,(w>>>16)&0xFF,(w>>>8)&0xFF,w&0xFF); }
+function getB(x,n){ return (x>>>(n*8))&0xFF; }
+
+function getNrBits(i){ var n=0; while (i>0){ n++; i>>>=1; } return n; }
+function getMask(n){ return (1<<n)-1; }
+
+//added 2008/11/13 XXX MUST USE ONE-WAY HASH FUNCTION FOR SECURITY REASON
+function randByte() {
+ return Math.floor( Math.random() * 256 );
+}
+// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Twofish
+// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+function createTwofish() {
+	//
+	var keyBytes = null;
+	var dataBytes = null;
+	var dataOffset = -1;
+	// var dataLength = -1;
+	var algorithmName = null;
+	// var idx2 = -1;
+	//
+
+	algorithmName = "twofish";
+
+	var tfsKey = [];
+	var tfsM = [ [], [], [], [] ];
+
+	function tfsInit(key) {
+		keyBytes = key;
+		var i, a, b, c, d, meKey = [], moKey = [], inKey = [];
+		var kLen;
+		var sKey = [];
+		var f01, f5b, fef;
+
+		var q0 = [ [ 8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4 ],
+				[ 2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5 ] ];
+		var q1 = [ [ 14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13 ],
+				[ 1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8 ] ];
+		var q2 = [ [ 11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1 ],
+				[ 4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15 ] ];
+		var q3 = [ [ 13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10 ],
+				[ 11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10 ] ];
+		var ror4 = [ 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 ];
+		var ashx = [ 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7 ];
+		var q = [ [], [] ];
+		var m = [ [], [], [], [] ];
+
+		function ffm5b(x) {
+			return x ^ (x >> 2) ^ [ 0, 90, 180, 238 ][x & 3];
+		}
+		function ffmEf(x) {
+			return x ^ (x >> 1) ^ (x >> 2) ^ [ 0, 238, 180, 90 ][x & 3];
+		}
+
+		function mdsRem(p, q) {
+			var i, t, u;
+			for (i = 0; i < 8; i++) {
+				t = q >>> 24;
+				q = ((q << 8) & MAXINT) | p >>> 24;
+				p = (p << 8) & MAXINT;
+				u = t << 1;
+				if (t & 128) {
+					u ^= 333;
+				}
+				q ^= t ^ (u << 16);
+				u ^= t >>> 1;
+				if (t & 1) {
+					u ^= 166;
+				}
+				q ^= u << 24 | u << 8;
+			}
+			return q;
+		}
+
+		function qp(n, x) {
+			var a, b, c, d;
+			a = x >> 4;
+			b = x & 15;
+			c = q0[n][a ^ b];
+			d = q1[n][ror4[b] ^ ashx[a]];
+			return q3[n][ror4[d] ^ ashx[c]] << 4 | q2[n][c ^ d];
+		}
+
+		function hFun(x, key) {
+			var a = getB(x, 0), b = getB(x, 1), c = getB(x, 2), d = getB(x, 3);
+			switch (kLen) {
+			case 4:
+				a = q[1][a] ^ getB(key[3], 0);
+				b = q[0][b] ^ getB(key[3], 1);
+				c = q[0][c] ^ getB(key[3], 2);
+				d = q[1][d] ^ getB(key[3], 3);
+			case 3:
+				a = q[1][a] ^ getB(key[2], 0);
+				b = q[1][b] ^ getB(key[2], 1);
+				c = q[0][c] ^ getB(key[2], 2);
+				d = q[0][d] ^ getB(key[2], 3);
+			case 2:
+				a = q[0][q[0][a] ^ getB(key[1], 0)] ^ getB(key[0], 0);
+				b = q[0][q[1][b] ^ getB(key[1], 1)] ^ getB(key[0], 1);
+				c = q[1][q[0][c] ^ getB(key[1], 2)] ^ getB(key[0], 2);
+				d = q[1][q[1][d] ^ getB(key[1], 3)] ^ getB(key[0], 3);
+			}
+			return m[0][a] ^ m[1][b] ^ m[2][c] ^ m[3][d];
+		}
+
+		keyBytes = keyBytes.slice(0, 32);
+		i = keyBytes.length;
+		while (i != 16 && i != 24 && i != 32)
+			keyBytes[i++] = 0;
+
+		for (i = 0; i < keyBytes.length; i += 4) {
+			inKey[i >> 2] = getW(keyBytes, i);
+		}
+		for (i = 0; i < 256; i++) {
+			q[0][i] = qp(0, i);
+			q[1][i] = qp(1, i);
+		}
+		for (i = 0; i < 256; i++) {
+			f01 = q[1][i];
+			f5b = ffm5b(f01);
+			fef = ffmEf(f01);
+			m[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24);
+			m[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24);
+			f01 = q[0][i];
+			f5b = ffm5b(f01);
+			fef = ffmEf(f01);
+			m[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24);
+			m[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24);
+		}
+
+		kLen = inKey.length / 2;
+		for (i = 0; i < kLen; i++) {
+			a = inKey[i + i];
+			meKey[i] = a;
+			b = inKey[i + i + 1];
+			moKey[i] = b;
+			sKey[kLen - i - 1] = mdsRem(a, b);
+		}
+		for (i = 0; i < 40; i += 2) {
+			a = 0x1010101 * i;
+			b = a + 0x1010101;
+			a = hFun(a, meKey);
+			b = rotw(hFun(b, moKey), 8);
+			tfsKey[i] = (a + b) & MAXINT;
+			tfsKey[i + 1] = rotw(a + 2 * b, 9);
+		}
+		for (i = 0; i < 256; i++) {
+			a = b = c = d = i;
+			switch (kLen) {
+			case 4:
+				a = q[1][a] ^ getB(sKey[3], 0);
+				b = q[0][b] ^ getB(sKey[3], 1);
+				c = q[0][c] ^ getB(sKey[3], 2);
+				d = q[1][d] ^ getB(sKey[3], 3);
+			case 3:
+				a = q[1][a] ^ getB(sKey[2], 0);
+				b = q[1][b] ^ getB(sKey[2], 1);
+				c = q[0][c] ^ getB(sKey[2], 2);
+				d = q[0][d] ^ getB(sKey[2], 3);
+			case 2:
+				tfsM[0][i] = m[0][q[0][q[0][a] ^ getB(sKey[1], 0)]
+						^ getB(sKey[0], 0)];
+				tfsM[1][i] = m[1][q[0][q[1][b] ^ getB(sKey[1], 1)]
+						^ getB(sKey[0], 1)];
+				tfsM[2][i] = m[2][q[1][q[0][c] ^ getB(sKey[1], 2)]
+						^ getB(sKey[0], 2)];
+				tfsM[3][i] = m[3][q[1][q[1][d] ^ getB(sKey[1], 3)]
+						^ getB(sKey[0], 3)];
+			}
+		}
+	}
+
+	function tfsG0(x) {
+		return tfsM[0][getB(x, 0)] ^ tfsM[1][getB(x, 1)] ^ tfsM[2][getB(x, 2)]
+				^ tfsM[3][getB(x, 3)];
+	}
+	function tfsG1(x) {
+		return tfsM[0][getB(x, 3)] ^ tfsM[1][getB(x, 0)] ^ tfsM[2][getB(x, 1)]
+				^ tfsM[3][getB(x, 2)];
+	}
+
+	function tfsFrnd(r, blk) {
+		var a = tfsG0(blk[0]);
+		var b = tfsG1(blk[1]);
+		blk[2] = rotw(blk[2] ^ (a + b + tfsKey[4 * r + 8]) & MAXINT, 31);
+		blk[3] = rotw(blk[3], 1) ^ (a + 2 * b + tfsKey[4 * r + 9]) & MAXINT;
+		a = tfsG0(blk[2]);
+		b = tfsG1(blk[3]);
+		blk[0] = rotw(blk[0] ^ (a + b + tfsKey[4 * r + 10]) & MAXINT, 31);
+		blk[1] = rotw(blk[1], 1) ^ (a + 2 * b + tfsKey[4 * r + 11]) & MAXINT;
+	}
+
+	function tfsIrnd(i, blk) {
+		var a = tfsG0(blk[0]);
+		var b = tfsG1(blk[1]);
+		blk[2] = rotw(blk[2], 1) ^ (a + b + tfsKey[4 * i + 10]) & MAXINT;
+		blk[3] = rotw(blk[3] ^ (a + 2 * b + tfsKey[4 * i + 11]) & MAXINT, 31);
+		a = tfsG0(blk[2]);
+		b = tfsG1(blk[3]);
+		blk[0] = rotw(blk[0], 1) ^ (a + b + tfsKey[4 * i + 8]) & MAXINT;
+		blk[1] = rotw(blk[1] ^ (a + 2 * b + tfsKey[4 * i + 9]) & MAXINT, 31);
+	}
+
+	function tfsClose() {
+		tfsKey = [];
+		tfsM = [ [], [], [], [] ];
+	}
+
+	function tfsEncrypt(data, offset) {
+		dataBytes = data;
+		dataOffset = offset;
+		var blk = [ getW(dataBytes, dataOffset) ^ tfsKey[0],
+				getW(dataBytes, dataOffset + 4) ^ tfsKey[1],
+				getW(dataBytes, dataOffset + 8) ^ tfsKey[2],
+				getW(dataBytes, dataOffset + 12) ^ tfsKey[3] ];
+		for ( var j = 0; j < 8; j++) {
+			tfsFrnd(j, blk);
+		}
+		setW(dataBytes, dataOffset, blk[2] ^ tfsKey[4]);
+		setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[5]);
+		setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[6]);
+		setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[7]);
+		dataOffset += 16;
+		return dataBytes;
+	}
+
+	function tfsDecrypt(data, offset) {
+		dataBytes = data;
+		dataOffset = offset;
+		var blk = [ getW(dataBytes, dataOffset) ^ tfsKey[4],
+				getW(dataBytes, dataOffset + 4) ^ tfsKey[5],
+				getW(dataBytes, dataOffset + 8) ^ tfsKey[6],
+				getW(dataBytes, dataOffset + 12) ^ tfsKey[7] ];
+		for ( var j = 7; j >= 0; j--) {
+			tfsIrnd(j, blk);
+		}
+		setW(dataBytes, dataOffset, blk[2] ^ tfsKey[0]);
+		setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[1]);
+		setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[2]);
+		setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[3]);
+		dataOffset += 16;
+	}
+	
+	// added by Recurity Labs
+	function tfsFinal() {
+		return dataBytes;
+	}
+
+	return {
+		name : "twofish",
+		blocksize : 128 / 8,
+		open : tfsInit,
+		close : tfsClose,
+		encrypt : tfsEncrypt,
+		decrypt : tfsDecrypt,
+		// added by Recurity Labs
+		finalize: tfsFinal
+	};
+}
+
+/* Modified by Recurity Labs GmbH 
+ * 
+ * Originally written by nklein software (nklein.com)
+ */
+
+/* 
+ * Javascript implementation based on Bruce Schneier's reference implementation.
+ *
+ *
+ * The constructor doesn't do much of anything.  It's just here
+ * so we can start defining properties and methods and such.
+ */
+function Blowfish() {
+};
+
+/*
+ * Declare the block size so that protocols know what size
+ * Initialization Vector (IV) they will need.
+ */
+Blowfish.prototype.BLOCKSIZE = 8;
+
+/*
+ * These are the default SBOXES.
+ */
+Blowfish.prototype.SBOXES = [
+    [
+	0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
+	0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+	0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
+	0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+	0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
+	0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+	0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
+	0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+	0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
+	0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+	0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
+	0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+	0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
+	0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+	0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
+	0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+	0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
+	0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+	0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
+	0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+	0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
+	0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+	0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
+	0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+	0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
+	0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+	0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
+	0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+	0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
+	0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+	0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
+	0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+	0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
+	0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+	0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
+	0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+	0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
+	0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+	0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
+	0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+	0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
+	0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+	0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
+    ], [
+	0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
+	0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+	0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
+	0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+	0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
+	0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+	0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
+	0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+	0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
+	0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+	0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
+	0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+	0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
+	0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+	0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
+	0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+	0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
+	0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+	0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
+	0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+	0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
+	0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+	0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
+	0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+	0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
+	0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+	0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
+	0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+	0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
+	0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+	0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
+	0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+	0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
+	0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+	0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
+	0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+	0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
+	0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+	0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
+	0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+	0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
+	0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+	0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
+    ], [
+	0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
+	0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+	0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
+	0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+	0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
+	0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+	0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
+	0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+	0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
+	0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+	0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
+	0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+	0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
+	0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+	0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
+	0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+	0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
+	0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+	0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
+	0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+	0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
+	0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+	0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
+	0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+	0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
+	0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+	0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
+	0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+	0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
+	0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+	0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
+	0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+	0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
+	0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+	0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
+	0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+	0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
+	0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+	0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
+	0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+	0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
+	0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+	0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
+    ], [
+	0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
+	0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+	0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
+	0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+	0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
+	0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+	0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
+	0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+	0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
+	0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+	0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
+	0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+	0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
+	0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+	0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
+	0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+	0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
+	0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+	0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
+	0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+	0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
+	0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+	0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
+	0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+	0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
+	0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+	0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
+	0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+	0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
+	0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+	0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
+	0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+	0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
+	0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+	0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
+	0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+	0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
+	0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+	0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
+	0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+	0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
+	0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+	0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
+    ]
+];
+
+//*
+//* This is the default PARRAY
+//*
+Blowfish.prototype.PARRAY = [
+    0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
+    0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+    0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b
+];
+
+//*
+//* This is the number of rounds the cipher will go
+//*
+Blowfish.prototype.NN = 16;
+
+//*
+//* This function is needed to get rid of problems
+//* with the high-bit getting set.  If we don't do
+//* this, then sometimes ( aa & 0x00FFFFFFFF ) is not
+//* equal to ( bb & 0x00FFFFFFFF ) even when they
+//* agree bit-for-bit for the first 32 bits.
+//*
+Blowfish.prototype._clean = function( xx ) {
+    if ( xx < 0 ) {
+	var yy = xx & 0x7FFFFFFF;
+	xx = yy + 0x80000000;
+    }
+    return xx;
+};
+
+//*
+//* This is the mixing function that uses the sboxes
+//*
+Blowfish.prototype._F = function ( xx ) {
+    var aa;
+    var bb;
+    var cc;
+    var dd;
+    var yy;
+
+    dd = xx & 0x00FF;
+    xx >>>= 8;
+    cc = xx & 0x00FF;
+    xx >>>= 8;
+    bb = xx & 0x00FF;
+    xx >>>= 8;
+    aa = xx & 0x00FF;
+
+    yy = this.sboxes[ 0 ][ aa ] + this.sboxes[ 1 ][ bb ];
+    yy = yy ^ this.sboxes[ 2 ][ cc ];
+    yy = yy + this.sboxes[ 3 ][ dd ];
+
+    return yy;
+};
+
+//*
+//* This method takes an array with two values, left and right
+//* and does NN rounds of Blowfish on them.
+//*
+Blowfish.prototype._encrypt_block = function ( vals ) {
+    var dataL = vals[ 0 ];
+    var dataR = vals[ 1 ];
+
+    var ii;
+
+    for ( ii=0; ii < this.NN; ++ii ) {
+	dataL = dataL ^ this.parray[ ii ];
+	dataR = this._F( dataL ) ^ dataR;
+
+	var tmp = dataL;
+	dataL = dataR;
+	dataR = tmp;
+    }
+
+    dataL = dataL ^ this.parray[ this.NN + 0 ];
+    dataR = dataR ^ this.parray[ this.NN + 1 ];
+
+    vals[ 0 ] = this._clean( dataR );
+    vals[ 1 ] = this._clean( dataL );
+};
+
+//*
+//* This method takes a vector of numbers and turns them
+//* into long words so that they can be processed by the
+//* real algorithm.
+//*
+//* Maybe I should make the real algorithm above take a vector
+//* instead.  That will involve more looping, but it won't require
+//* the F() method to deconstruct the vector.
+//*
+Blowfish.prototype.encrypt_block = function ( vector ) {
+    var ii;
+    var vals = [ 0, 0 ];
+    var off  = this.BLOCKSIZE/2;
+    for ( ii = 0; ii < this.BLOCKSIZE/2; ++ii ) {
+	vals[0] = ( vals[0] << 8 ) | ( vector[ ii + 0   ] & 0x00FF );
+	vals[1] = ( vals[1] << 8 ) | ( vector[ ii + off ] & 0x00FF );
+    }
+
+    this._encrypt_block( vals );
+
+    var ret = [ ];
+    for ( ii = 0; ii < this.BLOCKSIZE/2; ++ii ) {
+	ret[ ii + 0   ] = ( vals[ 0 ] >>> (24 - 8*(ii)) & 0x00FF );
+	ret[ ii + off ] = ( vals[ 1 ] >>> (24 - 8*(ii)) & 0x00FF );
+	// vals[ 0 ] = ( vals[ 0 ] >>> 8 );
+	// vals[ 1 ] = ( vals[ 1 ] >>> 8 );
+    }
+
+    return ret;
+};
+
+//*
+//* This method takes an array with two values, left and right
+//* and undoes NN rounds of Blowfish on them.
+//*
+Blowfish.prototype._decrypt_block = function ( vals ) {
+    var dataL = vals[ 0 ];
+    var dataR = vals[ 1 ];
+
+    var ii;
+
+    for ( ii=this.NN+1; ii > 1; --ii ) {
+	dataL = dataL ^ this.parray[ ii ];
+	dataR = this._F( dataL ) ^ dataR;
+
+	var tmp = dataL;
+	dataL = dataR;
+	dataR = tmp;
+    }
+
+    dataL = dataL ^ this.parray[ 1 ];
+    dataR = dataR ^ this.parray[ 0 ];
+
+    vals[ 0 ] = this._clean( dataR );
+    vals[ 1 ] = this._clean( dataL );
+};
+
+//*
+//* This method takes a key array and initializes the
+//* sboxes and parray for this encryption.
+//*
+Blowfish.prototype.init = function ( key ) {
+    var ii;
+    var jj = 0;
+
+    this.parray = [];
+    for ( ii=0; ii < this.NN + 2; ++ii ) {
+	var data = 0x00000000;
+	var kk;
+	for ( kk=0; kk < 4; ++kk ) {
+	    data = ( data << 8 ) | ( key[ jj ] & 0x00FF );
+	    if ( ++jj >= key.length ) {
+		jj = 0;
+	    }
+	}
+	this.parray[ ii ] = this.PARRAY[ ii ] ^ data;
+    }
+
+    this.sboxes = [];
+    for ( ii=0; ii < 4; ++ii ) {
+	this.sboxes[ ii ] = [];
+	for ( jj=0; jj < 256; ++jj ) {
+	    this.sboxes[ ii ][ jj ] = this.SBOXES[ ii ][ jj ];
+	}
+    }
+
+    var vals = [ 0x00000000, 0x00000000 ];
+
+    for ( ii=0; ii < this.NN+2; ii += 2 ) {
+	this._encrypt_block( vals );
+	this.parray[ ii + 0 ] = vals[ 0 ];
+	this.parray[ ii + 1 ] = vals[ 1 ];
+    }
+
+    for ( ii=0; ii < 4; ++ii ) {
+	for ( jj=0; jj < 256; jj += 2 ) {
+	    this._encrypt_block( vals );
+	    this.sboxes[ ii ][ jj + 0 ] = vals[ 0 ];
+	    this.sboxes[ ii ][ jj + 1 ] = vals[ 1 ];
+	}
+    }
+};
+
+// added by Recurity Labs
+function BFencrypt(block,key) {
+	var bf = new Blowfish();
+	bf.init(util.str2bin(key));
+	return bf.encrypt_block(block);
+}
+
+/* Rijndael (AES) Encryption
+ * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de
+ * version 1.1, check www.haneWIN.de for the latest version
+
+ * This software is provided as-is, without express or implied warranty.  
+ * Permission to use, copy, modify, distribute or sell this software, with or
+ * without fee, for any purpose and by any individual or organization, is hereby
+ * granted, provided that the above copyright notice and this paragraph appear 
+ * in all copies. Distribution as a part of an application or binary must
+ * include the above copyright notice in the documentation and/or other
+ * materials provided with the application or distribution.
+ */
+
+// The round constants used in subkey expansion
+var Rcon = [ 
+0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 
+0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 
+0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 ];
+
+// Precomputed lookup table for the SBox
+var S = [
+ 99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254, 215, 171, 
+118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212, 162, 175, 156, 164, 
+114, 192, 183, 253, 147,  38,  54,  63, 247, 204,  52, 165, 229, 241, 113, 
+216,  49,  21,   4, 199,  35, 195,  24, 150,   5, 154,   7,  18, 128, 226, 
+235,  39, 178, 117,   9, 131,  44,  26,  27, 110,  90, 160,  82,  59, 214, 
+179,  41, 227,  47, 132,  83, 209,   0, 237,  32, 252, 177,  91, 106, 203, 
+190,  57,  74,  76,  88, 207, 208, 239, 170, 251,  67,  77,  51, 133,  69, 
+249,   2, 127,  80,  60, 159, 168,  81, 163,  64, 143, 146, 157,  56, 245, 
+188, 182, 218,  33,  16, 255, 243, 210, 205,  12,  19, 236,  95, 151,  68,  
+23,  196, 167, 126,  61, 100,  93,  25, 115,  96, 129,  79, 220,  34,  42, 
+144, 136,  70, 238, 184,  20, 222,  94,  11, 219, 224,  50,  58,  10,  73,
+  6,  36,  92, 194, 211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 
+141, 213,  78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,  
+ 46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138, 112,  62, 
+181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134, 193,  29, 158, 225,
+248, 152,  17, 105, 217, 142, 148, 155,  30, 135, 233, 206,  85,  40, 223,
+140, 161, 137,  13, 191, 230,  66, 104,  65, 153,  45,  15, 176,  84, 187,  
+ 22 ];
+
+var T1 = [
+0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6,
+0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591,
+0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56,
+0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec,
+0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
+0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb,
+0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45,
+0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b,
+0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c,
+0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
+0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9,
+0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a,
+0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d,
+0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f,
+0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
+0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea,
+0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34,
+0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b,
+0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d,
+0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
+0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1,
+0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6,
+0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972,
+0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85,
+0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
+0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511,
+0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe,
+0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b,
+0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05,
+0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
+0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142,
+0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf,
+0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3,
+0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e,
+0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
+0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6,
+0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3,
+0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b,
+0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428,
+0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
+0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14,
+0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8,
+0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4,
+0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2,
+0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
+0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949,
+0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf,
+0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810,
+0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c,
+0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
+0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e,
+0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f,
+0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc,
+0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c,
+0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
+0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27,
+0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122,
+0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433,
+0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9,
+0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
+0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a,
+0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0,
+0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e,
+0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c ];
+
+var T2 = [
+0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d,
+0xf2f2ff0d, 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154,
+0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d,
+0xfefee719, 0xd7d7b562, 0xabab4de6, 0x7676ec9a,
+0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87,
+0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b,
+0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea,
+0x9c9c23bf, 0xa4a453f7, 0x7272e496, 0xc0c09b5b,
+0xb7b775c2, 0xfdfde11c, 0x93933dae, 0x26264c6a,
+0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f,
+0x3434685c, 0xa5a551f4, 0xe5e5d134, 0xf1f1f908,
+0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f,
+0x0404080c, 0xc7c79552, 0x23234665, 0xc3c39d5e,
+0x18183028, 0x969637a1, 0x05050a0f, 0x9a9a2fb5,
+0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d,
+0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f,
+0x0909121b, 0x83831d9e, 0x2c2c5874, 0x1a1a342e,
+0x1b1b362d, 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb,
+0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce,
+0x2929527b, 0xe3e3dd3e, 0x2f2f5e71, 0x84841397,
+0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c,
+0x20204060, 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed,
+0x6a6ad4be, 0xcbcb8d46, 0xbebe67d9, 0x3939724b,
+0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a,
+0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16,
+0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194,
+0x45458acf, 0xf9f9e910, 0x02020406, 0x7f7ffe81,
+0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3,
+0x5151a2f3, 0xa3a35dfe, 0x404080c0, 0x8f8f058a,
+0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104,
+0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263,
+0x10102030, 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d,
+0xcdcd814c, 0x0c0c1814, 0x13132635, 0xececc32f,
+0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39,
+0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47,
+0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695,
+0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f,
+0x22224466, 0x2a2a547e, 0x90903bab, 0x88880b83,
+0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c,
+0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76,
+0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e,
+0x494992db, 0x06060c0a, 0x2424486c, 0x5c5cb8e4,
+0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6,
+0x919139a8, 0x959531a4, 0xe4e4d337, 0x7979f28b,
+0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7,
+0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0,
+0x6c6cd8b4, 0x5656acfa, 0xf4f4f307, 0xeaeacf25,
+0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x08081018,
+0xbaba6fd5, 0x7878f088, 0x25254a6f, 0x2e2e5c72,
+0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751,
+0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21,
+0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85,
+0x7070e090, 0x3e3e7c42, 0xb5b571c4, 0x6666ccaa,
+0x484890d8, 0x03030605, 0xf6f6f701, 0x0e0e1c12,
+0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0,
+0x86861791, 0xc1c19958, 0x1d1d3a27, 0x9e9e27b9,
+0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233,
+0x6969d2bb, 0xd9d9a970, 0x8e8e0789, 0x949433a7,
+0x9b9b2db6, 0x1e1e3c22, 0x87871592, 0xe9e9c920,
+0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a,
+0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17,
+0xbfbf65da, 0xe6e6d731, 0x424284c6, 0x6868d0b8,
+0x414182c3, 0x999929b0, 0x2d2d5a77, 0x0f0f1e11,
+0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a ];
+
+var T3 = [
+0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b,
+0xf2ff0df2, 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5,
+0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b,
+0xfee719fe, 0xd7b562d7, 0xab4de6ab, 0x76ec9a76,
+0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d,
+0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0,
+0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf,
+0x9c23bf9c, 0xa453f7a4, 0x72e49672, 0xc09b5bc0,
+0xb775c2b7, 0xfde11cfd, 0x933dae93, 0x264c6a26,
+0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc,
+0x34685c34, 0xa551f4a5, 0xe5d134e5, 0xf1f908f1,
+0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15,
+0x04080c04, 0xc79552c7, 0x23466523, 0xc39d5ec3,
+0x18302818, 0x9637a196, 0x050a0f05, 0x9a2fb59a,
+0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2,
+0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75,
+0x09121b09, 0x831d9e83, 0x2c58742c, 0x1a342e1a,
+0x1b362d1b, 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0,
+0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3,
+0x29527b29, 0xe3dd3ee3, 0x2f5e712f, 0x84139784,
+0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced,
+0x20406020, 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b,
+0x6ad4be6a, 0xcb8d46cb, 0xbe67d9be, 0x39724b39,
+0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf,
+0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb,
+0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485,
+0x458acf45, 0xf9e910f9, 0x02040602, 0x7ffe817f,
+0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8,
+0x51a2f351, 0xa35dfea3, 0x4080c040, 0x8f058a8f,
+0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5,
+0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321,
+0x10203010, 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2,
+0xcd814ccd, 0x0c18140c, 0x13263513, 0xecc32fec,
+0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917,
+0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d,
+0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573,
+0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc,
+0x22446622, 0x2a547e2a, 0x903bab90, 0x880b8388,
+0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14,
+0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db,
+0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a,
+0x4992db49, 0x060c0a06, 0x24486c24, 0x5cb8e45c,
+0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662,
+0x9139a891, 0x9531a495, 0xe4d337e4, 0x79f28b79,
+0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d,
+0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9,
+0x6cd8b46c, 0x56acfa56, 0xf4f307f4, 0xeacf25ea,
+0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x08101808,
+0xba6fd5ba, 0x78f08878, 0x254a6f25, 0x2e5c722e,
+0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6,
+0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f,
+0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a,
+0x70e09070, 0x3e7c423e, 0xb571c4b5, 0x66ccaa66,
+0x4890d848, 0x03060503, 0xf6f701f6, 0x0e1c120e,
+0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9,
+0x86179186, 0xc19958c1, 0x1d3a271d, 0x9e27b99e,
+0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311,
+0x69d2bb69, 0xd9a970d9, 0x8e07898e, 0x9433a794,
+0x9b2db69b, 0x1e3c221e, 0x87159287, 0xe9c920e9,
+0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf,
+0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d,
+0xbf65dabf, 0xe6d731e6, 0x4284c642, 0x68d0b868,
+0x4182c341, 0x9929b099, 0x2d5a772d, 0x0f1e110f,
+0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16 ];
+
+var T4 = [
+0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b,
+0xff0df2f2, 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5,
+0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b,
+0xe719fefe, 0xb562d7d7, 0x4de6abab, 0xec9a7676,
+0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d,
+0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0,
+0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf,
+0x23bf9c9c, 0x53f7a4a4, 0xe4967272, 0x9b5bc0c0,
+0x75c2b7b7, 0xe11cfdfd, 0x3dae9393, 0x4c6a2626,
+0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc,
+0x685c3434, 0x51f4a5a5, 0xd134e5e5, 0xf908f1f1,
+0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515,
+0x080c0404, 0x9552c7c7, 0x46652323, 0x9d5ec3c3,
+0x30281818, 0x37a19696, 0x0a0f0505, 0x2fb59a9a,
+0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2,
+0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575,
+0x121b0909, 0x1d9e8383, 0x58742c2c, 0x342e1a1a,
+0x362d1b1b, 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0,
+0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3,
+0x527b2929, 0xdd3ee3e3, 0x5e712f2f, 0x13978484,
+0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded,
+0x40602020, 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b,
+0xd4be6a6a, 0x8d46cbcb, 0x67d9bebe, 0x724b3939,
+0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf,
+0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb,
+0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585,
+0x8acf4545, 0xe910f9f9, 0x04060202, 0xfe817f7f,
+0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8,
+0xa2f35151, 0x5dfea3a3, 0x80c04040, 0x058a8f8f,
+0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5,
+0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121,
+0x20301010, 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2,
+0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec,
+0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717,
+0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d,
+0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373,
+0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc,
+0x44662222, 0x547e2a2a, 0x3bab9090, 0x0b838888,
+0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414,
+0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb,
+0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a,
+0x92db4949, 0x0c0a0606, 0x486c2424, 0xb8e45c5c,
+0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262,
+0x39a89191, 0x31a49595, 0xd337e4e4, 0xf28b7979,
+0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d,
+0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9,
+0xd8b46c6c, 0xacfa5656, 0xf307f4f4, 0xcf25eaea,
+0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808,
+0x6fd5baba, 0xf0887878, 0x4a6f2525, 0x5c722e2e,
+0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6,
+0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f,
+0x96dd4b4b, 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a,
+0xe0907070, 0x7c423e3e, 0x71c4b5b5, 0xccaa6666,
+0x90d84848, 0x06050303, 0xf701f6f6, 0x1c120e0e,
+0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9,
+0x17918686, 0x9958c1c1, 0x3a271d1d, 0x27b99e9e,
+0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111,
+0xd2bb6969, 0xa970d9d9, 0x07898e8e, 0x33a79494,
+0x2db69b9b, 0x3c221e1e, 0x15928787, 0xc920e9e9,
+0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf,
+0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d,
+0x65dabfbf, 0xd731e6e6, 0x84c64242, 0xd0b86868,
+0x82c34141, 0x29b09999, 0x5a772d2d, 0x1e110f0f,
+0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616 ];
+
+function B0(x) { return (x&255); }
+function B1(x) { return ((x>>8)&255); }
+function B2(x) { return ((x>>16)&255); }
+function B3(x) { return ((x>>24)&255); }
+
+function F1(x0, x1, x2, x3)
+{
+  return B1(T1[x0&255]) | (B1(T1[(x1>>8)&255])<<8)
+      | (B1(T1[(x2>>16)&255])<<16) | (B1(T1[x3>>>24])<<24);
+}
+
+function packBytes(octets)
+{
+  var i, j;
+  var len=octets.length;
+  var b=new Array(len/4);
+
+  if (!octets || len % 4) return;
+
+  for (i=0, j=0; j<len; j+= 4)
+     b[i++] = octets[j] | (octets[j+1]<<8) | (octets[j+2]<<16) | (octets[j+3]<<24);
+
+  return b;  
+}
+
+function unpackBytes(packed)
+{
+  var j;
+  var i=0, l = packed.length;
+  var r = new Array(l*4);
+
+  for (j=0; j<l; j++)
+  {
+    r[i++] = B0(packed[j]);
+    r[i++] = B1(packed[j]);
+    r[i++] = B2(packed[j]);
+    r[i++] = B3(packed[j]);
+  }
+  return r;
+}
+
+// ------------------------------------------------
+
+var maxkc=8;
+var maxrk=14;
+
+function keyExpansion(key)
+{
+  var kc, i, j, r, t;
+  var rounds;
+  var keySched=new Array(maxrk+1);
+  var keylen=key.length;
+  var k=new Array(maxkc);
+  var tk=new Array(maxkc);
+  var rconpointer=0;
+
+  if(keylen==16)
+  {
+   rounds=10;
+   kc=4;
+  }
+  else if(keylen==24)
+  {
+   rounds=12;
+   kc=6;
+  }
+  else if(keylen==32)
+  {
+   rounds=14;
+   kc=8;
+  }
+  else
+  {
+	util.print_error('aes.js: Invalid key-length for AES key:'+keylen);
+   return;
+  }
+
+  for(i=0; i<maxrk+1; i++) keySched[i]=new Array(4);
+
+  for(i=0,j=0; j<keylen; j++,i+=4)
+    k[j] = key.charCodeAt(i) | (key.charCodeAt(i+1)<<8)
+                     | (key.charCodeAt(i+2)<<16) | (key.charCodeAt(i+3)<<24);
+
+  for(j=kc-1; j>=0; j--) tk[j] = k[j];
+
+  r=0;
+  t=0;
+  for(j=0; (j<kc)&&(r<rounds+1); )
+  {
+    for(; (j<kc)&&(t<4); j++,t++)
+    {
+      keySched[r][t]=tk[j];
+    }
+    if(t==4)
+    {
+      r++;
+      t=0;
+    }
+  }
+
+  while(r<rounds+1)
+  {
+    var temp = tk[kc-1];
+
+    tk[0] ^= S[B1(temp)] | (S[B2(temp)]<<8) | (S[B3(temp)]<<16) | (S[B0(temp)]<<24);
+    tk[0] ^= Rcon[rconpointer++];
+
+    if(kc != 8)
+    {
+      for(j=1; j<kc; j++) tk[j] ^= tk[j-1];
+    }
+    else
+    {
+      for(j=1; j<kc/2; j++) tk[j] ^= tk[j-1];
+ 
+      temp = tk[kc/2-1];
+      tk[kc/2] ^= S[B0(temp)] | (S[B1(temp)]<<8) | (S[B2(temp)]<<16) | (S[B3(temp)]<<24);
+
+      for(j=kc/2+1; j<kc; j++) tk[j] ^= tk[j-1];
+    }
+
+    for(j=0; (j<kc)&&(r<rounds+1); )
+    {
+      for(; (j<kc)&&(t<4); j++,t++)
+      {
+        keySched[r][t]=tk[j];
+      }
+      if(t==4)
+      {
+        r++;
+        t=0;
+      }
+    }
+  }
+  this.rounds = rounds;
+  this.rk = keySched;
+  return this;
+}
+
+function AESencrypt(block, ctx)
+{
+  var r;
+  var t0,t1,t2,t3;
+
+  var b = packBytes(block);
+  var rounds = ctx.rounds;
+  var b0 = b[0];
+  var b1 = b[1];
+  var b2 = b[2];
+  var b3 = b[3];
+
+  for(r=0; r<rounds-1; r++)
+  {
+    t0 = b0 ^ ctx.rk[r][0];
+    t1 = b1 ^ ctx.rk[r][1];
+    t2 = b2 ^ ctx.rk[r][2];
+    t3 = b3 ^ ctx.rk[r][3];
+
+    b0 = T1[t0&255] ^ T2[(t1>>8)&255] ^ T3[(t2>>16)&255] ^ T4[t3>>>24];
+    b1 = T1[t1&255] ^ T2[(t2>>8)&255] ^ T3[(t3>>16)&255] ^ T4[t0>>>24];
+    b2 = T1[t2&255] ^ T2[(t3>>8)&255] ^ T3[(t0>>16)&255] ^ T4[t1>>>24];
+    b3 = T1[t3&255] ^ T2[(t0>>8)&255] ^ T3[(t1>>16)&255] ^ T4[t2>>>24];
+  }
+
+  // last round is special
+  r = rounds-1;
+
+  t0 = b0 ^ ctx.rk[r][0];
+  t1 = b1 ^ ctx.rk[r][1];
+  t2 = b2 ^ ctx.rk[r][2];
+  t3 = b3 ^ ctx.rk[r][3];
+
+  b[0] = F1(t0, t1, t2, t3) ^ ctx.rk[rounds][0];
+  b[1] = F1(t1, t2, t3, t0) ^ ctx.rk[rounds][1];
+  b[2] = F1(t2, t3, t0, t1) ^ ctx.rk[rounds][2];
+  b[3] = F1(t3, t0, t1, t2) ^ ctx.rk[rounds][3];
+
+  return unpackBytes(b);
+}
+// Modified by Recurity Labs GmbH 
+
+// modified version of http://www.hanewin.net/encrypt/PGdecode.js:
+
+/* OpenPGP encryption using RSA/AES
+ * Copyright 2005-2006 Herbert Hanewinkel, www.haneWIN.de
+ * version 2.0, check www.haneWIN.de for the latest version
+
+ * This software is provided as-is, without express or implied warranty.  
+ * Permission to use, copy, modify, distribute or sell this software, with or
+ * without fee, for any purpose and by any individual or organization, is hereby
+ * granted, provided that the above copyright notice and this paragraph appear 
+ * in all copies. Distribution as a part of an application or binary must
+ * include the above copyright notice in the documentation and/or other
+ * materials provided with the application or distribution.
+ */
+
+// --------------------------------------
+/**
+ * This function encrypts a given with the specified prefixrandom 
+ * using the specified blockcipher to encrypt a message
+ * @param prefixrandom random bytes of block_size length provided 
+ *  as a string to be used in prefixing the data
+ * @param blockcipherfn the algorithm encrypt function to encrypt
+ *  data in one block_size encryption. The function must be 
+ *  specified as blockcipherfn([integer_array(integers 0..255)] 
+ *  block,[integer_array(integers 0..255)] key) returning an 
+ *  array of bytes (integers 0..255)
+ * @param block_size the block size in bytes of the algorithm used
+ * @param plaintext data to be encrypted provided as a string
+ * @param key key to be used to encrypt the data as 
+ *  integer_array(integers 0..255)]. This will be passed to the 
+ *  blockcipherfn
+ * @param resync a boolean value specifying if a resync of the 
+ *  IV should be used or not. The encrypteddatapacket uses the 
+ *  "old" style with a resync. Encryption within an 
+ *  encryptedintegrityprotecteddata packet is not resyncing the IV.
+ * @return a string with the encrypted data
+ */
+function openpgp_cfb_encrypt(prefixrandom, blockcipherencryptfn, plaintext, block_size, key, resync) {
+	var FR = new Array(block_size);
+	var FRE = new Array(block_size);
+
+	prefixrandom = prefixrandom + prefixrandom.charAt(block_size-2) +prefixrandom.charAt(block_size-1);
+	util.print_debug("prefixrandom:"+util.hexstrdump(prefixrandom));
+	var ciphertext = "";
+	// 1.  The feedback register (FR) is set to the IV, which is all zeros.
+	for (var i = 0; i < block_size; i++) FR[i] = 0;
+	
+	// 2.  FR is encrypted to produce FRE (FR Encrypted).  This is the
+    //     encryption of an all-zero value.
+	FRE = blockcipherencryptfn(FR, key);
+	// 3.  FRE is xored with the first BS octets of random data prefixed to
+    //     the plaintext to produce C[1] through C[BS], the first BS octets
+    //     of ciphertext.
+	for (var i = 0; i < block_size; i++) ciphertext += String.fromCharCode(FRE[i] ^ prefixrandom.charCodeAt(i));
+	
+	// 4.  FR is loaded with C[1] through C[BS].
+	for (var i = 0; i < block_size; i++) FR[i] = ciphertext.charCodeAt(i);
+	
+	// 5.  FR is encrypted to produce FRE, the encryption of the first BS
+    // 	   octets of ciphertext.
+	FRE = blockcipherencryptfn(FR, key);
+
+	// 6.  The left two octets of FRE get xored with the next two octets of
+	//     data that were prefixed to the plaintext.  This produces C[BS+1]
+	//     and C[BS+2], the next two octets of ciphertext.
+	ciphertext += String.fromCharCode(FRE[0] ^ prefixrandom.charCodeAt(block_size));
+	ciphertext += String.fromCharCode(FRE[1] ^ prefixrandom.charCodeAt(block_size+1));
+
+	if (resync) {
+		// 7.  (The resync step) FR is loaded with C3-C10.
+		for (var i = 0; i < block_size; i++) FR[i] = ciphertext.charCodeAt(i+2);
+	} else {
+		for (var i = 0; i < block_size; i++) FR[i] = ciphertext.charCodeAt(i);
+	}
+	// 8.  FR is encrypted to produce FRE.
+	FRE = blockcipherencryptfn(FR, key);
+	
+	if (resync) {
+		// 9.  FRE is xored with the first 8 octets of the given plaintext, now
+	    //	   that we have finished encrypting the 10 octets of prefixed data.
+	    // 	   This produces C11-C18, the next 8 octets of ciphertext.
+		for (var i = 0; i < block_size; i++)
+			ciphertext += String.fromCharCode(FRE[i] ^ plaintext.charCodeAt(i));
+		for(n=block_size+2; n < plaintext.length; n+=block_size) {
+			// 10. FR is loaded with C11-C18
+			for (var i = 0; i < block_size; i++) FR[i] = ciphertext.charCodeAt(n+i);
+		
+			// 11. FR is encrypted to produce FRE.
+			FRE = blockcipherencryptfn(FR, key);
+		
+			// 12. FRE is xored with the next 8 octets of plaintext, to produce the
+			// next 8 octets of ciphertext.  These are loaded into FR and the
+			// process is repeated until the plaintext is used up.
+			for (var i = 0; i < block_size; i++) ciphertext += String.fromCharCode(FRE[i] ^ plaintext.charCodeAt((n-2)+i));
+		}
+	}
+	else {
+		plaintext = "  "+plaintext;
+		// 9.  FRE is xored with the first 8 octets of the given plaintext, now
+	    //	   that we have finished encrypting the 10 octets of prefixed data.
+	    // 	   This produces C11-C18, the next 8 octets of ciphertext.
+		for (var i = 2; i < block_size; i++) ciphertext += String.fromCharCode(FRE[i] ^ plaintext.charCodeAt(i));
+		var tempCiphertext = ciphertext.substring(0,2*block_size).split('');
+		var tempCiphertextString = ciphertext.substring(block_size);
+		for(n=block_size; n<plaintext.length; n+=block_size) {
+			// 10. FR is loaded with C11-C18
+			for (var i = 0; i < block_size; i++) FR[i] = tempCiphertextString.charCodeAt(i);
+			tempCiphertextString='';
+			
+			// 11. FR is encrypted to produce FRE.
+			FRE = blockcipherencryptfn(FR, key);
+			
+			// 12. FRE is xored with the next 8 octets of plaintext, to produce the
+			//     next 8 octets of ciphertext.  These are loaded into FR and the
+			//     process is repeated until the plaintext is used up.
+			for (var i = 0; i < block_size; i++){ tempCiphertext.push(String.fromCharCode(FRE[i] ^ plaintext.charCodeAt(n+i)));
+			tempCiphertextString += String.fromCharCode(FRE[i] ^ plaintext.charCodeAt(n+i));
+			}
+		}
+		ciphertext = tempCiphertext.join('');
+		
+	}
+	return ciphertext;
+}
+
+/**
+ * decrypts the prefixed data for the Modification Detection Code (MDC) computation
+ * @param blockcipherencryptfn cipher function to use
+ * @param block_size blocksize of the algorithm
+ * @param key the key for encryption
+ * @param ciphertext the encrypted data
+ * @return plaintext data of D(ciphertext) with blocksize length +2
+ */
+function openpgp_cfb_mdc(blockcipherencryptfn, block_size, key, ciphertext) {
+	var iblock = new Array(block_size);
+	var ablock = new Array(block_size);
+	var i;
+
+	// initialisation vector
+	for(i=0; i < block_size; i++) iblock[i] = 0;
+
+	iblock = blockcipherencryptfn(iblock, key);
+	for(i = 0; i < block_size; i++)
+	{
+		ablock[i] = ciphertext.charCodeAt(i);
+		iblock[i] ^= ablock[i];
+	}
+
+	ablock = blockcipherencryptfn(ablock, key);
+
+	return util.bin2str(iblock)+
+		String.fromCharCode(ablock[0]^ciphertext.charCodeAt(block_size))+
+		String.fromCharCode(ablock[1]^ciphertext.charCodeAt(block_size+1));
+}
+/**
+ * This function decrypts a given plaintext using the specified
+ * blockcipher to decrypt a message
+ * @param blockcipherfn the algorithm _encrypt_ function to encrypt
+ *  data in one block_size encryption. The function must be 
+ *  specified as blockcipherfn([integer_array(integers 0..255)] 
+ *  block,[integer_array(integers 0..255)] key) returning an 
+ *  array of bytes (integers 0..255)
+ * @param block_size the block size in bytes of the algorithm used
+ * @param plaintext ciphertext to be decrypted provided as a string
+ * @param key key to be used to decrypt the ciphertext as 
+ *  integer_array(integers 0..255)]. This will be passed to the 
+ *  blockcipherfn
+ * @param resync a boolean value specifying if a resync of the 
+ *  IV should be used or not. The encrypteddatapacket uses the 
+ *  "old" style with a resync. Decryption within an 
+ *  encryptedintegrityprotecteddata packet is not resyncing the IV.
+ * @return a string with the plaintext data
+ */
+
+function openpgp_cfb_decrypt(blockcipherencryptfn, block_size, key, ciphertext, resync)
+{
+	util.print_debug("resync:"+resync);
+	var iblock = new Array(block_size);
+	var ablock = new Array(block_size);
+	var i, n = '';
+	var text = [];
+
+	// initialisation vector
+	for(i=0; i < block_size; i++) iblock[i] = 0;
+
+	iblock = blockcipherencryptfn(iblock, key);
+	for(i = 0; i < block_size; i++)
+	{
+		ablock[i] = ciphertext.charCodeAt(i);
+		iblock[i] ^= ablock[i];
+	}
+
+	ablock = blockcipherencryptfn(ablock, key);
+
+	util.print_debug("openpgp_cfb_decrypt:\niblock:"+util.hexidump(iblock)+"\nablock:"+util.hexidump(ablock)+"\n");
+	util.print_debug((ablock[0]^ciphertext.charCodeAt(block_size)).toString(16)+(ablock[1]^ciphertext.charCodeAt(block_size+1)).toString(16));
+	
+	// test check octets
+	if(iblock[block_size-2]!=(ablock[0]^ciphertext.charCodeAt(block_size))
+	|| iblock[block_size-1]!=(ablock[1]^ciphertext.charCodeAt(block_size+1)))
+	{
+		util.print_eror("error duding decryption. Symmectric encrypted data not valid.");
+		return text.join('');
+	}
+	
+	/*  RFC4880: Tag 18 and Resync:
+	 *  [...] Unlike the Symmetrically Encrypted Data Packet, no
+   	 *  special CFB resynchronization is done after encrypting this prefix
+     *  data.  See "OpenPGP CFB Mode" below for more details.
+
+	 */
+	
+	if (resync) {
+	    for(i=0; i<block_size; i++) iblock[i] = ciphertext.charCodeAt(i+2);
+		for(n=block_size+2; n<ciphertext.length; n+=block_size)
+		{
+			ablock = blockcipherencryptfn(iblock, key);
+
+			for(i = 0; i<block_size && i+n < ciphertext.length; i++)
+			{
+				iblock[i] = ciphertext.charCodeAt(n+i);
+				text.push(String.fromCharCode(ablock[i]^iblock[i])); 
+			}
+		}
+	} else {
+		for(i=0; i<block_size; i++) iblock[i] = ciphertext.charCodeAt(i);
+		for(n=block_size; n<ciphertext.length; n+=block_size)
+		{
+			ablock = blockcipherencryptfn(iblock, key);
+			for(i = 0; i<block_size && i+n < ciphertext.length; i++)
+			{
+				iblock[i] = ciphertext.charCodeAt(n+i);
+				text.push(String.fromCharCode(ablock[i]^iblock[i])); 
+			}
+		}
+		
+	}
+	
+	return text.join('');
+}
+
+
+function normal_cfb_encrypt(blockcipherencryptfn, block_size, key, plaintext, iv) {
+	var blocki ="";
+	var blockc = "";
+	var pos = 0;
+	var cyphertext = [];
+	var tempBlock = [];
+	blockc = iv.substring(0,block_size);
+	while (plaintext.length > block_size*pos) {
+		var encblock = blockcipherencryptfn(blockc, key);
+		blocki = plaintext.substring((pos*block_size),(pos*block_size)+block_size);
+		for (var i=0; i < blocki.length; i++)
+		    tempBlock.push(String.fromCharCode(blocki.charCodeAt(i) ^ encblock[i]));
+		blockc = tempBlock.join('');
+		tempBlock = [];
+		cyphertext.push(blockc);
+		pos++;
+	}
+	return cyphertext.join('');
+}
+
+function normal_cfb_decrypt(blockcipherencryptfn, block_size, key, ciphertext, iv) { 
+	var blockp ="";
+	var pos = 0;
+	var plaintext = [];
+	var offset = 0;
+	if (iv == null)
+		for (var i = 0; i < block_size; i++) blockp += String.fromCharCode(0);
+	else
+		blockp = iv.substring(0,block_size);
+	while (ciphertext.length > (block_size*pos)) {
+		var decblock = blockcipherencryptfn(blockp, key);
+		blockp = ciphertext.substring((pos*(block_size))+offset,(pos*(block_size))+(block_size)+offset);
+		for (var i=0; i < blockp.length; i++) {
+			plaintext.push(String.fromCharCode(blockp.charCodeAt(i) ^ decblock[i]));
+		}
+		pos++;
+	}
+	
+	return plaintext.join('');
+}
+/* A JavaScript implementation of the SHA family of hashes, as defined in FIPS 
+ * PUB 180-2 as well as the corresponding HMAC implementation as defined in
+ * FIPS PUB 198a
+ *
+ * Version 1.3 Copyright Brian Turek 2008-2010
+ * Distributed under the BSD License
+ * See http://jssha.sourceforge.net/ for more information
+ *
+ * Several functions taken from Paul Johnson
+ */
+
+/* Modified by Recurity Labs GmbH
+ * 
+ * This code has been slightly modified direct string output:
+ * - bin2bstr has been added
+ * - following wrappers of this library have been added:
+ *   - str_sha1
+ *   - str_sha256
+ *   - str_sha224
+ *   - str_sha384
+ *   - str_sha512
+ */
+
+var jsSHA = (function () {
+	
+	/*
+	 * Configurable variables. Defaults typically work
+	 */
+	/* Number of Bits Per character (8 for ASCII, 16 for Unicode) */
+	var charSize = 8, 
+	/* base-64 pad character. "=" for strict RFC compliance */
+	b64pad = "", 
+	/* hex output format. 0 - lowercase; 1 - uppercase */
+	hexCase = 0, 
+
+	/*
+	 * Int_64 is a object for 2 32-bit numbers emulating a 64-bit number
+	 *
+	 * @constructor
+	 * @param {Number} msint_32 The most significant 32-bits of a 64-bit number
+	 * @param {Number} lsint_32 The least significant 32-bits of a 64-bit number
+	 */
+	Int_64 = function (msint_32, lsint_32)
+	{
+		this.highOrder = msint_32;
+		this.lowOrder = lsint_32;
+	},
+
+	/*
+	 * Convert a string to an array of big-endian words
+	 * If charSize is ASCII, characters >255 have their hi-byte silently
+	 * ignored.
+	 *
+	 * @param {String} str String to be converted to binary representation
+	 * @return Integer array representation of the parameter
+	 */
+	str2binb = function (str)
+	{
+		var bin = [], mask = (1 << charSize) - 1,
+			length = str.length * charSize, i;
+
+		for (i = 0; i < length; i += charSize)
+		{
+			bin[i >> 5] |= (str.charCodeAt(i / charSize) & mask) <<
+				(32 - charSize - (i % 32));
+		}
+
+		return bin;
+	},
+
+	/*
+	 * Convert a hex string to an array of big-endian words
+	 *
+	 * @param {String} str String to be converted to binary representation
+	 * @return Integer array representation of the parameter
+	 */
+	hex2binb = function (str)
+	{
+		var bin = [], length = str.length, i, num;
+
+		for (i = 0; i < length; i += 2)
+		{
+			num = parseInt(str.substr(i, 2), 16);
+			if (!isNaN(num))
+			{
+				bin[i >> 3] |= num << (24 - (4 * (i % 8)));
+			}
+			else
+			{
+				return "INVALID HEX STRING";
+			}
+		}
+
+		return bin;
+	},
+
+	/*
+	 * Convert an array of big-endian words to a hex string.
+	 *
+	 * @private
+	 * @param {Array} binarray Array of integers to be converted to hexidecimal
+	 *	 representation
+	 * @return Hexidecimal representation of the parameter in String form
+	 */
+	binb2hex = function (binarray)
+	{
+		var hex_tab = (hexCase) ? "0123456789ABCDEF" : "0123456789abcdef",
+			str = "", length = binarray.length * 4, i, srcByte;
+
+		for (i = 0; i < length; i += 1)
+		{
+			srcByte = binarray[i >> 2] >> ((3 - (i % 4)) * 8);
+			str += hex_tab.charAt((srcByte >> 4) & 0xF) +
+				hex_tab.charAt(srcByte & 0xF);
+		}
+
+		return str;
+	},
+
+	/*
+	 * Convert an array of big-endian words to a base-64 string
+	 *
+	 * @private
+	 * @param {Array} binarray Array of integers to be converted to base-64
+	 *	 representation
+	 * @return Base-64 encoded representation of the parameter in String form
+	 */
+	binb2b64 = function (binarray)
+	{
+		var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +
+			"0123456789+/", str = "", length = binarray.length * 4, i, j,
+			triplet;
+
+		for (i = 0; i < length; i += 3)
+		{
+			triplet = (((binarray[i >> 2] >> 8 * (3 - i % 4)) & 0xFF) << 16) |
+				(((binarray[i + 1 >> 2] >> 8 * (3 - (i + 1) % 4)) & 0xFF) << 8) |
+				((binarray[i + 2 >> 2] >> 8 * (3 - (i + 2) % 4)) & 0xFF);
+			for (j = 0; j < 4; j += 1)
+			{
+				if (i * 8 + j * 6 <= binarray.length * 32)
+				{
+					str += tab.charAt((triplet >> 6 * (3 - j)) & 0x3F);
+				}
+				else
+				{
+					str += b64pad;
+				}
+			}
+		}
+		return str;
+	},
+
+	/*
+	 * Convert an array of big-endian words to a string
+	 */
+	binb2str = function (bin)
+	{
+	  var str = "";
+	  var mask = (1 << 8) - 1;
+	  for(var i = 0; i < bin.length * 32; i += 8)
+	    str += String.fromCharCode((bin[i>>5] >>> (24 - i%32)) & mask);
+	  return str;
+	},
+	/*
+	 * The 32-bit implementation of circular rotate left
+	 *
+	 * @private
+	 * @param {Number} x The 32-bit integer argument
+	 * @param {Number} n The number of bits to shift
+	 * @return The x shifted circularly by n bits
+	 */
+	rotl_32 = function (x, n)
+	{
+		return (x << n) | (x >>> (32 - n));
+	},
+
+	/*
+	 * The 32-bit implementation of circular rotate right
+	 *
+	 * @private
+	 * @param {Number} x The 32-bit integer argument
+	 * @param {Number} n The number of bits to shift
+	 * @return The x shifted circularly by n bits
+	 */
+	rotr_32 = function (x, n)
+	{
+		return (x >>> n) | (x << (32 - n));
+	},
+
+	/*
+	 * The 64-bit implementation of circular rotate right
+	 *
+	 * @private
+	 * @param {Int_64} x The 64-bit integer argument
+	 * @param {Number} n The number of bits to shift
+	 * @return The x shifted circularly by n bits
+	 */
+	rotr_64 = function (x, n)
+	{
+		if (n <= 32)
+		{
+			return new Int_64(
+					(x.highOrder >>> n) | (x.lowOrder << (32 - n)),
+					(x.lowOrder >>> n) | (x.highOrder << (32 - n))
+				);
+		}
+		else
+		{
+			return new Int_64(
+					(x.lowOrder >>> n) | (x.highOrder << (32 - n)),
+					(x.highOrder >>> n) | (x.lowOrder << (32 - n))
+				);
+		}
+	},
+
+	/*
+	 * The 32-bit implementation of shift right
+	 *
+	 * @private
+	 * @param {Number} x The 32-bit integer argument
+	 * @param {Number} n The number of bits to shift
+	 * @return The x shifted by n bits
+	 */
+	shr_32 = function (x, n)
+	{
+		return x >>> n;
+	},
+
+	/*
+	 * The 64-bit implementation of shift right
+	 *
+	 * @private
+	 * @param {Int_64} x The 64-bit integer argument
+	 * @param {Number} n The number of bits to shift
+	 * @return The x shifted by n bits
+	 */
+	shr_64 = function (x, n)
+	{
+		if (n <= 32)
+		{
+			return new Int_64(
+					x.highOrder >>> n,
+					x.lowOrder >>> n | (x.highOrder << (32 - n))
+				);
+		}
+		else
+		{
+			return new Int_64(
+					0,
+					x.highOrder << (32 - n)
+				);
+		}
+	},
+
+	/*
+	 * The 32-bit implementation of the NIST specified Parity function
+	 *
+	 * @private
+	 * @param {Number} x The first 32-bit integer argument
+	 * @param {Number} y The second 32-bit integer argument
+	 * @param {Number} z The third 32-bit integer argument
+	 * @return The NIST specified output of the function
+	 */
+	parity_32 = function (x, y, z)
+	{
+		return x ^ y ^ z;
+	},
+
+	/*
+	 * The 32-bit implementation of the NIST specified Ch function
+	 *
+	 * @private
+	 * @param {Number} x The first 32-bit integer argument
+	 * @param {Number} y The second 32-bit integer argument
+	 * @param {Number} z The third 32-bit integer argument
+	 * @return The NIST specified output of the function
+	 */
+	ch_32 = function (x, y, z)
+	{
+		return (x & y) ^ (~x & z);
+	},
+
+	/*
+	 * The 64-bit implementation of the NIST specified Ch function
+	 *
+	 * @private
+	 * @param {Int_64} x The first 64-bit integer argument
+	 * @param {Int_64} y The second 64-bit integer argument
+	 * @param {Int_64} z The third 64-bit integer argument
+	 * @return The NIST specified output of the function
+	 */
+	ch_64 = function (x, y, z)
+	{
+		return new Int_64(
+				(x.highOrder & y.highOrder) ^ (~x.highOrder & z.highOrder),
+				(x.lowOrder & y.lowOrder) ^ (~x.lowOrder & z.lowOrder)
+			);
+	},
+
+	/*
+	 * The 32-bit implementation of the NIST specified Maj function
+	 *
+	 * @private
+	 * @param {Number} x The first 32-bit integer argument
+	 * @param {Number} y The second 32-bit integer argument
+	 * @param {Number} z The third 32-bit integer argument
+	 * @return The NIST specified output of the function
+	 */
+	maj_32 = function (x, y, z)
+	{
+		return (x & y) ^ (x & z) ^ (y & z);
+	},
+
+	/*
+	 * The 64-bit implementation of the NIST specified Maj function
+	 *
+	 * @private
+	 * @param {Int_64} x The first 64-bit integer argument
+	 * @param {Int_64} y The second 64-bit integer argument
+	 * @param {Int_64} z The third 64-bit integer argument
+	 * @return The NIST specified output of the function
+	 */
+	maj_64 = function (x, y, z)
+	{
+		return new Int_64(
+				(x.highOrder & y.highOrder) ^
+				(x.highOrder & z.highOrder) ^
+				(y.highOrder & z.highOrder),
+				(x.lowOrder & y.lowOrder) ^
+				(x.lowOrder & z.lowOrder) ^
+				(y.lowOrder & z.lowOrder)
+			);
+	},
+
+	/*
+	 * The 32-bit implementation of the NIST specified Sigma0 function
+	 *
+	 * @private
+	 * @param {Number} x The 32-bit integer argument
+	 * @return The NIST specified output of the function
+	 */
+	sigma0_32 = function (x)
+	{
+		return rotr_32(x, 2) ^ rotr_32(x, 13) ^ rotr_32(x, 22);
+	},
+
+	/*
+	 * The 64-bit implementation of the NIST specified Sigma0 function
+	 *
+	 * @private
+	 * @param {Int_64} x The 64-bit integer argument
+	 * @return The NIST specified output of the function
+	 */
+	sigma0_64 = function (x)
+	{
+		var rotr28 = rotr_64(x, 28), rotr34 = rotr_64(x, 34),
+			rotr39 = rotr_64(x, 39);
+
+		return new Int_64(
+				rotr28.highOrder ^ rotr34.highOrder ^ rotr39.highOrder,
+				rotr28.lowOrder ^ rotr34.lowOrder ^ rotr39.lowOrder);
+	},
+
+	/*
+	 * The 32-bit implementation of the NIST specified Sigma1 function
+	 *
+	 * @private
+	 * @param {Number} x The 32-bit integer argument
+	 * @return The NIST specified output of the function
+	 */
+	sigma1_32 = function (x)
+	{
+		return rotr_32(x, 6) ^ rotr_32(x, 11) ^ rotr_32(x, 25);
+	},
+
+	/*
+	 * The 64-bit implementation of the NIST specified Sigma1 function
+	 *
+	 * @private
+	 * @param {Int_64} x The 64-bit integer argument
+	 * @return The NIST specified output of the function
+	 */
+	sigma1_64 = function (x)
+	{
+		var rotr14 = rotr_64(x, 14), rotr18 = rotr_64(x, 18),
+			rotr41 = rotr_64(x, 41);
+
+		return new Int_64(
+				rotr14.highOrder ^ rotr18.highOrder ^ rotr41.highOrder,
+				rotr14.lowOrder ^ rotr18.lowOrder ^ rotr41.lowOrder);
+	},
+
+	/*
+	 * The 32-bit implementation of the NIST specified Gamma0 function
+	 *
+	 * @private
+	 * @param {Number} x The 32-bit integer argument
+	 * @return The NIST specified output of the function
+	 */
+	gamma0_32 = function (x)
+	{
+		return rotr_32(x, 7) ^ rotr_32(x, 18) ^ shr_32(x, 3);
+	},
+
+	/*
+	 * The 64-bit implementation of the NIST specified Gamma0 function
+	 *
+	 * @private
+	 * @param {Int_64} x The 64-bit integer argument
+	 * @return The NIST specified output of the function
+	 */
+	gamma0_64 = function (x)
+	{
+		var rotr1 = rotr_64(x, 1), rotr8 = rotr_64(x, 8), shr7 = shr_64(x, 7);
+
+		return new Int_64(
+				rotr1.highOrder ^ rotr8.highOrder ^ shr7.highOrder,
+				rotr1.lowOrder ^ rotr8.lowOrder ^ shr7.lowOrder
+			);
+	},
+
+	/*
+	 * The 32-bit implementation of the NIST specified Gamma1 function
+	 *
+	 * @private
+	 * @param {Number} x The 32-bit integer argument
+	 * @return The NIST specified output of the function
+	 */
+	gamma1_32 = function (x)
+	{
+		return rotr_32(x, 17) ^ rotr_32(x, 19) ^ shr_32(x, 10);
+	},
+
+	/*
+	 * The 64-bit implementation of the NIST specified Gamma1 function
+	 *
+	 * @private
+	 * @param {Int_64} x The 64-bit integer argument
+	 * @return The NIST specified output of the function
+	 */
+	gamma1_64 = function (x)
+	{
+		var rotr19 = rotr_64(x, 19), rotr61 = rotr_64(x, 61),
+			shr6 = shr_64(x, 6);
+
+		return new Int_64(
+				rotr19.highOrder ^ rotr61.highOrder ^ shr6.highOrder,
+				rotr19.lowOrder ^ rotr61.lowOrder ^ shr6.lowOrder
+			);
+	},
+
+	/*
+	 * Add two 32-bit integers, wrapping at 2^32. This uses 16-bit operations
+	 * internally to work around bugs in some JS interpreters.
+	 *
+	 * @private
+	 * @param {Number} x The first 32-bit integer argument to be added
+	 * @param {Number} y The second 32-bit integer argument to be added
+	 * @return The sum of x + y
+	 */
+	safeAdd_32_2 = function (x, y)
+	{
+		var lsw = (x & 0xFFFF) + (y & 0xFFFF),
+			msw = (x >>> 16) + (y >>> 16) + (lsw >>> 16);
+
+		return ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+	},
+
+	/*
+	 * Add four 32-bit integers, wrapping at 2^32. This uses 16-bit operations
+	 * internally to work around bugs in some JS interpreters.
+	 *
+	 * @private
+	 * @param {Number} a The first 32-bit integer argument to be added
+	 * @param {Number} b The second 32-bit integer argument to be added
+	 * @param {Number} c The third 32-bit integer argument to be added
+	 * @param {Number} d The fourth 32-bit integer argument to be added
+	 * @return The sum of a + b + c + d
+	 */
+	safeAdd_32_4 = function (a, b, c, d)
+	{
+		var lsw = (a & 0xFFFF) + (b & 0xFFFF) + (c & 0xFFFF) + (d & 0xFFFF),
+			msw = (a >>> 16) + (b >>> 16) + (c >>> 16) + (d >>> 16) +
+				(lsw >>> 16);
+
+		return ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+	},
+
+	/*
+	 * Add five 32-bit integers, wrapping at 2^32. This uses 16-bit operations
+	 * internally to work around bugs in some JS interpreters.
+	 *
+	 * @private
+	 * @param {Number} a The first 32-bit integer argument to be added
+	 * @param {Number} b The second 32-bit integer argument to be added
+	 * @param {Number} c The third 32-bit integer argument to be added
+	 * @param {Number} d The fourth 32-bit integer argument to be added
+	 * @param {Number} e The fifth 32-bit integer argument to be added
+	 * @return The sum of a + b + c + d + e
+	 */
+	safeAdd_32_5 = function (a, b, c, d, e)
+	{
+		var lsw = (a & 0xFFFF) + (b & 0xFFFF) + (c & 0xFFFF) + (d & 0xFFFF) +
+				(e & 0xFFFF),
+			msw = (a >>> 16) + (b >>> 16) + (c >>> 16) + (d >>> 16) +
+				(e >>> 16) + (lsw >>> 16);
+
+		return ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+	},
+
+	/*
+	 * Add two 64-bit integers, wrapping at 2^64. This uses 16-bit operations
+	 * internally to work around bugs in some JS interpreters.
+	 *
+	 * @private
+	 * @param {Int_64} x The first 64-bit integer argument to be added
+	 * @param {Int_64} y The second 64-bit integer argument to be added
+	 * @return The sum of x + y
+	 */
+	safeAdd_64_2 = function (x, y)
+	{
+		var lsw, msw, lowOrder, highOrder;
+
+		lsw = (x.lowOrder & 0xFFFF) + (y.lowOrder & 0xFFFF);
+		msw = (x.lowOrder >>> 16) + (y.lowOrder >>> 16) + (lsw >>> 16);
+		lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+
+		lsw = (x.highOrder & 0xFFFF) + (y.highOrder & 0xFFFF) + (msw >>> 16);
+		msw = (x.highOrder >>> 16) + (y.highOrder >>> 16) + (lsw >>> 16);
+		highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+
+		return new Int_64(highOrder, lowOrder);
+	},
+
+	/*
+	 * Add four 64-bit integers, wrapping at 2^64. This uses 16-bit operations
+	 * internally to work around bugs in some JS interpreters.
+	 *
+	 * @private
+	 * @param {Int_64} a The first 64-bit integer argument to be added
+	 * @param {Int_64} b The second 64-bit integer argument to be added
+	 * @param {Int_64} c The third 64-bit integer argument to be added
+	 * @param {Int_64} d The fouth 64-bit integer argument to be added
+	 * @return The sum of a + b + c + d
+	 */
+	safeAdd_64_4 = function (a, b, c, d)
+	{
+		var lsw, msw, lowOrder, highOrder;
+
+		lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) +
+			(c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF);
+		msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) +
+			(c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (lsw >>> 16);
+		lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+
+		lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) +
+			(c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (msw >>> 16);
+		msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) +
+			(c.highOrder >>> 16) + (d.highOrder >>> 16) + (lsw >>> 16);
+		highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+
+		return new Int_64(highOrder, lowOrder);
+	},
+
+	/*
+	 * Add five 64-bit integers, wrapping at 2^64. This uses 16-bit operations
+	 * internally to work around bugs in some JS interpreters.
+	 *
+	 * @private
+	 * @param {Int_64} a The first 64-bit integer argument to be added
+	 * @param {Int_64} b The second 64-bit integer argument to be added
+	 * @param {Int_64} c The third 64-bit integer argument to be added
+	 * @param {Int_64} d The fouth 64-bit integer argument to be added
+	 * @param {Int_64} e The fouth 64-bit integer argument to be added
+	 * @return The sum of a + b + c + d + e
+	 */
+	safeAdd_64_5 = function (a, b, c, d, e)
+	{
+		var lsw, msw, lowOrder, highOrder;
+
+		lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) +
+			(c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF) +
+			(e.lowOrder & 0xFFFF);
+		msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) +
+			(c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (e.lowOrder >>> 16) +
+			(lsw >>> 16);
+		lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+
+		lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) +
+			(c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) +
+			(e.highOrder & 0xFFFF) + (msw >>> 16);
+		msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) +
+			(c.highOrder >>> 16) + (d.highOrder >>> 16) +
+			(e.highOrder >>> 16) + (lsw >>> 16);
+		highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+
+		return new Int_64(highOrder, lowOrder);
+	},
+
+	/*
+	 * Calculates the SHA-1 hash of the string set at instantiation
+	 *
+	 * @private
+	 * @param {Array} message The binary array representation of the string to
+	 *	 hash
+	 * @param {Number} messageLen The number of bits in the message
+	 * @return The array of integers representing the SHA-1 hash of message
+	 */
+	coreSHA1 = function (message, messageLen)
+	{
+		var W = [], a, b, c, d, e, T, ch = ch_32, parity = parity_32,
+			maj = maj_32, rotl = rotl_32, safeAdd_2 = safeAdd_32_2, i, t,
+			safeAdd_5 = safeAdd_32_5, appendedMessageLength,
+			H = [
+				0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0
+			],
+			K = [
+				0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999,
+				0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999,
+				0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999,
+				0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999,
+				0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999,
+				0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1,
+				0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1,
+				0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1,
+				0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1,
+				0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1,
+				0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc,
+				0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc,
+				0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc,
+				0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc,
+				0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc,
+				0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6,
+				0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6,
+				0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6,
+				0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6,
+				0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6
+			];
+
+		/* Append '1' at the end of the binary string */
+		message[messageLen >> 5] |= 0x80 << (24 - (messageLen % 32));
+		/* Append length of binary string in the position such that the new
+		length is a multiple of 512.  Logic does not work for even multiples
+		of 512 but there can never be even multiples of 512 */
+		message[(((messageLen + 65) >> 9) << 4) + 15] = messageLen;
+
+		appendedMessageLength = message.length;
+
+		for (i = 0; i < appendedMessageLength; i += 16)
+		{
+			a = H[0];
+			b = H[1];
+			c = H[2];
+			d = H[3];
+			e = H[4];
+
+			for (t = 0; t < 80; t += 1)
+			{
+				if (t < 16)
+				{
+					W[t] = message[t + i];
+				}
+				else
+				{
+					W[t] = rotl(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1);
+				}
+
+				if (t < 20)
+				{
+					T = safeAdd_5(rotl(a, 5), ch(b, c, d), e, K[t], W[t]);
+				}
+				else if (t < 40)
+				{
+					T = safeAdd_5(rotl(a, 5), parity(b, c, d), e, K[t], W[t]);
+				}
+				else if (t < 60)
+				{
+					T = safeAdd_5(rotl(a, 5), maj(b, c, d), e, K[t], W[t]);
+				} else {
+					T = safeAdd_5(rotl(a, 5), parity(b, c, d), e, K[t], W[t]);
+				}
+
+				e = d;
+				d = c;
+				c = rotl(b, 30);
+				b = a;
+				a = T;
+			}
+
+			H[0] = safeAdd_2(a, H[0]);
+			H[1] = safeAdd_2(b, H[1]);
+			H[2] = safeAdd_2(c, H[2]);
+			H[3] = safeAdd_2(d, H[3]);
+			H[4] = safeAdd_2(e, H[4]);
+		}
+
+		return H;
+	},
+
+	/*
+	 * Calculates the desired SHA-2 hash of the string set at instantiation
+	 *
+	 * @private
+	 * @param {Array} The binary array representation of the string to hash
+	 * @param {Number} The number of bits in message
+	 * @param {String} variant The desired SHA-2 variant
+	 * @return The array of integers representing the SHA-2 hash of message
+	 */
+	coreSHA2 = function (message, messageLen, variant)
+	{
+		var a, b, c, d, e, f, g, h, T1, T2, H, numRounds, lengthPosition, i, t,
+			binaryStringInc, binaryStringMult, safeAdd_2, safeAdd_4, safeAdd_5,
+			gamma0, gamma1, sigma0, sigma1, ch, maj, Int, K, W = [],
+			appendedMessageLength;
+
+		/* Set up the various function handles and variable for the specific 
+		 * variant */
+		if (variant === "SHA-224" || variant === "SHA-256")
+		{
+			/* 32-bit variant */
+			numRounds = 64;
+			lengthPosition = (((messageLen + 65) >> 9) << 4) + 15;
+			binaryStringInc = 16;
+			binaryStringMult = 1;
+			Int = Number;
+			safeAdd_2 = safeAdd_32_2;
+			safeAdd_4 = safeAdd_32_4;
+			safeAdd_5 = safeAdd_32_5;
+			gamma0 = gamma0_32;
+			gamma1 = gamma1_32;
+			sigma0 = sigma0_32;
+			sigma1 = sigma1_32;
+			maj = maj_32;
+			ch = ch_32;
+			K = [
+					0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
+					0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
+					0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
+					0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
+					0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
+					0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
+					0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
+					0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
+					0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
+					0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
+					0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
+					0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
+					0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
+					0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
+					0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
+					0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
+				];
+
+			if (variant === "SHA-224")
+			{
+				H = [
+						0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
+						0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
+					];
+			}
+			else
+			{
+				H = [
+						0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
+						0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
+					];
+			}
+		}
+		else if (variant === "SHA-384" || variant === "SHA-512")
+		{
+			/* 64-bit variant */
+			numRounds = 80;
+			lengthPosition = (((messageLen + 128) >> 10) << 5) + 31;
+			binaryStringInc = 32;
+			binaryStringMult = 2;
+			Int = Int_64;
+			safeAdd_2 = safeAdd_64_2;
+			safeAdd_4 = safeAdd_64_4;
+			safeAdd_5 = safeAdd_64_5;
+			gamma0 = gamma0_64;
+			gamma1 = gamma1_64;
+			sigma0 = sigma0_64;
+			sigma1 = sigma1_64;
+			maj = maj_64;
+			ch = ch_64;
+
+			K = [
+				new Int(0x428a2f98, 0xd728ae22), new Int(0x71374491, 0x23ef65cd),
+				new Int(0xb5c0fbcf, 0xec4d3b2f), new Int(0xe9b5dba5, 0x8189dbbc),
+				new Int(0x3956c25b, 0xf348b538), new Int(0x59f111f1, 0xb605d019),
+				new Int(0x923f82a4, 0xaf194f9b), new Int(0xab1c5ed5, 0xda6d8118),
+				new Int(0xd807aa98, 0xa3030242), new Int(0x12835b01, 0x45706fbe),
+				new Int(0x243185be, 0x4ee4b28c), new Int(0x550c7dc3, 0xd5ffb4e2),
+				new Int(0x72be5d74, 0xf27b896f), new Int(0x80deb1fe, 0x3b1696b1),
+				new Int(0x9bdc06a7, 0x25c71235), new Int(0xc19bf174, 0xcf692694),
+				new Int(0xe49b69c1, 0x9ef14ad2), new Int(0xefbe4786, 0x384f25e3),
+				new Int(0x0fc19dc6, 0x8b8cd5b5), new Int(0x240ca1cc, 0x77ac9c65),
+				new Int(0x2de92c6f, 0x592b0275), new Int(0x4a7484aa, 0x6ea6e483),
+				new Int(0x5cb0a9dc, 0xbd41fbd4), new Int(0x76f988da, 0x831153b5),
+				new Int(0x983e5152, 0xee66dfab), new Int(0xa831c66d, 0x2db43210),
+				new Int(0xb00327c8, 0x98fb213f), new Int(0xbf597fc7, 0xbeef0ee4),
+				new Int(0xc6e00bf3, 0x3da88fc2), new Int(0xd5a79147, 0x930aa725),
+				new Int(0x06ca6351, 0xe003826f), new Int(0x14292967, 0x0a0e6e70),
+				new Int(0x27b70a85, 0x46d22ffc), new Int(0x2e1b2138, 0x5c26c926),
+				new Int(0x4d2c6dfc, 0x5ac42aed), new Int(0x53380d13, 0x9d95b3df),
+				new Int(0x650a7354, 0x8baf63de), new Int(0x766a0abb, 0x3c77b2a8),
+				new Int(0x81c2c92e, 0x47edaee6), new Int(0x92722c85, 0x1482353b),
+				new Int(0xa2bfe8a1, 0x4cf10364), new Int(0xa81a664b, 0xbc423001),
+				new Int(0xc24b8b70, 0xd0f89791), new Int(0xc76c51a3, 0x0654be30),
+				new Int(0xd192e819, 0xd6ef5218), new Int(0xd6990624, 0x5565a910),
+				new Int(0xf40e3585, 0x5771202a), new Int(0x106aa070, 0x32bbd1b8),
+				new Int(0x19a4c116, 0xb8d2d0c8), new Int(0x1e376c08, 0x5141ab53),
+				new Int(0x2748774c, 0xdf8eeb99), new Int(0x34b0bcb5, 0xe19b48a8),
+				new Int(0x391c0cb3, 0xc5c95a63), new Int(0x4ed8aa4a, 0xe3418acb),
+				new Int(0x5b9cca4f, 0x7763e373), new Int(0x682e6ff3, 0xd6b2b8a3),
+				new Int(0x748f82ee, 0x5defb2fc), new Int(0x78a5636f, 0x43172f60),
+				new Int(0x84c87814, 0xa1f0ab72), new Int(0x8cc70208, 0x1a6439ec),
+				new Int(0x90befffa, 0x23631e28), new Int(0xa4506ceb, 0xde82bde9),
+				new Int(0xbef9a3f7, 0xb2c67915), new Int(0xc67178f2, 0xe372532b),
+				new Int(0xca273ece, 0xea26619c), new Int(0xd186b8c7, 0x21c0c207),
+				new Int(0xeada7dd6, 0xcde0eb1e), new Int(0xf57d4f7f, 0xee6ed178),
+				new Int(0x06f067aa, 0x72176fba), new Int(0x0a637dc5, 0xa2c898a6),
+				new Int(0x113f9804, 0xbef90dae), new Int(0x1b710b35, 0x131c471b),
+				new Int(0x28db77f5, 0x23047d84), new Int(0x32caab7b, 0x40c72493),
+				new Int(0x3c9ebe0a, 0x15c9bebc), new Int(0x431d67c4, 0x9c100d4c),
+				new Int(0x4cc5d4be, 0xcb3e42b6), new Int(0x597f299c, 0xfc657e2a),
+				new Int(0x5fcb6fab, 0x3ad6faec), new Int(0x6c44198c, 0x4a475817)
+			];
+
+			if (variant === "SHA-384")
+			{
+				H = [
+					new Int(0xcbbb9d5d, 0xc1059ed8), new Int(0x0629a292a, 0x367cd507),
+					new Int(0x9159015a, 0x3070dd17), new Int(0x0152fecd8, 0xf70e5939),
+					new Int(0x67332667, 0xffc00b31), new Int(0x98eb44a87, 0x68581511),
+					new Int(0xdb0c2e0d, 0x64f98fa7), new Int(0x047b5481d, 0xbefa4fa4)
+				];
+			}
+			else
+			{
+				H = [
+					new Int(0x6a09e667, 0xf3bcc908), new Int(0xbb67ae85, 0x84caa73b),
+					new Int(0x3c6ef372, 0xfe94f82b), new Int(0xa54ff53a, 0x5f1d36f1),
+					new Int(0x510e527f, 0xade682d1), new Int(0x9b05688c, 0x2b3e6c1f),
+					new Int(0x1f83d9ab, 0xfb41bd6b), new Int(0x5be0cd19, 0x137e2179)
+				];
+			}
+		}
+
+		/* Append '1' at the end of the binary string */
+		message[messageLen >> 5] |= 0x80 << (24 - messageLen % 32);
+		/* Append length of binary string in the position such that the new
+		 * length is correct */
+		message[lengthPosition] = messageLen;
+
+		appendedMessageLength = message.length;
+
+		for (i = 0; i < appendedMessageLength; i += binaryStringInc)
+		{
+			a = H[0];
+			b = H[1];
+			c = H[2];
+			d = H[3];
+			e = H[4];
+			f = H[5];
+			g = H[6];
+			h = H[7];
+
+			for (t = 0; t < numRounds; t += 1)
+			{
+				if (t < 16)
+				{
+					/* Bit of a hack - for 32-bit, the second term is ignored */
+					W[t] = new Int(message[t * binaryStringMult + i],
+							message[t * binaryStringMult + i + 1]);
+				}
+				else
+				{
+					W[t] = safeAdd_4(
+							gamma1(W[t - 2]), W[t - 7],
+							gamma0(W[t - 15]), W[t - 16]
+						);
+				}
+
+				T1 = safeAdd_5(h, sigma1(e), ch(e, f, g), K[t], W[t]);
+				T2 = safeAdd_2(sigma0(a), maj(a, b, c));
+				h = g;
+				g = f;
+				f = e;
+				e = safeAdd_2(d, T1);
+				d = c;
+				c = b;
+				b = a;
+				a = safeAdd_2(T1, T2);
+			}
+
+			H[0] = safeAdd_2(a, H[0]);
+			H[1] = safeAdd_2(b, H[1]);
+			H[2] = safeAdd_2(c, H[2]);
+			H[3] = safeAdd_2(d, H[3]);
+			H[4] = safeAdd_2(e, H[4]);
+			H[5] = safeAdd_2(f, H[5]);
+			H[6] = safeAdd_2(g, H[6]);
+			H[7] = safeAdd_2(h, H[7]);
+		}
+
+		switch (variant)
+		{
+		case "SHA-224":
+			return	[
+				H[0], H[1], H[2], H[3],
+				H[4], H[5], H[6]
+			];
+		case "SHA-256":
+			return H;
+		case "SHA-384":
+			return [
+				H[0].highOrder, H[0].lowOrder,
+				H[1].highOrder, H[1].lowOrder,
+				H[2].highOrder, H[2].lowOrder,
+				H[3].highOrder, H[3].lowOrder,
+				H[4].highOrder, H[4].lowOrder,
+				H[5].highOrder, H[5].lowOrder
+			];
+		case "SHA-512":
+			return [
+				H[0].highOrder, H[0].lowOrder,
+				H[1].highOrder, H[1].lowOrder,
+				H[2].highOrder, H[2].lowOrder,
+				H[3].highOrder, H[3].lowOrder,
+				H[4].highOrder, H[4].lowOrder,
+				H[5].highOrder, H[5].lowOrder,
+				H[6].highOrder, H[6].lowOrder,
+				H[7].highOrder, H[7].lowOrder
+			];
+		default:
+			/* This should never be reached */
+			return []; 
+		}
+	},
+
+	/*
+	 * jsSHA is the workhorse of the library.  Instantiate it with the string to
+	 * be hashed as the parameter
+	 *
+	 * @constructor
+	 * @param {String} srcString The string to be hashed
+	 * @param {String} inputFormat The format of srcString, ASCII or HEX
+	 */
+	jsSHA = function (srcString, inputFormat)
+	{
+
+		this.sha1 = null;
+		this.sha224 = null;
+		this.sha256 = null;
+		this.sha384 = null;
+		this.sha512 = null;
+
+		this.strBinLen = null;
+		this.strToHash = null;
+
+		/* Convert the input string into the correct type */
+		if ("HEX" === inputFormat)
+		{
+			if (0 !== (srcString.length % 2))
+			{
+				return "TEXT MUST BE IN BYTE INCREMENTS";
+			}
+			this.strBinLen = srcString.length * 4;
+			this.strToHash = hex2binb(srcString);
+		}
+		else if (("ASCII" === inputFormat) ||
+			 ('undefined' === typeof(inputFormat)))
+		{
+			this.strBinLen = srcString.length * charSize;
+			this.strToHash = str2binb(srcString);
+		}
+		else
+		{
+			return "UNKNOWN TEXT INPUT TYPE";
+		}
+	};
+
+	jsSHA.prototype = {
+		/*
+		 * Returns the desired SHA hash of the string specified at instantiation
+		 * using the specified parameters
+		 *
+		 * @param {String} variant The desired SHA variant (SHA-1, SHA-224,
+		 *	 SHA-256, SHA-384, or SHA-512)
+		 * @param {String} format The desired output formatting (B64 or HEX)
+		 * @return The string representation of the hash in the format specified
+		 */
+		getHash : function (variant, format)
+		{
+			var formatFunc = null, message = this.strToHash.slice();
+
+			switch (format)
+			{
+			case "HEX":
+				formatFunc = binb2hex;
+				break;
+			case "B64":
+				formatFunc = binb2b64;
+				break;
+			case "ASCII":
+				formatFunc = binb2str;
+				break;
+			default:
+				return "FORMAT NOT RECOGNIZED";
+			}
+
+			switch (variant)
+			{
+			case "SHA-1":
+				if (null === this.sha1)
+				{
+					this.sha1 = coreSHA1(message, this.strBinLen);
+				}
+				return formatFunc(this.sha1);
+			case "SHA-224":
+				if (null === this.sha224)
+				{
+					this.sha224 = coreSHA2(message, this.strBinLen, variant);
+				}
+				return formatFunc(this.sha224);
+			case "SHA-256":
+				if (null === this.sha256)
+				{
+					this.sha256 = coreSHA2(message, this.strBinLen, variant);
+				}
+				return formatFunc(this.sha256);
+			case "SHA-384":
+				if (null === this.sha384)
+				{
+					this.sha384 = coreSHA2(message, this.strBinLen, variant);
+				}
+				return formatFunc(this.sha384);
+			case "SHA-512":
+				if (null === this.sha512)
+				{
+					this.sha512 = coreSHA2(message, this.strBinLen, variant);
+				}
+				return formatFunc(this.sha512);
+			default:
+				return "HASH NOT RECOGNIZED";
+			}
+		},
+
+		/*
+		 * Returns the desired HMAC of the string specified at instantiation
+		 * using the key and variant param.
+		 *
+		 * @param {String} key The key used to calculate the HMAC
+		 * @param {String} inputFormat The format of key, ASCII or HEX
+		 * @param {String} variant The desired SHA variant (SHA-1, SHA-224,
+		 *	 SHA-256, SHA-384, or SHA-512)
+		 * @param {String} outputFormat The desired output formatting
+		 *	 (B64 or HEX)
+		 * @return The string representation of the hash in the format specified
+		 */
+		getHMAC : function (key, inputFormat, variant, outputFormat)
+		{
+			var formatFunc, keyToUse, blockByteSize, blockBitSize, i,
+				retVal, lastArrayIndex, keyBinLen, hashBitSize,
+				keyWithIPad = [], keyWithOPad = [];
+
+			/* Validate the output format selection */
+			switch (outputFormat)
+			{
+			case "HEX":
+				formatFunc = binb2hex;
+				break;
+			case "B64":
+				formatFunc = binb2b64;
+				break;
+			case "ASCII":
+				formatFunc = binb2str;
+				break;
+			default:
+				return "FORMAT NOT RECOGNIZED";
+			}
+
+			/* Validate the hash variant selection and set needed variables */
+			switch (variant)
+			{
+			case "SHA-1":
+				blockByteSize = 64;
+				hashBitSize = 160;
+				break;
+			case "SHA-224":
+				blockByteSize = 64;
+				hashBitSize = 224;
+				break;
+			case "SHA-256":
+				blockByteSize = 64;
+				hashBitSize = 256;
+				break;
+			case "SHA-384":
+				blockByteSize = 128;
+				hashBitSize = 384;
+				break;
+			case "SHA-512":
+				blockByteSize = 128;
+				hashBitSize = 512;
+				break;
+			default:
+				return "HASH NOT RECOGNIZED";
+			}
+
+			/* Validate input format selection */
+			if ("HEX" === inputFormat)
+			{
+				/* Nibbles must come in pairs */
+				if (0 !== (key.length % 2))
+				{
+					return "KEY MUST BE IN BYTE INCREMENTS";
+				}
+				keyToUse = hex2binb(key);
+				keyBinLen = key.length * 4;
+			}
+			else if ("ASCII" === inputFormat)
+			{
+				keyToUse = str2binb(key);
+				keyBinLen = key.length * charSize;
+			}
+			else
+			{
+				return "UNKNOWN KEY INPUT TYPE";
+			}
+
+			/* These are used multiple times, calculate and store them */
+			blockBitSize = blockByteSize * 8;
+			lastArrayIndex = (blockByteSize / 4) - 1;
+
+			/* Figure out what to do with the key based on its size relative to
+			 * the hash's block size */
+			if (blockByteSize < (keyBinLen / 8))
+			{
+				if ("SHA-1" === variant)
+				{
+					keyToUse = coreSHA1(keyToUse, keyBinLen);
+				}
+				else
+				{
+					keyToUse = coreSHA2(keyToUse, keyBinLen, variant);
+				}
+				/* For all variants, the block size is bigger than the output
+				 * size so there will never be a useful byte at the end of the
+				 * string */
+				keyToUse[lastArrayIndex] &= 0xFFFFFF00;
+			}
+			else if (blockByteSize > (keyBinLen / 8))
+			{
+				/* If the blockByteSize is greater than the key length, there
+				 * will always be at LEAST one "useless" byte at the end of the
+				 * string */
+				keyToUse[lastArrayIndex] &= 0xFFFFFF00;
+			}
+
+			/* Create ipad and opad */
+			for (i = 0; i <= lastArrayIndex; i += 1)
+			{
+				keyWithIPad[i] = keyToUse[i] ^ 0x36363636;
+				keyWithOPad[i] = keyToUse[i] ^ 0x5C5C5C5C;
+			}
+
+			/* Calculate the HMAC */
+			if ("SHA-1" === variant)
+			{
+				retVal = coreSHA1(
+							keyWithIPad.concat(this.strToHash),
+							blockBitSize + this.strBinLen);
+				retVal = coreSHA1(
+							keyWithOPad.concat(retVal),
+							blockBitSize + hashBitSize);
+			}
+			else
+			{
+				retVal = coreSHA2(
+							keyWithIPad.concat(this.strToHash),
+							blockBitSize + this.strBinLen, variant);
+				retVal = coreSHA2(
+							keyWithOPad.concat(retVal),
+							blockBitSize + hashBitSize, variant);
+			}
+
+			return (formatFunc(retVal));
+		}
+	};
+
+	return jsSHA;
+}());
+
+function str_sha1(str) {
+	var shaObj = new jsSHA(str, "ASCII");
+	return shaObj.getHash("SHA-1", "ASCII");
+}
+
+function str_sha224(str) {
+	var shaObj = new jsSHA(str, "ASCII");
+	return shaObj.getHash("SHA-224", "ASCII");
+}
+
+function str_sha256(str) {
+	var shaObj = new jsSHA(str, "ASCII");
+	return shaObj.getHash("SHA-256", "ASCII");
+}
+
+
+function str_sha384(str) {
+	var shaObj = new jsSHA(str, "ASCII");
+	return shaObj.getHash("SHA-384", "ASCII");
+
+}
+
+function str_sha512(str) {
+	var shaObj = new jsSHA(str, "ASCII");
+	return shaObj.getHash("SHA-512", "ASCII");
+}
+/*
+ * CryptoMX Tools
+ * Copyright (C) 2004 - 2006 Derek Buitenhuis
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/* Modified by Recurity Labs GmbH
+ */
+
+var RMDsize   = 160;
+var X = new Array();
+
+function ROL(x, n)
+{
+  return new Number ((x << n) | ( x >>> (32 - n)));
+}
+
+function F(x, y, z)
+{
+  return new Number(x ^ y ^ z);
+}
+
+function G(x, y, z)
+{
+  return new Number((x & y) | (~x & z));
+}
+
+function H(x, y, z)
+{
+  return new Number((x | ~y) ^ z);
+}
+
+function I(x, y, z)
+{
+  return new Number((x & z) | (y & ~z));
+}
+
+function J(x, y, z)
+{
+  return new Number(x ^ (y | ~z));
+}
+
+function mixOneRound(a, b, c, d, e, x, s, roundNumber)
+{
+  switch (roundNumber)
+  {
+    case 0 : a += F(b, c, d) + x + 0x00000000; break;
+    case 1 : a += G(b, c, d) + x + 0x5a827999; break;
+    case 2 : a += H(b, c, d) + x + 0x6ed9eba1; break;
+    case 3 : a += I(b, c, d) + x + 0x8f1bbcdc; break;
+    case 4 : a += J(b, c, d) + x + 0xa953fd4e; break;
+    case 5 : a += J(b, c, d) + x + 0x50a28be6; break;
+    case 6 : a += I(b, c, d) + x + 0x5c4dd124; break;
+    case 7 : a += H(b, c, d) + x + 0x6d703ef3; break;
+    case 8 : a += G(b, c, d) + x + 0x7a6d76e9; break;
+    case 9 : a += F(b, c, d) + x + 0x00000000; break;
+    
+    default : document.write("Bogus round number"); break;
+  }  
+  
+  a = ROL(a, s) + e;
+  c = ROL(c, 10);
+
+  a &= 0xffffffff;
+  b &= 0xffffffff;
+  c &= 0xffffffff;
+  d &= 0xffffffff;
+  e &= 0xffffffff;
+
+  var retBlock = new Array();
+  retBlock[0] = a;
+  retBlock[1] = b;
+  retBlock[2] = c;
+  retBlock[3] = d;
+  retBlock[4] = e;
+  retBlock[5] = x;
+  retBlock[6] = s;
+
+  return retBlock;
+}
+
+function MDinit (MDbuf)
+{
+  MDbuf[0] = 0x67452301;
+  MDbuf[1] = 0xefcdab89;
+  MDbuf[2] = 0x98badcfe;
+  MDbuf[3] = 0x10325476;
+  MDbuf[4] = 0xc3d2e1f0;
+}
+
+var ROLs = [
+  [11, 14, 15, 12,  5,  8,  7,  9, 11, 13, 14, 15,  6,  7,  9,  8],
+  [ 7,  6,  8, 13, 11,  9,  7, 15,  7, 12, 15,  9, 11,  7, 13, 12],
+  [11, 13,  6,  7, 14,  9, 13, 15, 14,  8, 13,  6,  5, 12,  7,  5],
+  [11, 12, 14, 15, 14, 15,  9,  8,  9, 14,  5,  6,  8,  6,  5, 12],
+  [ 9, 15,  5, 11,  6,  8, 13, 12,  5, 12, 13, 14, 11,  8,  5,  6],
+  [ 8,  9,  9, 11, 13, 15, 15,  5,  7,  7,  8, 11, 14, 14, 12,  6],
+  [ 9, 13, 15,  7, 12,  8,  9, 11,  7,  7, 12,  7,  6, 15, 13, 11],
+  [ 9,  7, 15, 11,  8,  6,  6, 14, 12, 13,  5, 14, 13, 13,  7,  5],
+  [15,  5,  8, 11, 14, 14,  6, 14,  6,  9, 12,  9, 12,  5, 15,  8],
+  [ 8,  5, 12,  9, 12,  5, 14,  6,  8, 13,  6,  5, 15, 13, 11, 11]
+];
+
+var indexes = [
+  [ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15],
+  [ 7,  4, 13,  1, 10,  6, 15,  3, 12,  0,  9,  5,  2, 14, 11,  8],
+  [ 3, 10, 14,  4,  9, 15,  8,  1,  2,  7,  0,  6, 13, 11,  5, 12],
+  [ 1,  9, 11, 10,  0,  8, 12,  4, 13,  3,  7, 15, 14,  5,  6,  2],
+  [ 4,  0,  5,  9,  7, 12,  2, 10, 14,  1,  3,  8, 11,  6, 15, 13],
+  [ 5, 14,  7,  0,  9,  2, 11,  4, 13,  6, 15,  8,  1, 10,  3, 12],
+  [ 6, 11,  3,  7,  0, 13,  5, 10, 14, 15,  8, 12,  4,  9,  1,  2],
+  [15,  5,  1,  3,  7, 14,  6,  9, 11,  8, 12,  2, 10,  0,  4, 13],
+  [ 8,  6,  4,  1,  3, 11, 15,  0,  5, 12,  2, 13,  9,  7, 10, 14],
+  [12, 15, 10,  4,  1,  5,  8,  7,  6,  2, 13, 14,  0,  3,  9, 11]
+];
+
+function compress (MDbuf, X)
+{
+  blockA = new Array();
+  blockB = new Array();
+
+  var retBlock;
+
+  for (var i=0; i < 5; i++)
+  {
+    blockA[i] = new Number(MDbuf[i]);
+    blockB[i] = new Number(MDbuf[i]);
+  }
+
+  var step = 0;
+  for (var j = 0; j < 5; j++)
+  {
+    for (var i = 0; i < 16; i++)
+    {
+      retBlock = mixOneRound(
+        blockA[(step+0) % 5],
+        blockA[(step+1) % 5],   
+        blockA[(step+2) % 5],   
+        blockA[(step+3) % 5],   
+        blockA[(step+4) % 5],  
+        X[indexes[j][i]], 
+        ROLs[j][i],
+        j
+      );
+
+      blockA[(step+0) % 5] = retBlock[0];
+      blockA[(step+1) % 5] = retBlock[1];
+      blockA[(step+2) % 5] = retBlock[2];
+      blockA[(step+3) % 5] = retBlock[3];
+      blockA[(step+4) % 5] = retBlock[4];
+
+      step += 4;
+    }
+  }
+
+  step = 0;
+  for (var j = 5; j < 10; j++)
+  {
+    for (var i = 0; i < 16; i++)
+    {  
+      retBlock = mixOneRound(
+        blockB[(step+0) % 5], 
+        blockB[(step+1) % 5], 
+        blockB[(step+2) % 5], 
+        blockB[(step+3) % 5], 
+        blockB[(step+4) % 5],  
+        X[indexes[j][i]], 
+        ROLs[j][i],
+        j
+      );
+
+      blockB[(step+0) % 5] = retBlock[0];
+      blockB[(step+1) % 5] = retBlock[1];
+      blockB[(step+2) % 5] = retBlock[2];
+      blockB[(step+3) % 5] = retBlock[3];
+      blockB[(step+4) % 5] = retBlock[4];
+
+      step += 4;
+    }
+  }
+
+  blockB[3] += blockA[2] + MDbuf[1];
+  MDbuf[1]  = MDbuf[2] + blockA[3] + blockB[4];
+  MDbuf[2]  = MDbuf[3] + blockA[4] + blockB[0];
+  MDbuf[3]  = MDbuf[4] + blockA[0] + blockB[1];
+  MDbuf[4]  = MDbuf[0] + blockA[1] + blockB[2];
+  MDbuf[0]  = blockB[3];
+}
+
+function zeroX(X)
+{
+  for (var i = 0; i < 16; i++) { X[i] = 0; }
+}
+
+function MDfinish (MDbuf, strptr, lswlen, mswlen)
+{
+  var X = new Array(16);
+  zeroX(X);
+
+  var j = 0;
+  for (var i=0; i < (lswlen & 63); i++)
+  {
+    X[i >>> 2] ^= (strptr.charCodeAt(j++) & 255) << (8 * (i & 3));
+  }
+
+  X[(lswlen >>> 2) & 15] ^= 1 << (8 * (lswlen & 3) + 7);
+
+  if ((lswlen & 63) > 55)
+  {
+    compress(MDbuf, X);
+    var X = new Array(16);
+    zeroX(X);
+  }
+
+  X[14] = lswlen << 3;
+  X[15] = (lswlen >>> 29) | (mswlen << 3);
+
+  compress(MDbuf, X);
+}
+
+function BYTES_TO_DWORD(fourChars)
+{
+  var tmp  = (fourChars.charCodeAt(3) & 255) << 24;
+  tmp   |= (fourChars.charCodeAt(2) & 255) << 16;
+  tmp   |= (fourChars.charCodeAt(1) & 255) << 8;
+  tmp   |= (fourChars.charCodeAt(0) & 255);  
+
+  return tmp;
+}
+
+function RMD(message)
+{
+  var MDbuf   = new Array(RMDsize / 32);
+  var hashcode   = new Array(RMDsize / 8);
+  var length;  
+  var nbytes;
+
+  MDinit(MDbuf);
+  length = message.length;
+
+  var X = new Array(16);
+  zeroX(X);
+
+  var j=0;
+  for (var nbytes=length; nbytes > 63; nbytes -= 64)
+  {
+    for (var i=0; i < 16; i++)
+    {
+      X[i] = BYTES_TO_DWORD(message.substr(j, 4));
+      j += 4;
+    }
+    compress(MDbuf, X);
+  }
+
+  MDfinish(MDbuf, message.substr(j), length, 0);
+
+  for (var i=0; i < RMDsize / 8; i += 4)
+  {
+    hashcode[i]   =  MDbuf[i >>> 2]   & 255;
+    hashcode[i+1] = (MDbuf[i >>> 2] >>> 8)   & 255;
+    hashcode[i+2] = (MDbuf[i >>> 2] >>> 16) & 255;
+    hashcode[i+3] = (MDbuf[i >>> 2] >>> 24) & 255;
+  }
+
+  return hashcode;
+}
+
+
+function RMDstring(message)
+{
+  var hashcode = RMD(message);
+  var retString = "";
+
+  for (var i=0; i < RMDsize/8; i++)
+  {
+    retString += String.fromCharCode(hashcode[i]);
+  }  
+
+  return retString;  
+}/**
+ * A fast MD5 JavaScript implementation
+ * Copyright (c) 2012 Joseph Myers
+ * http://www.myersdaily.org/joseph/javascript/md5-text.html
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies.
+ *
+ * Of course, this soft is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+function MD5(entree) {
+	var hex = md5(entree);
+	var bin = util.hex2bin(hex);
+	return bin;
+}
+
+function md5cycle(x, k) {
+var a = x[0], b = x[1], c = x[2], d = x[3];
+
+a = ff(a, b, c, d, k[0], 7, -680876936);
+d = ff(d, a, b, c, k[1], 12, -389564586);
+c = ff(c, d, a, b, k[2], 17,  606105819);
+b = ff(b, c, d, a, k[3], 22, -1044525330);
+a = ff(a, b, c, d, k[4], 7, -176418897);
+d = ff(d, a, b, c, k[5], 12,  1200080426);
+c = ff(c, d, a, b, k[6], 17, -1473231341);
+b = ff(b, c, d, a, k[7], 22, -45705983);
+a = ff(a, b, c, d, k[8], 7,  1770035416);
+d = ff(d, a, b, c, k[9], 12, -1958414417);
+c = ff(c, d, a, b, k[10], 17, -42063);
+b = ff(b, c, d, a, k[11], 22, -1990404162);
+a = ff(a, b, c, d, k[12], 7,  1804603682);
+d = ff(d, a, b, c, k[13], 12, -40341101);
+c = ff(c, d, a, b, k[14], 17, -1502002290);
+b = ff(b, c, d, a, k[15], 22,  1236535329);
+
+a = gg(a, b, c, d, k[1], 5, -165796510);
+d = gg(d, a, b, c, k[6], 9, -1069501632);
+c = gg(c, d, a, b, k[11], 14,  643717713);
+b = gg(b, c, d, a, k[0], 20, -373897302);
+a = gg(a, b, c, d, k[5], 5, -701558691);
+d = gg(d, a, b, c, k[10], 9,  38016083);
+c = gg(c, d, a, b, k[15], 14, -660478335);
+b = gg(b, c, d, a, k[4], 20, -405537848);
+a = gg(a, b, c, d, k[9], 5,  568446438);
+d = gg(d, a, b, c, k[14], 9, -1019803690);
+c = gg(c, d, a, b, k[3], 14, -187363961);
+b = gg(b, c, d, a, k[8], 20,  1163531501);
+a = gg(a, b, c, d, k[13], 5, -1444681467);
+d = gg(d, a, b, c, k[2], 9, -51403784);
+c = gg(c, d, a, b, k[7], 14,  1735328473);
+b = gg(b, c, d, a, k[12], 20, -1926607734);
+
+a = hh(a, b, c, d, k[5], 4, -378558);
+d = hh(d, a, b, c, k[8], 11, -2022574463);
+c = hh(c, d, a, b, k[11], 16,  1839030562);
+b = hh(b, c, d, a, k[14], 23, -35309556);
+a = hh(a, b, c, d, k[1], 4, -1530992060);
+d = hh(d, a, b, c, k[4], 11,  1272893353);
+c = hh(c, d, a, b, k[7], 16, -155497632);
+b = hh(b, c, d, a, k[10], 23, -1094730640);
+a = hh(a, b, c, d, k[13], 4,  681279174);
+d = hh(d, a, b, c, k[0], 11, -358537222);
+c = hh(c, d, a, b, k[3], 16, -722521979);
+b = hh(b, c, d, a, k[6], 23,  76029189);
+a = hh(a, b, c, d, k[9], 4, -640364487);
+d = hh(d, a, b, c, k[12], 11, -421815835);
+c = hh(c, d, a, b, k[15], 16,  530742520);
+b = hh(b, c, d, a, k[2], 23, -995338651);
+
+a = ii(a, b, c, d, k[0], 6, -198630844);
+d = ii(d, a, b, c, k[7], 10,  1126891415);
+c = ii(c, d, a, b, k[14], 15, -1416354905);
+b = ii(b, c, d, a, k[5], 21, -57434055);
+a = ii(a, b, c, d, k[12], 6,  1700485571);
+d = ii(d, a, b, c, k[3], 10, -1894986606);
+c = ii(c, d, a, b, k[10], 15, -1051523);
+b = ii(b, c, d, a, k[1], 21, -2054922799);
+a = ii(a, b, c, d, k[8], 6,  1873313359);
+d = ii(d, a, b, c, k[15], 10, -30611744);
+c = ii(c, d, a, b, k[6], 15, -1560198380);
+b = ii(b, c, d, a, k[13], 21,  1309151649);
+a = ii(a, b, c, d, k[4], 6, -145523070);
+d = ii(d, a, b, c, k[11], 10, -1120210379);
+c = ii(c, d, a, b, k[2], 15,  718787259);
+b = ii(b, c, d, a, k[9], 21, -343485551);
+
+x[0] = add32(a, x[0]);
+x[1] = add32(b, x[1]);
+x[2] = add32(c, x[2]);
+x[3] = add32(d, x[3]);
+
+}
+
+function cmn(q, a, b, x, s, t) {
+a = add32(add32(a, q), add32(x, t));
+return add32((a << s) | (a >>> (32 - s)), b);
+}
+
+function ff(a, b, c, d, x, s, t) {
+return cmn((b & c) | ((~b) & d), a, b, x, s, t);
+}
+
+function gg(a, b, c, d, x, s, t) {
+return cmn((b & d) | (c & (~d)), a, b, x, s, t);
+}
+
+function hh(a, b, c, d, x, s, t) {
+return cmn(b ^ c ^ d, a, b, x, s, t);
+}
+
+function ii(a, b, c, d, x, s, t) {
+return cmn(c ^ (b | (~d)), a, b, x, s, t);
+}
+
+function md51(s) {
+txt = '';
+var n = s.length,
+state = [1732584193, -271733879, -1732584194, 271733878], i;
+for (i=64; i<=s.length; i+=64) {
+md5cycle(state, md5blk(s.substring(i-64, i)));
+}
+s = s.substring(i-64);
+var tail = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
+for (i=0; i<s.length; i++)
+tail[i>>2] |= s.charCodeAt(i) << ((i%4) << 3);
+tail[i>>2] |= 0x80 << ((i%4) << 3);
+if (i > 55) {
+md5cycle(state, tail);
+for (i=0; i<16; i++) tail[i] = 0;
+}
+tail[14] = n*8;
+md5cycle(state, tail);
+return state;
+}
+
+/* there needs to be support for Unicode here,
+ * unless we pretend that we can redefine the MD-5
+ * algorithm for multi-byte characters (perhaps
+ * by adding every four 16-bit characters and
+ * shortening the sum to 32 bits). Otherwise
+ * I suggest performing MD-5 as if every character
+ * was two bytes--e.g., 0040 0025 = @%--but then
+ * how will an ordinary MD-5 sum be matched?
+ * There is no way to standardize text to something
+ * like UTF-8 before transformation; speed cost is
+ * utterly prohibitive. The JavaScript standard
+ * itself needs to look at this: it should start
+ * providing access to strings as preformed UTF-8
+ * 8-bit unsigned value arrays.
+ */
+function md5blk(s) { /* I figured global was faster.   */
+var md5blks = [], i; /* Andy King said do it this way. */
+for (i=0; i<64; i+=4) {
+md5blks[i>>2] = s.charCodeAt(i)
++ (s.charCodeAt(i+1) << 8)
++ (s.charCodeAt(i+2) << 16)
++ (s.charCodeAt(i+3) << 24);
+}
+return md5blks;
+}
+
+var hex_chr = '0123456789abcdef'.split('');
+
+function rhex(n)
+{
+var s='', j=0;
+for(; j<4; j++)
+s += hex_chr[(n >> (j * 8 + 4)) & 0x0F]
++ hex_chr[(n >> (j * 8)) & 0x0F];
+return s;
+}
+
+function hex(x) {
+for (var i=0; i<x.length; i++)
+x[i] = rhex(x[i]);
+return x.join('');
+}
+
+function md5(s) {
+return hex(md51(s));
+}
+
+/* this function is much faster,
+so if possible we use it. Some IEs
+are the only ones I know of that
+need the idiotic second function,
+generated by an if clause.  */
+
+function add32(a, b) {
+return (a + b) & 0xFFFFFFFF;
+}
+
+if (md5('hello') != '5d41402abc4b2a76b9719d911017c592') {
+function add32(x, y) {
+var lsw = (x & 0xFFFF) + (y & 0xFFFF),
+msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+return (msw << 16) | (lsw & 0xFFFF);
+}
 }
 // GPG4Browsers - An OpenPGP implementation in javascript
 // Copyright (C) 2011 Recurity Labs GmbH
@@ -15009,264 +14449,839 @@ function openpgp_keyring() {
 // License along with this library; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
-var Util = function() {
+function openpgp_msg_privatekey() {
+	this.subKeys = new Array();
+	this.privateKeyPacket = null;
+	this.userIds = new Array();
+	this.userAttributes = new Array();
+	this.revocationSignatures = new Array();
+	this.subKeys = new Array();
 
-    this.emailRegEx = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
-	
-	this.hexdump = function(str) {
-	    var r=[];
-	    var e=str.length;
-	    var c=0;
-	    var h;
-	    var i = 0;
-	    while(c<e){
-	        h=str.charCodeAt(c++).toString(16);
-	        while(h.length<2) h="0"+h;
-	        r.push(" "+h);
-	        i++;
-	        if (i % 32 == 0)
-	        	r.push("\n           ");
-	    }
-	    return r.join('');
-	};
-	
 	/**
-	 * create hexstring from a binary
-	 * @param str [String] string to convert
-	 * @return [String] string containing the hexadecimal values
+	 * 
+	 * @return last position
 	 */
-	this.hexstrdump = function(str) {
-		if (str == null)
-			return "";
-	    var r=[];
-	    var e=str.length;
-	    var c=0;
-	    var h;
-	    while(c<e){
-	        h=str[c++].charCodeAt().toString(16);
-	        while(h.length<2) h="0"+h;
-	        r.push(""+h);
-	    }
-	    return r.join('');
-	};
+	function read_nodes(parent_node, input, position, len) {
+		this.privateKeyPacket = parent_node;
+		
+		var pos = position;
+		while (input.length > pos) {
+			var result = openpgp_packet.read_packet(input, pos, input.length - pos);
+			if (result == null) {
+				util.print_error("openpgp.msg.messge decrypt:\n"+'[pub/priv_key]parsing ends here @:' + pos + " l:" + len);
+				break;
+			} else {
+				switch (result.tagType) {
+				case 2: // public key revocation signature
+					if (result.signatureType == 32)
+						this.revocationSignatures[this.revocationSignatures.length] = result;
+					else if (result.signatureType > 15 && result.signatureType < 20) {
+						if (this.certificationsignatures == null)
+							this.certificationSignatures = new Array();
+						this.certificationSignatures[this.certificationSignatures.length] = result;
+					} else
+						util.print_error("openpgp.msg.messge decrypt:\n"+"unknown signature type directly on key "+result.signatureType+" @"+pos);
+					pos += result.packetLength + result.headerLength;
+					break;
+				case 7: // PrivateSubkey Packet
+					this.subKeys[this.subKeys.length] = result;
+					pos += result.packetLength + result.headerLength;
+					pos += result.read_nodes(this.privateKeyPacket,input, pos, input.length - pos);
+					break;
+				case 17: // User Attribute Packet
+					this.userAttributes[this.userAttributes.length] = result;
+					pos += result.packetLength + result.headerLength;
+					pos += result.read_nodes(this.privateKeyPacket,input, pos, input.length - pos);
+					break;
+				case 13: // User ID Packet
+					this.userIds[this.userIds.length] = result;
+					pos += result.packetLength + result.headerLength;
+					pos += result.read_nodes(this.privateKeyPacket, input, pos, input.length - pos);
+					break;
+				default:
+					this.position = position - this.privateKeyPacket.packetLength - this.privateKeyPacket.headerLength;
+					this.len = pos - position;
+					return this.len;
+				}
+			}
+		}
+		this.position = position - this.privateKeyPacket.packetLength - this.privateKeyPacket.headerLength;
+		this.len = pos - position;
+		
+		return this.len;
+	}
 	
-	/**
-	 * create binary string from a hex encoded string
-	 * @param str [String] hex string to convert
-	 * @return [String] string containing the binary values
-	 */
-	this.hex2bin = function(hex) {
-	    var str = '';
-	    for (var i = 0; i < hex.length; i += 2)
-	        str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
-	    return str;
-	};
+	function getKeyId() {
+		return this.privateKeyPacket.publicKey.getKeyId();
+	}
 	
-	/**
-	 * creating a hex string from an binary array of integers (0..255)
-	 * @param [Array[integer 0..255]] array to convert
-	 * @return [String] hexadecimal representation of the array
-	 */
-	this.hexidump = function(str) {
-	    var r=[];
-	    var e=str.length;
-	    var c=0;
-	    var h;
-	    while(c<e){
-	        h=str[c++].toString(16);
-	        while(h.length<2) h="0"+h;
-	        r.push(""+h);
-	    }
-	    return r.join('');
-	};
 	
-	/**
-	 * convert a string to an array of integers(0.255)
-	 * @param [String] string to convert
-	 * @return [Array [Integer 0..255]] array of (binary) integers
-	 */
-	this.str2bin = function(str) {
+	function getSubKeyIds() {
+		if (this.privateKeyPacket.publicKey.version == 4) // V3 keys MUST NOT have subkeys.
 		var result = new Array();
-		for (var i = 0; i < str.length; i++) {
-			result[i] = str.charCodeAt(i);
+		for (var i = 0; i < this.subKeys.length; i++) {
+			result[i] = str_sha1(this.subKeys[i].publicKey.header+this.subKeys[i].publicKey.data).substring(12,20);
+		}
+		return result;
+	}
+	
+	
+	function getSigningKey() {
+		if ((this.privateKeyPacket.publicKey.publicKeyAlgorithm == 17 ||
+			 this.privateKeyPacket.publicKey.publicKeyAlgorithm != 2)
+			&& this.privateKeyPacket.publicKey.verifyKey() == 3)
+			return this.privateKeyPacket;
+		else if (this.privateKeyPacket.publicKey.version == 4) // V3 keys MUST NOT have subkeys.
+			for (var j = 0; j < this.privateKeyPacket.subKeys.length; j++) {
+				if ((this.privateKeyPacket.subKeys[j].publicKey.publicKeyAlgorithm == 17 ||
+					 this.privateKeyPacket.subKeys[j].publicKey.publicKeyAlgorithm != 2) &&
+					 this.privateKeyPacket.subKeys[j].publicKey.verifyKey() == 3)
+					return this.privateKeyPacket.subKeys[j];
+			}
+		return null;
+	}
+	
+	function getPreferredSignatureHashAlgorithm() {
+		var pkey = this.getSigningKey();
+		if (pkey == null) {
+			util.print_error("private key is for encryption only! Cannot create a signature.")
+			return null;
+		}
+		if (pkey.publicKey.publicKeyAlgorithm == 17) {
+			var dsa = new DSA();
+			return dsa.select_hash_algorithm(pkey.publicKey.MPIs[1].toBigInteger()); // q
+		}
+		return openpgp.config.config.prefer_hash_algorithm;
+			
+	}
+
+	function decryptSecretMPIs(str_passphrase) {
+		return this.privateKeyPacket.decryptSecretMPIs(str_passphrase);
+	}
+	
+	function getFingerprint() {
+		return this.privateKeyPacket.publicKey.getFingerprint();
+	}
+
+	// TODO need to implement this
+	function revoke() {
+		
+	}
+	this.getSigningKey = getSigningKey;
+	this.getFingerprint = getFingerprint;
+	this.getPreferredSignatureHashAlgorithm = getPreferredSignatureHashAlgorithm;
+	this.read_nodes = read_nodes;
+	this.decryptSecretMPIs = decryptSecretMPIs;
+	this.getSubKeyIds = getSubKeyIds;
+	this.getKeyId = getKeyId;
+	
+}// GPG4Browsers - An OpenPGP implementation in javascript
+// Copyright (C) 2011 Recurity Labs GmbH
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+function openpgp_msg_publickey() {
+	this.data;
+	this.position;
+	this.len;
+	this.tostring = "OPENPGP PUBLIC KEY\n";
+	this.bindingSignature = null;
+	this.publicKeyPacket = null;
+	this.userIds = new Array();
+	this.userAttributes = new Array();
+	this.revocationSignatures = new Array();
+	this.subKeys = new Array();
+	this.arbitraryPacket = new Array();
+	this.directSignatures = new Array();
+	/**
+	 * 
+	 * @return last position
+	 */
+	function read_nodes(parent_node, input, position, len) {
+		this.publicKeyPacket = parent_node;
+		var exit = false;
+		var pos = position;
+		var l = len;
+		while (input.length != pos) {
+			var result = openpgp_packet.read_packet(input, pos, input.length - pos);
+			if (result == null) {
+				util.print_error("openpgp.msg.publickey read_nodes:\n"+'[pub_key]parsing ends here @:' + pos + " l:" + l);
+				break;
+			} else {
+				switch (result.tagType) {
+				case 2: // public key revocation signature
+					if (result.signatureType == 32)
+						this.revocationSignatures[this.revocationSignatures.length] = result;
+					else if (result.signatureType == 16 || result.signatureType == 17 || result.signatureType == 18  || result.signatureType == 19)
+						this.certificationSignature = result;
+					else if (result.signatureType == 25) {
+						this.bindingSignature = result;
+					} else if (result.signatureType == 31) {
+						this.directSignatures[this.directSignatures.length] = result;
+					} else
+						util.print_error("openpgp.msg.publickey read_nodes:\n"+"unknown signature type directly on key "+result.signatureType);
+					pos += result.packetLength + result.headerLength;
+					break;
+				case 14: // Public-Subkey Packet
+					this.subKeys[this.subKeys.length] = result;
+					pos += result.packetLength + result.headerLength;
+					pos += result.read_nodes(this.publicKeyPacket,input, pos, input.length - pos);
+					break;
+				case 17: // User Attribute Packet
+					this.userAttributes[this.userAttributes.length] = result;
+					pos += result.packetLength + result.headerLength;
+					pos += result.read_nodes(this.publicKeyPacket,input, pos, input.length - pos);
+					break;
+				case 13: // User ID Packet
+					this.userIds[this.userIds.length] = result;
+					pos += result.packetLength + result.headerLength;
+					pos += result.read_nodes(this.publicKeyPacket, input, pos, input.length - pos);
+					break;
+				default:
+					this.data = input;
+					this.position = position - this.publicKeyPacket.packetLength - this.publicKeyPacket.headerLength;
+					this.len = pos - position;
+					return this.len;
+				}
+			}
+		}
+		this.data = input;
+		this.position = position - (this.publicKeyPacket.packetLength - this.publicKeyPacket.headerLength);
+		this.len = pos - position;
+		return this.len;
+	}
+
+	function write() {
+
+	}
+
+	function getKeyId() {
+		return this.publicKeyPacket.getKeyId();
+	}
+	
+	function getFingerprint() {
+		return this.publicKeyPacket.getFingerprint();
+	}
+
+
+	
+	function validate() {
+		// check revocation keys
+		for (var i = 0; i < this.revocationSignatures.length; i++) {
+			var tohash = this.publicKeyPacket.header+this.publicKeyPacket.data;
+			if (this.revocationSignatures[i].verify(tohash, this.publicKeyPacket))
+				return false;
 		}
 		
+		if (this.subKeys.length != 0) {
+			// search for a valid subkey
+			var found = false;
+			for (var i = 0; i < this.subKeys.length; i++)
+				if (this.subKeys[i].verifyKey() == 3) {
+					found = true;
+					break;
+				}
+			if (!found)
+				return false;
+		}
+		// search for one valid userid
+		found = false;
+		for (var i = 0; i < this.userIds.length; i++)
+			if (this.userIds[i].verify(this.publicKeyPacket) == 0) {
+				found = true;
+				break;
+			}
+		if (!found)
+			return false;
+		return true;
+	}
+	
+	/**
+	 * verifies all signatures
+	 * @return a 2 dimensional array. the first dimension corresponds to the userids available
+	 */
+	function verifyCertificationSignatures() {
+		var result = new Array();
+		for (var i = 0; i < this.userIds.length; i++) {
+			result[i] = this.userIds[i].verifyCertificationSignatures(this.publicKeyPacket);
+		}
 		return result;
-	};
+	}
+	this.verifyCertificationSignatures = verifyCertificationSignatures;
+	
+	/**
+	 * verifies:
+	 *  - revocation certificates directly on key
+	 *  - self signatures
+	 *  - subkey binding and revocation certificates
+	 *  
+	 *  This is useful for validating the key
+	 *  @returns true if the basic signatures are all valid
+	 */
+	function verifyBasicSignatures() {
+		for (var i = 0; i < this.revocationSignatures.length; i++) {
+			var tohash = this.publicKeyPacket.header+this.publicKeyPacket.data;
+			if (this.revocationSignatures[i].verify(tohash, this.publicKeyPacket))
+				return false;
+			else return false;
+		}
+		
+		if (this.subKeys.length != 0) {
+			// search for a valid subkey
+			var found = false;
+			for (var i = 0; i < this.subKeys.length; i++) {
+				if (this.subKeys[i] == null)
+					continue;
+				var result = this.subKeys[i].verifyKey();
+				if (result == 3) {
+					found = true;
+					break;
+				} 
+			}
+			if (!found)
+				return false;
+		}
+		var keyId = this.getKeyId();
+		for (var i = 0; i < this.userIds.length; i++) {
+			for (var j = 0; j < this.userIds[i].certificationRevocationSignatures.length; j++) {
+				if (this.userIds[i].certificationSignatures[j].getIssuer == keyId &&
+					this.userIds[i].certificationSignatures[j].verifyBasic(this.publicKeyPacket) != 4)
+					return false;
+			}
+		}
+		return true;
+	}
+	
+	function toString() {
+		var result = " OPENPGP Public Key\n    length: "+this.len+"\n";
+		result += "    Revocation Signatures:\n"
+		for (var i=0; i < this.revocationSignatures.length; i++) {
+			result += "    "+this.revocationSignatures[i].toString(); 
+		}
+		result += "    User Ids:\n";
+		for (var i=0; i < this.userIds.length; i++) {
+			result += "    "+this.userIds[i].toString(); 
+		}
+		result += "    User Attributes:\n";
+		for (var i=0; i < this.userAttributes.length; i++) {
+			result += "    "+this.userAttributes[i].toString(); 
+		}
+		result += "    Public Key SubKeys:\n";
+		for (var i=0; i < this.subKeys.length; i++) {
+			result += "    "+this.subKeys[i].toString(); 
+		}
+		return result;
+	}
+	
+	/**
+	 * finds an encryption key for this public key
+	 * @returns null if no encryption key has been found
+	 */
+	function getEncryptionKey() {
+		if (this.publicKeyPacket.publicKeyAlgorithm != 17 && this.publicKeyPacket.publicKeyAlgorithm != 3
+				&& this.publicKeyPacket.verifyKey())
+			return this.publicKeyPacket;
+		else if (this.publicKeyPacket.version == 4) // V3 keys MUST NOT have subkeys.
+			for (var j = 0; j < this.subKeys.length; j++)
+				if (this.subKeys[j].publicKeyAlgorithm != 17 &&
+						this.subKeys[j].publicKeyAlgorithm != 3 &&
+						this.subKeys[j].verifyKey()) {
+					return this.subKeys[j];
+				}
+		return null;
+	}
+	
+	function getSigningKey() {
+		if ((this.publicKeyPacket.publicKeyAlgorithm == 17 ||
+			 this.publicKeyPacket.publicKeyAlgorithm != 2))
+			return this.publicKeyPacket;
+		else if (this.publicKeyPacket.version == 4) // V3 keys MUST NOT have subkeys.
+			for (var j = 0; j < this.subKeys.length; j++) {
+				if ((this.subKeys[j].publicKeyAlgorithm == 17 ||
+					 this.subKeys[j].publicKeyAlgorithm != 2) &&
+					 this.subKeys[j].verifyKey())
+					return this.subKeys[j];
+			}
+		return null;
+	}
 
-	/**
-	 * convert an array of integers(0.255) to a string 
-	 * @param [Array [Integer 0..255]] array of (binary) integers to convert
-	 * @return [String] string representation of the array
-	 */
-	this.bin2str = function(bin) {
-		var result = [];
-		for (var i = 0; i < bin.length; i++) {
-			result.push(String.fromCharCode(bin[i]));
-		}
-		return result.join('');
-	};
-	
-	/**
-	 * convert a string to a Uint8Array
-	 * @param [String] string to convert
-	 * @return [Uint8Array] array of (binary) integers
-	 */
-	this.str2Uint8Array = function(str){
-        var uintArray = new Uint8Array(new ArrayBuffer(str.length));
-        for(var n = 0; n < str.length; n++){
-            uintArray[n] = str.charCodeAt(n);
-        }
-        return uintArray;
-	};
-	
-	/**
-	 * convert a Uint8Array to a string. This currently functions the same as bin2str. 
-	 * @param [Uint8Array] array of (binary) integers to convert
-	 * @return [String] string representation of the array
-	 */
-	this.Uint8Array2str = function(bin) {
-        var result = [];
-        for(n = 0; n< bin.length; n++){
-            result[n] = String.fromCharCode(bin[n]);
-        }
-        return result.join('');
-	};
-	
-	/**
-	 * calculates a 16bit sum of a string by adding each character codes modulus 65535
-	 * @param text [String] string to create a sum of
-	 * @return [Integer] an integer containing the sum of all character codes % 65535
-	 */
-	this.calc_checksum = function(text) {
-		var checksum = {  s: 0, add: function (sadd) { this.s = (this.s + sadd) % 65536; }};
-		for (var i = 0; i < text.length; i++) {
-			checksum.add(text.charCodeAt(i));
-		}
-		return checksum.s;
-	};
-	
-	/**
-	 * Helper function to print a debug message. Debug 
-	 * messages are only printed if
-	 * openpgp.config.debug is set to true. The calling
-	 * Javascript context MUST define
-	 * a "showMessages(text)" function. Line feeds ('\n')
-	 * are automatically converted to HTML line feeds '<br/>'
-	 * @param str [String] string of the debug message
-	 * @return [String] an HTML tt entity containing a paragraph with a style attribute where the debug message is HTMLencoded in. 
-	 */
-	this.print_debug = function(str) {
-		if (openpgp.config.debug) {
-			str = openpgp_encoding_html_encode(str);
-			showMessages("<tt><p style=\"background-color: #ffffff; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;\">"+str.replace(/\n/g,"<br>")+"</p></tt>");
-		}
-	};
-	
-	/**
-	 * Helper function to print a debug message. Debug 
-	 * messages are only printed if
-	 * openpgp.config.debug is set to true. The calling
-	 * Javascript context MUST define
-	 * a "showMessages(text)" function. Line feeds ('\n')
-	 * are automatically converted to HTML line feeds '<br/>'
-	 * Different than print_debug because will call hexstrdump iff necessary.
-	 * @param str [String] string of the debug message
-	 * @return [String] an HTML tt entity containing a paragraph with a style attribute where the debug message is HTMLencoded in. 
-	 */
-	this.print_debug_hexstr_dump = function(str,strToHex) {
-		if (openpgp.config.debug) {
-			str = str + this.hexstrdump(strToHex);
-			str = openpgp_encoding_html_encode(str);
-			showMessages("<tt><p style=\"background-color: #ffffff; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;\">"+str.replace(/\n/g,"<br>")+"</p></tt>");
-		}
-	};
-	
-	/**
-	 * Helper function to print an error message. 
-	 * The calling Javascript context MUST define
-	 * a "showMessages(text)" function. Line feeds ('\n')
-	 * are automatically converted to HTML line feeds '<br/>'
-	 * @param str [String] string of the error message
-	 * @return [String] a HTML paragraph entity with a style attribute containing the HTML encoded error message
-	 */
-	this.print_error = function(str) {
-		str = openpgp_encoding_html_encode(str);
-		showMessages("<p style=\"font-size: 80%; background-color: #FF8888; margin:0; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;\"><span style=\"color: #888;\"><b>ERROR:</b></span>	"+str.replace(/\n/g,"<br>")+"</p>");
-	};
-	
-	/**
-	 * Helper function to print an info message. 
-	 * The calling Javascript context MUST define
-	 * a "showMessages(text)" function. Line feeds ('\n')
-	 * are automatically converted to HTML line feeds '<br/>'.
-	 * @param str [String] string of the info message
-	 * @return [String] a HTML paragraph entity with a style attribute containing the HTML encoded info message
-	 */
-	this.print_info = function(str) {
-		str = openpgp_encoding_html_encode(str);
-		showMessages("<p style=\"font-size: 80%; background-color: #88FF88; margin:0; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;\"><span style=\"color: #888;\"><b>INFO:</b></span>	"+str.replace(/\n/g,"<br>")+"</p>");
-	};
-	
-	this.print_warning = function(str) {
-		str = openpgp_encoding_html_encode(str);
-		showMessages("<p style=\"font-size: 80%; background-color: #FFAA88; margin:0; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;\"><span style=\"color: #888;\"><b>WARNING:</b></span>	"+str.replace(/\n/g,"<br>")+"</p>");
-	};
-	
-	this.getLeftNBits = function (string, bitcount) {
-		var rest = bitcount % 8;
-		if (rest == 0)
-			return string.substring(0, bitcount / 8);
-		var bytes = (bitcount - rest) / 8 +1;
-		var result = string.substring(0, bytes);
-		return this.shiftRight(result, 8-rest); // +String.fromCharCode(string.charCodeAt(bytes -1) << (8-rest) & 0xFF);
-	};
-	/**
-	 * Shifting a string to n bits right
-	 * @param value [String] the string to shift
-	 * @param bitcount [Integer] amount of bits to shift (MUST be smaller than 9)
-	 * @return [String] resulting string. 
-	 */
-	this.shiftRight = function(value, bitcount) {
-		var temp = util.str2bin(value);
-        if (bitcount % 8 != 0) {
-        	for (var i = temp.length-1; i >= 0; i--) {
-        		temp[i] >>= bitcount % 8;
-        		if (i > 0)
-        			temp[i] |= (temp[i - 1] << (8 - (bitcount % 8))) & 0xFF;
-        	}
-        } else {
-        	return value;
-        }
-        return util.bin2str(temp);
-	};
-	
-	/**
-	 * Return the algorithm type as string
-	 * @return [String] String representing the message type
-	 */
-	this.get_hashAlgorithmString = function(algo) {
-		switch(algo) {
-		case 1:
-			return "MD5";
-		case 2:
-			return "SHA1";
-		case 3:
-			return "RIPEMD160";
-		case 8:
-			return "SHA256";
-		case 9:
-			return "SHA384";
-		case 10:
-			return "SHA512";
-		case 11:
-			return "SHA224";
-		}
-		return "unknown";
-	};
-};
+	this.getEncryptionKey = getEncryptionKey;
+	this.getSigningKey = getSigningKey;
+	this.read_nodes = read_nodes;
+	this.write = write;
+	this.toString = toString;
+	this.validate = validate;
+	this.getFingerprint = getFingerprint;
+	this.getKeyId = getKeyId;
+	this.verifyBasicSignatures = verifyBasicSignatures;
+}
+// GPG4Browsers - An OpenPGP implementation in javascript
+// Copyright (C) 2011 Recurity Labs GmbH
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
 /**
- * an instance that should be used. 
+ * Wrapper function for the base64 codec. 
+ * This function encodes a String (message) in base64 (radix-64)
+ * @param message [String] the message to encode
+ * @return [String] the base64 encoded data
  */
-var util = new Util();
+function openpgp_encoding_base64_encode(message) {
+	return s2r(message);
+}
+
+
+/**
+ * Wrapper function for the base64 codec.
+ * This function decodes a String(message) in base64 (radix-64)
+ * @param message [String] base64 encoded data
+ * @return [String] raw data after decoding
+ */
+function openpgp_encoding_base64_decode(message) {
+	return r2s(message);
+}
+
+/**
+ * Wrapper function for jquery library.
+ * This function escapes HTML characters within a string. This is used to prevent XSS.
+ * @param message [String] message to escape
+ * @return [String] html encoded string
+ */
+function openpgp_encoding_html_encode(message) {
+	if (message == null)
+		return "";
+	return $('<div/>').text(message).html();
+}
+
+/**
+ * create a EME-PKCS1-v1_5 padding (See RFC4880 13.1.1)
+ * @param message [String] message to be padded
+ * @param length [Integer] length to the resulting message
+ * @return [String] EME-PKCS1 padded message
+ */
+function openpgp_encoding_eme_pkcs1_encode(message, length) {
+	if (message.length > length-11)
+		return -1;
+	var result = "";
+	result += String.fromCharCode(0);
+	result += String.fromCharCode(2);
+	for (var i = 0; i < length - message.length - 3; i++) {
+		result += String.fromCharCode(openpgp_crypto_getPseudoRandom(1,255));
+	}
+	result += String.fromCharCode(0);
+	result += message;
+	return result;
+}
+
+/**
+ * decodes a EME-PKCS1-v1_5 padding (See RFC4880 13.1.2)
+ * @param message [String] EME-PKCS1 padded message
+ * @return [String] decoded message 
+ */
+function openpgp_encoding_eme_pkcs1_decode(message, len) {
+	if (message.length < len)
+	    message = String.fromCharCode(0)+message;
+	if (message.length < 12 || message.charCodeAt(0) != 0 || message.charCodeAt(1) != 2)
+		return -1;
+	var i = 2;
+	while (message.charCodeAt(i) != 0 && message.length > i)
+	    i++;
+	return message.substring(i+1, message.length);
+}
+/**
+ * ASN1 object identifiers for hashes (See RFC4880 5.2.2)
+ */
+hash_headers = new Array();
+hash_headers[1]  = [0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x04,0x10];
+hash_headers[3]  = [0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x24,0x03,0x02,0x01,0x05,0x00,0x04,0x14];
+hash_headers[2]  = [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14];
+hash_headers[8]  = [0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20];
+hash_headers[9]  = [0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30];
+hash_headers[10] = [0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40];
+hash_headers[11] = [0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04,0x05,0x00,0x04,0x1C];
+
+/**
+ * create a EMSA-PKCS1-v1_5 padding (See RFC4880 13.1.3)
+ * @param algo [Integer] hash algorithm type used
+ * @param data [String] data to be hashed
+ * @param keylength [Integer] key size of the public mpi in bytes
+ * @return the [String] hashcode with pkcs1padding as string
+ */
+function openpgp_encoding_emsa_pkcs1_encode(algo, data, keylength) {
+	var data2 = "";
+	data2 += String.fromCharCode(0x00);
+	data2 += String.fromCharCode(0x01);
+	for (var i = 0; i < (keylength - hash_headers[algo].length - 3 - openpgp_crypto_getHashByteLength(algo)); i++)
+		data2 += String.fromCharCode(0xff);
+	data2 += String.fromCharCode(0x00);
+	
+	for (var i = 0; i < hash_headers[algo].length; i++)
+		data2 += String.fromCharCode(hash_headers[algo][i]);
+	
+	data2 += openpgp_crypto_hashData(algo, data);
+	return new BigInteger(util.hexstrdump(data2),16);
+}
+
+/**
+ * extract the hash out of an EMSA-PKCS1-v1.5 padding (See RFC4880 13.1.3) 
+ * @param data [String] hash in pkcs1 encoding
+ * @return the hash as string
+ */
+function openpgp_encoding_emsa_pkcs1_decode(algo, data) { 
+	var i = 0;
+	if (data.charCodeAt(0) == 0) i++;
+	else if (data.charCodeAt(0) != 1) return -1;
+	else i++;
+
+	while (data.charCodeAt(i) == 0xFF) i++;
+	if (data.charCodeAt(i++) != 0) return -1;
+	var j = 0;
+	for (j = 0; j < hash_headers[algo].length && j+i < data.length; j++) {
+		if (data.charCodeAt(j+i) != hash_headers[algo][j]) return -1;
+	}
+	i+= j;	
+	if (data.substring(i).length < openpgp_crypto_getHashByteLength(algo)) return -1;
+	return data.substring(i);
+}/* OpenPGP radix-64/base64 string encoding/decoding
+ * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de
+ * version 1.0, check www.haneWIN.de for the latest version
+ *
+ * This software is provided as-is, without express or implied warranty.  
+ * Permission to use, copy, modify, distribute or sell this software, with or
+ * without fee, for any purpose and by any individual or organization, is hereby
+ * granted, provided that the above copyright notice and this paragraph appear 
+ * in all copies. Distribution as a part of an application or binary must
+ * include the above copyright notice in the documentation and/or other materials
+ * provided with the application or distribution.
+ */
+
+var b64s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+
+function s2r(t) {
+	var a, c, n;
+	var r = '', l = 0, s = 0;
+	var tl = t.length;
+
+	for (n = 0; n < tl; n++) {
+		c = t.charCodeAt(n);
+		if (s == 0) {
+			r += b64s.charAt((c >> 2) & 63);
+			a = (c & 3) << 4;
+		} else if (s == 1) {
+			r += b64s.charAt((a | (c >> 4) & 15));
+			a = (c & 15) << 2;
+		} else if (s == 2) {
+			r += b64s.charAt(a | ((c >> 6) & 3));
+			l += 1;
+			if ((l % 60) == 0)
+				r += "\n";
+			r += b64s.charAt(c & 63);
+		}
+		l += 1;
+		if ((l % 60) == 0)
+			r += "\n";
+
+		s += 1;
+		if (s == 3)
+			s = 0;
+	}
+	if (s > 0) {
+		r += b64s.charAt(a);
+		l += 1;
+		if ((l % 60) == 0)
+			r += "\n";
+		r += '=';
+		l += 1;
+	}
+	if (s == 1) {
+		if ((l % 60) == 0)
+			r += "\n";
+		r += '=';
+	}
+
+	return r;
+}
+
+function r2s(t) {
+	var c, n;
+	var r = '', s = 0, a = 0;
+	var tl = t.length;
+
+	for (n = 0; n < tl; n++) {
+		c = b64s.indexOf(t.charAt(n));
+		if (c >= 0) {
+			if (s)
+				r += String.fromCharCode(a | (c >> (6 - s)) & 255);
+			s = (s + 2) & 7;
+			a = (c << s) & 255;
+		}
+	}
+	return r;
+}
+// GPG4Browsers - An OpenPGP implementation in javascript
+// Copyright (C) 2011 Recurity Labs GmbH
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+/**
+ * DeArmor an OpenPGP armored message; verify the checksum and return the encoded bytes
+ * @text [String] OpenPGP armored message
+ * @return either the bytes of the decoded message or an object with attribute "text" containing the message text
+ * and an attribute "openpgp" containing the bytes.
+ */
+function openpgp_encoding_deArmor(text) {
+	var type = getPGPMessageType(text);
+	if (type != 2) {
+	var splittedtext = text.split('-----');
+	data = { openpgp: openpgp_encoding_base64_decode(splittedtext[2].split('\n\n')[1].split("\n=")[0].replace(/\n- /g,"\n")),
+			type: type};
+	if (verifyCheckSum(data.openpgp, splittedtext[2].split('\n\n')[1].split("\n=")[1].split('\n')[0]))
+		return data;
+	else
+		util.print_error("Ascii armor integrity check on message failed: '"+splittedtext[2].split('\n\n')[1].split("\n=")[1].split('\n')[0]+"' should be '"+getCheckSum(data))+"'";
+	} else {
+		var splittedtext = text.split('-----');
+		var result = { text: splittedtext[2].replace(/\n- /g,"\n").split("\n\n")[1],
+		               openpgp: openpgp_encoding_base64_decode(splittedtext[4].split("\n\n")[1].split("\n=")[0]),
+		               type: type};
+		if (verifyCheckSum(result.openpgp, splittedtext[4].split("\n\n")[1].split("\n=")[1]))
+				return result;
+		else
+			util.print_error("Ascii armor integrity check on message failed");
+	}
+}
+
+/**
+ * Finds out which Ascii Armoring type is used. This is an internal function
+ * @param text [String] ascii armored text
+ * @return 0 = MESSAGE PART n of m
+ *         1 = MESSAGE PART n
+ *         2 = SIGNED MESSAGE
+ *         3 = PGP MESSAGE
+ *         4 = PUBLIC KEY BLOCK
+ *         5 = PRIVATE KEY BLOCK
+ *         null = unknown
+ */
+function getPGPMessageType(text) {
+	var splittedtext = text.split('-----');
+	// BEGIN PGP MESSAGE, PART X/Y
+	// Used for multi-part messages, where the armor is split amongst Y
+	// parts, and this is the Xth part out of Y.
+	if (splittedtext[1].match(/BEGIN PGP MESSAGE, PART \d+\/\d+/)) {
+		return 0;
+	} else
+		// BEGIN PGP MESSAGE, PART X
+		// Used for multi-part messages, where this is the Xth part of an
+		// unspecified number of parts. Requires the MESSAGE-ID Armor
+		// Header to be used.
+	if (splittedtext[1].match(/BEGIN PGP MESSAGE, PART \d+/)) {
+		return 1;
+
+	} else
+		// BEGIN PGP SIGNATURE
+		// Used for detached signatures, OpenPGP/MIME signatures, and
+		// cleartext signatures. Note that PGP 2.x uses BEGIN PGP MESSAGE
+		// for detached signatures.
+	if (splittedtext[1].match(/BEGIN PGP SIGNED MESSAGE/)) {
+		return 2;
+
+	} else
+  	    // BEGIN PGP MESSAGE
+	    // Used for signed, encrypted, or compressed files.
+	if (splittedtext[1].match(/BEGIN PGP MESSAGE/)) {
+		return 3;
+
+	} else
+		// BEGIN PGP PUBLIC KEY BLOCK
+		// Used for armoring public keys.
+	if (splittedtext[1].match(/BEGIN PGP PUBLIC KEY BLOCK/)) {
+		return 4;
+
+	} else
+		// BEGIN PGP PRIVATE KEY BLOCK
+		// Used for armoring private keys.
+	if (splittedtext[1].match(/BEGIN PGP PRIVATE KEY BLOCK/)) {
+		return 5;
+	}
+}
+
+/**
+ * Add additional information to the armor version of an OpenPGP binary
+ * packet block.
+ * @author  Alex
+ * @version 2011-12-16
+ * @return  The header information
+ */
+function openpgp_encoding_armor_addheader() {
+    var result = "";
+	if (openpgp.config.config.show_version) {
+        result += "Version: "+openpgp.config.versionstring+'\r\n';
+    }
+	if (openpgp.config.config.show_comment) {
+        result += "Comment: "+openpgp.config.commentstring+'\r\n';
+    }
+    result += '\r\n';
+    return result;
+}
+
+/**
+ * Armor an OpenPGP binary packet block
+ * @param messagetype type of the message
+ * @param data
+ * @param partindex
+ * @param parttotal
+ * @return {string} Armored text
+ */
+function openpgp_encoding_armor(messagetype, data, partindex, parttotal) {
+	var result = "";
+	switch(messagetype) {
+	case 0:
+		result += "-----BEGIN PGP MESSAGE, PART "+partindex+"/"+parttotal+"-----\r\n";
+		result += openpgp_encoding_armor_addheader();
+		result += openpgp_encoding_base64_encode(data);
+		result += "\r\n="+getCheckSum(data)+"\r\n";
+		result += "-----END PGP MESSAGE, PART "+partindex+"/"+parttotal+"-----\r\n";
+		break;
+	case 1:
+		result += "-----BEGIN PGP MESSAGE, PART "+partindex+"-----\r\n";
+		result += openpgp_encoding_armor_addheader();
+		result += openpgp_encoding_base64_encode(data);
+		result += "\r\n="+getCheckSum(data)+"\r\n";
+		result += "-----END PGP MESSAGE, PART "+partindex+"-----\r\n";
+		break;
+	case 2:
+		result += "\r\n-----BEGIN PGP SIGNED MESSAGE-----\r\nHash: "+data.hash+"\r\n\r\n";
+		result += data.text.replace(/\n-/g,"\n- -");
+		result += "\r\n-----BEGIN PGP SIGNATURE-----\r\n";
+		result += openpgp_encoding_armor_addheader();
+		result += openpgp_encoding_base64_encode(data.openpgp);
+		result += "\r\n="+getCheckSum(data.openpgp)+"\r\n";
+		result += "-----END PGP SIGNATURE-----\r\n";
+		break;
+	case 3:
+		result += "-----BEGIN PGP MESSAGE-----\r\n";
+		result += openpgp_encoding_armor_addheader();
+		result += openpgp_encoding_base64_encode(data);
+		result += "\r\n="+getCheckSum(data)+"\r\n";
+		result += "-----END PGP MESSAGE-----\r\n";
+		break;
+	case 4:
+		result += "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n";
+		result += openpgp_encoding_armor_addheader();
+		result += openpgp_encoding_base64_encode(data);
+		result += "\r\n="+getCheckSum(data)+"\r\n";
+		result += "-----END PGP PUBLIC KEY BLOCK-----\r\n\r\n";
+		break;
+	case 5:
+		result += "-----BEGIN PGP PRIVATE KEY BLOCK-----\r\n";
+		result += openpgp_encoding_armor_addheader();
+		result += openpgp_encoding_base64_encode(data);
+		result += "\r\n="+getCheckSum(data)+"\r\n";
+		result += "-----END PGP PRIVATE KEY BLOCK-----\r\n";
+		break;
+	}
+
+	return result;
+}
+
+/**
+ * Calculates a checksum over the given data and returns it base64 encoded
+ * @param data [String] data to create a CRC-24 checksum for
+ * @return [String] base64 encoded checksum
+ */
+function getCheckSum(data) {
+	var c = createcrc24(data);
+	var str = "" + String.fromCharCode(c >> 16)+
+				   String.fromCharCode((c >> 8) & 0xFF)+
+				   String.fromCharCode(c & 0xFF);
+	return openpgp_encoding_base64_encode(str);
+}
+
+/**
+ * Calculates the checksum over the given data and compares it with the given base64 encoded checksum
+ * @param data [String] data to create a CRC-24 checksum for
+ * @param checksum [String] base64 encoded checksum
+ * @return true if the given checksum is correct; otherwise false
+ */
+function verifyCheckSum(data, checksum) {
+	var c = getCheckSum(data);
+	var d = checksum;
+	return c[0] == d[0] && c[1] == d[1] && c[2] == d[2];
+}
+/**
+ * Internal function to calculate a CRC-24 checksum over a given string (data)
+ * @param data [String] data to create a CRC-24 checksum for
+ * @return [Integer] the CRC-24 checksum as number
+ */
+var crc_table = [
+0x00000000, 0x00864cfb, 0x018ad50d, 0x010c99f6, 0x0393e6e1, 0x0315aa1a, 0x021933ec, 0x029f7f17, 0x07a18139, 0x0727cdc2, 0x062b5434, 0x06ad18cf, 0x043267d8, 0x04b42b23, 0x05b8b2d5, 0x053efe2e, 0x0fc54e89, 0x0f430272, 0x0e4f9b84, 0x0ec9d77f, 0x0c56a868, 0x0cd0e493, 0x0ddc7d65, 0x0d5a319e, 0x0864cfb0, 0x08e2834b, 0x09ee1abd, 0x09685646, 0x0bf72951, 0x0b7165aa, 0x0a7dfc5c, 0x0afbb0a7, 0x1f0cd1e9, 0x1f8a9d12, 0x1e8604e4, 0x1e00481f, 0x1c9f3708, 0x1c197bf3, 0x1d15e205, 0x1d93aefe, 0x18ad50d0, 0x182b1c2b, 0x192785dd, 0x19a1c926, 0x1b3eb631, 0x1bb8faca, 0x1ab4633c, 0x1a322fc7, 0x10c99f60, 0x104fd39b, 0x11434a6d, 0x11c50696, 0x135a7981, 0x13dc357a, 0x12d0ac8c, 0x1256e077, 0x17681e59, 0x17ee52a2, 0x16e2cb54, 0x166487af, 0x14fbf8b8, 0x147db443, 0x15712db5, 0x15f7614e, 0x3e19a3d2, 0x3e9fef29, 0x3f9376df, 0x3f153a24, 0x3d8a4533, 0x3d0c09c8, 0x3c00903e, 0x3c86dcc5, 0x39b822eb, 0x393e6e10, 0x3832f7e6, 0x38b4bb1d, 0x3a2bc40a, 0x3aad88f1, 0x3ba11107, 0x3b275dfc, 0x31dced5b, 0x315aa1a0,
+0x30563856, 0x30d074ad, 0x324f0bba, 0x32c94741, 0x33c5deb7, 0x3343924c, 0x367d6c62, 0x36fb2099, 0x37f7b96f, 0x3771f594, 0x35ee8a83, 0x3568c678, 0x34645f8e, 0x34e21375, 0x2115723b, 0x21933ec0, 0x209fa736, 0x2019ebcd, 0x228694da, 0x2200d821, 0x230c41d7, 0x238a0d2c, 0x26b4f302, 0x2632bff9, 0x273e260f, 0x27b86af4, 0x252715e3, 0x25a15918, 0x24adc0ee, 0x242b8c15, 0x2ed03cb2, 0x2e567049, 0x2f5ae9bf, 0x2fdca544, 0x2d43da53, 0x2dc596a8, 0x2cc90f5e, 0x2c4f43a5, 0x2971bd8b, 0x29f7f170, 0x28fb6886, 0x287d247d, 0x2ae25b6a, 0x2a641791, 0x2b688e67, 0x2beec29c, 0x7c3347a4, 0x7cb50b5f, 0x7db992a9, 0x7d3fde52, 0x7fa0a145, 0x7f26edbe, 0x7e2a7448, 0x7eac38b3, 0x7b92c69d, 0x7b148a66, 0x7a181390, 0x7a9e5f6b, 0x7801207c, 0x78876c87, 0x798bf571, 0x790db98a, 0x73f6092d, 0x737045d6, 0x727cdc20, 0x72fa90db, 0x7065efcc, 0x70e3a337, 0x71ef3ac1, 0x7169763a, 0x74578814, 0x74d1c4ef, 0x75dd5d19, 0x755b11e2, 0x77c46ef5, 0x7742220e, 0x764ebbf8, 0x76c8f703, 0x633f964d, 0x63b9dab6, 0x62b54340, 0x62330fbb,
+0x60ac70ac, 0x602a3c57, 0x6126a5a1, 0x61a0e95a, 0x649e1774, 0x64185b8f, 0x6514c279, 0x65928e82, 0x670df195, 0x678bbd6e, 0x66872498, 0x66016863, 0x6cfad8c4, 0x6c7c943f, 0x6d700dc9, 0x6df64132, 0x6f693e25, 0x6fef72de, 0x6ee3eb28, 0x6e65a7d3, 0x6b5b59fd, 0x6bdd1506, 0x6ad18cf0, 0x6a57c00b, 0x68c8bf1c, 0x684ef3e7, 0x69426a11, 0x69c426ea, 0x422ae476, 0x42aca88d, 0x43a0317b, 0x43267d80, 0x41b90297, 0x413f4e6c, 0x4033d79a, 0x40b59b61, 0x458b654f, 0x450d29b4, 0x4401b042, 0x4487fcb9, 0x461883ae, 0x469ecf55, 0x479256a3, 0x47141a58, 0x4defaaff, 0x4d69e604, 0x4c657ff2, 0x4ce33309, 0x4e7c4c1e, 0x4efa00e5, 0x4ff69913, 0x4f70d5e8, 0x4a4e2bc6, 0x4ac8673d, 0x4bc4fecb, 0x4b42b230, 0x49ddcd27, 0x495b81dc, 0x4857182a, 0x48d154d1, 0x5d26359f, 0x5da07964, 0x5cace092, 0x5c2aac69, 0x5eb5d37e, 0x5e339f85, 0x5f3f0673, 0x5fb94a88, 0x5a87b4a6, 0x5a01f85d, 0x5b0d61ab, 0x5b8b2d50, 0x59145247, 0x59921ebc, 0x589e874a, 0x5818cbb1, 0x52e37b16, 0x526537ed, 0x5369ae1b, 0x53efe2e0, 0x51709df7, 0x51f6d10c,
+0x50fa48fa, 0x507c0401, 0x5542fa2f, 0x55c4b6d4, 0x54c82f22, 0x544e63d9, 0x56d11cce, 0x56575035, 0x575bc9c3, 0x57dd8538];
+
+function createcrc24(input) {
+  var crc = 0xB704CE;
+  var index = 0;
+
+  while((input.length - index) > 16)  {
+   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index)) & 0xff];
+   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+1)) & 0xff];
+   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+2)) & 0xff];
+   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+3)) & 0xff];
+   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+4)) & 0xff];
+   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+5)) & 0xff];
+   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+6)) & 0xff];
+   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+7)) & 0xff];
+   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+8)) & 0xff];
+   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+9)) & 0xff];
+   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+10)) & 0xff];
+   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+11)) & 0xff];
+   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+12)) & 0xff];
+   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+13)) & 0xff];
+   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+14)) & 0xff];
+   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+15)) & 0xff];
+   index += 16;
+  }
+
+  for(var j = index; j < input.length; j++) {
+   crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index++)) & 0xff]
+  }
+  return crc & 0xffffff;
+}
+
diff --git a/resources/openpgp.min.js b/resources/openpgp.min.js
index 7c47b5c6..258df823 100644
--- a/resources/openpgp.min.js
+++ b/resources/openpgp.min.js
@@ -1,19 +1,41 @@
-function openpgp_packet_onepasssignature(){this.tagType=4;this.flags=this.signingKeyId=this.publicKeyAlgorithm=this.hashAlgorithm=this.version=null;this.read_packet=function(a,b,c){this.packetLength=c;this.version=a.charCodeAt(b++);this.type=a.charCodeAt(b++);this.hashAlgorithm=a.charCodeAt(b++);this.publicKeyAlgorithm=a.charCodeAt(b++);this.signingKeyId=new openpgp_type_keyid;this.signingKeyId.read_packet(a,b);b+=8;this.flags=a.charCodeAt(b++);return this};this.toString=function(){return"5.4.  One-Pass Signature Packets (Tag 4)\n    length: "+
-this.packetLength+"\n    type:   "+this.type+"\n    keyID:  "+this.signingKeyId.toString()+"\n    hashA:  "+this.hashAlgorithm+"\n    pubKeyA:"+this.publicKeyAlgorithm+"\n    flags:  "+this.flags+"\n    version:"+this.version+"\n"};this.write_packet=function(a,b,c,d,e){d=""+openpgp_packet.write_packet_header(4,13);d+=String.fromCharCode(3);d+=String.fromCharCode(a);d+=String.fromCharCode(b);d+=String.fromCharCode(c.privateKeyPacket.publicKey.publicKeyAlgorithm);d+=c.getKeyId();return d=e?d+String.fromCharCode(0):
-d+String.fromCharCode(1)}}function openpgp_packet_marker(){this.tagType=10;this.read_packet=function(a,b){this.packetLength=3;return 80==a[b].charCodeAt()&&71==a[b+1].charCodeAt()&&80==a[b+2].charCodeAt()?this:null};this.toString=function(){return'5.8.  Marker Packet (Obsolete Literal Packet) (Tag 10)\n     packet reads: "PGP"\n'}}
+function _openpgp(){this.tostring="";this.generate_key_pair=function(a,b,c,d){var e=(new openpgp_packet_userid).write_packet(c),b=openpgp_crypto_generateKeyPair(a,b,d,openpgp.config.config.prefer_hash_algorithm,3),a=b.privateKey,f=(new openpgp_packet_keymaterial).read_priv_key(a.string,3,a.string.length);f.decryptSecretMPIs(d)||util.print_error("Issue creating key. Unable to read resulting private key");d=new openpgp_msg_privatekey;d.privateKeyPacket=f;d.getPreferredSignatureHashAlgorithm=function(){return openpgp.config.config.prefer_hash_algorithm};
+f=d.privateKeyPacket.publicKey.data;f=String.fromCharCode(153)+String.fromCharCode(f.length>>8&255)+String.fromCharCode(f.length&255)+f+String.fromCharCode(180)+String.fromCharCode(c.length>>24)+String.fromCharCode(c.length>>16&255)+String.fromCharCode(c.length>>8&255)+String.fromCharCode(c.length&255)+c;c=new openpgp_packet_signature;c=c.write_message_signature(16,f,d);b=openpgp_encoding_armor(4,b.publicKey.string+e+c.openpgp);e=openpgp_encoding_armor(5,a.string+e+c.openpgp);return{privateKey:d,
+privateKeyArmored:e,publicKeyArmored:b}};this.write_signed_message=function(a,b){var c=(new openpgp_packet_signature).write_message_signature(1,b.replace(/\r\n/g,"\n").replace(/\n/,"\r\n"),a),c={text:b.replace(/\r\n/g,"\n").replace(/\n/,"\r\n"),openpgp:c.openpgp,hash:c.hash};return openpgp_encoding_armor(2,c,null,null)};this.write_signed_and_encrypted_message=function(a,b,c){var d="",e=(new openpgp_packet_literaldata).write_packet(c.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"));util.print_debug_hexstr_dump("literal_packet: |"+
+e+"|\n",e);for(var f=0;f<b.length;f++){var g="",g=(new openpgp_packet_onepasssignature).write_packet(1,openpgp.config.config.prefer_hash_algorithm,a,!1);util.print_debug_hexstr_dump("onepasssigstr: |"+g+"|\n",g);var h=(new openpgp_packet_signature).write_message_signature(1,c.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"),a);util.print_debug_hexstr_dump("datasignature: |"+h.openpgp+"|\n",h.openpgp);d=0==f?g+e+h.openpgp:g+d+h.openpgp}util.print_debug_hexstr_dump("signed packet: |"+d+"|\n",d);a=openpgp_crypto_generateSessionKey(openpgp.config.config.encryption_cipher);
+c="";for(f=0;f<b.length;f++){e=b[f].getEncryptionKey();if(null==e)return util.print_error("no encryption key found! Key is for signing only."),null;c+=(new openpgp_packet_encryptedsessionkey).write_pub_key_packet(e.getKeyId(),e.MPIs,e.publicKeyAlgorithm,openpgp.config.config.encryption_cipher,a)}c=openpgp.config.config.integrity_protect?c+(new openpgp_packet_encryptedintegrityprotecteddata).write_packet(openpgp.config.config.encryption_cipher,a,d):c+(new openpgp_packet_encrypteddata).write_packet(openpgp.config.config.encryption_cipher,
+a,d);return openpgp_encoding_armor(3,c,null,null)};this.write_encrypted_message=function(a,b){var c="",c=(new openpgp_packet_literaldata).write_packet(b.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"));util.print_debug_hexstr_dump("literal_packet: |"+c+"|\n",c);for(var d=openpgp_crypto_generateSessionKey(openpgp.config.config.encryption_cipher),e="",f=0;f<a.length;f++){var g=a[f].getEncryptionKey();if(null==g)return util.print_error("no encryption key found! Key is for signing only."),null;e+=(new openpgp_packet_encryptedsessionkey).write_pub_key_packet(g.getKeyId(),
+g.MPIs,g.publicKeyAlgorithm,openpgp.config.config.encryption_cipher,d)}e=openpgp.config.config.integrity_protect?e+(new openpgp_packet_encryptedintegrityprotecteddata).write_packet(openpgp.config.config.encryption_cipher,d,c):e+(new openpgp_packet_encrypteddata).write_packet(openpgp.config.config.encryption_cipher,d,c);return openpgp_encoding_armor(3,e,null,null)};this.read_message=function(a){var b;try{b=openpgp_encoding_deArmor(a.replace(/\r/g,""))}catch(c){return util.print_error("no message found!"),
+null}for(var a=b.openpgp,d=[],e=0,f=0,g=a.length;f<a.length;){var h=openpgp_packet.read_packet(a,f,g);if(1==h.tagType||2==h.tagType&&16>h.signatureType||3==h.tagType||8==h.tagType||9==h.tagType||10==h.tagType||11==h.tagType||18==h.tagType||19==h.tagType)if(d[d.length]=new openpgp_msg_message,d[e].messagePacket=h,d[e].type=b.type,9==h.tagType||1==h.tagType||3==h.tagType||18==h.tagType)if(9==h.tagType){util.print_error("unexpected openpgp packet");break}else if(1==h.tagType){util.print_debug("session key found:\n "+
+h.toString());var k=!0;d[e].sessionKeys=[];for(var j=0;k;)d[e].sessionKeys[j]=h,f+=h.packetLength+h.headerLength,g-=h.packetLength+h.headerLength,h=openpgp_packet.read_packet(a,f,g),1!=h.tagType&&3!=h.tagType&&(k=!1),j++;18==h.tagType||9==h.tagType?(util.print_debug("encrypted data found:\n "+h.toString()),d[e].encryptedData=h,f+=h.packetLength+h.headerLength,g-=h.packetLength+h.headerLength,e++):util.print_debug("something is wrong: "+h.tagType)}else{if(18==h.tagType){util.print_debug("symmetric encrypted data");
+break}}else if(2==h.tagType&&3>h.signatureType){d[e].text=b.text;d[e].signature=h;break}else if(8==h.tagType){util.print_error("A directly compressed message is currently not supported");break}else if(10==h.tagType)d.length=0,f+=h.packetLength+h.headerLength,g-=h.packetLength+h.headerLength;else{if(11==h.tagType){util.print_error("A direct literal message is currently not supported.");break}}else return util.print_error("no message found!"),null}return d};this.read_publicKey=function(a){for(var b=
+0,c=[],d=0,a=openpgp_encoding_deArmor(a.replace(/\r/g,"")).openpgp,e=a.length;b!=a.length;){var f=openpgp_packet.read_packet(a,b,e);if(153==a[b].charCodeAt()||6==f.tagType)c[d]=new openpgp_msg_publickey,c[d].header=a.substring(b,b+3),153==a[b].charCodeAt()?(b++,e=a[b++].charCodeAt()<<8|a[b++].charCodeAt(),c[d].publicKeyPacket=new openpgp_packet_keymaterial,c[d].publicKeyPacket.header=c[d].header,c[d].publicKeyPacket.read_tag6(a,b,e),b+=c[d].publicKeyPacket.packetLength,b+=c[d].read_nodes(c[d].publicKeyPacket,
+a,b,a.length-b)):(c[d]=new openpgp_msg_publickey,c[d].publicKeyPacket=f,b+=f.headerLength+f.packetLength,b+=c[d].read_nodes(f,a,b,a.length-b));else return util.print_error("no public key found!"),null;c[d].data=a.substring(0,b);d++}return c};this.read_privateKey=function(a){for(var b=[],c=0,d=0,a=openpgp_encoding_deArmor(a.replace(/\r/g,"")).openpgp,e=a.length;d!=a.length;){var f=openpgp_packet.read_packet(a,d,e);if(5==f.tagType)b[b.length]=new openpgp_msg_privatekey,d+=f.headerLength+f.packetLength,
+d+=b[c].read_nodes(f,a,d,e);else return util.print_error("no block packet found!"),null;b[c].data=a.substring(0,d);c++}return b};this.init=function(){this.config=new openpgp_config;this.config.read();this.keyring=new openpgp_keyring;this.keyring.init()}}var openpgp=new _openpgp;
+function openpgp_packet_encryptedsessionkey(){this.read_pub_key_packet=function(a,b,c){this.tagType=1;this.packetLength=c;var d=b;if(10>c)return util.print_error("openpgp.packet.encryptedsessionkey.js\ninvalid length"),null;this.version=a[d++].charCodeAt();this.keyId=new openpgp_type_keyid;this.keyId.read_packet(a,d);d+=8;this.publicKeyAlgorithmUsed=a[d++].charCodeAt();switch(this.publicKeyAlgorithmUsed){case 1:case 2:this.MPIs=[];this.MPIs[0]=new openpgp_type_mpi;this.MPIs[0].read(a,d,d-b);break;
+case 16:this.MPIs=[];this.MPIs[0]=new openpgp_type_mpi;this.MPIs[0].read(a,d,d-b);d+=this.MPIs[0].packetLength;this.MPIs[1]=new openpgp_type_mpi;this.MPIs[1].read(a,d,d-b);break;default:util.print_error("openpgp.packet.encryptedsessionkey.js\nunknown public key packet algorithm type "+this.publicKeyAlgorithmType)}return this};this.read_symmetric_key_packet=function(a,b,c){this.tagType=3;var d=b;this.version=a[d++];this.symmetricKeyAlgorithmUsed=a[d++];this.s2k=new openpgp_type_s2k;this.s2k.read(a,
+d);if(s2k.s2kLength+d<c){this.encryptedSessionKey=[];for(b=d-b;b<c;b++)this.encryptedSessionKey[b]=a[d++]}return this};this.write_pub_key_packet=function(a,b,c,d,e){for(var f=String.fromCharCode(3),d=String.fromCharCode(d),d=d+e,e=util.calc_checksum(e),d=d+String.fromCharCode(e>>8&255),d=d+String.fromCharCode(e&255),f=f+a+String.fromCharCode(c),a=new openpgp_type_mpi,b=openpgp_crypto_asymetricEncrypt(c,b,a.create(openpgp_encoding_eme_pkcs1_encode(d,b[0].mpiByteLength))),c=0;c<b.length;c++)f+=b[c];
+return f=openpgp_packet.write_packet_header(1,f.length)+f};this.toString=function(){if(1==this.tagType){for(var a="5.1.  Public-Key Encrypted Session Key Packets (Tag 1)\n    KeyId:  "+this.keyId.toString()+"\n    length: "+this.packetLength+"\n    version:"+this.version+"\n    pubAlgUs:"+this.publicKeyAlgorithmUsed+"\n",b=0;b<this.MPIs.length;b++)a+=this.MPIs[b].toString();return a}return"5.3 Symmetric-Key Encrypted Session Key Packets (Tag 3)\n    KeyId:  "+this.keyId.toString()+"\n    length: "+
+this.packetLength+"\n    version:"+this.version+"\n    symKeyA:"+this.symmetricKeyAlgorithmUsed+"\n    s2k:    "+this.s2k+"\n"};this.decrypt=function(a,b){if(1==this.tagType){var c=openpgp_crypto_asymetricDecrypt(this.publicKeyAlgorithmUsed,b.publicKey.MPIs,b.secMPIs,this.MPIs).toMPI();c.charCodeAt(c.length-2);c.charCodeAt(c.length-1);var d=openpgp_encoding_eme_pkcs1_decode(c.substring(2,c.length-2),b.publicKey.MPIs[0].getByteLength()),c=d.substring(1),d=d.charCodeAt(0);return 18==a.encryptedData.tagType?
+a.encryptedData.decrypt(d,c):a.encryptedData.decrypt_sym(d,c)}if(3==this.tagType)return util.print_error("Symmetric encrypted sessionkey is not supported!"),null}}
+function openpgp_packet_userattribute(){this.tagType=17;this.certificationSignatures=[];this.certificationRevocationSignatures=[];this.revocationSignatures=[];this.parentNode=null;this.read_packet=function(a,b,c){var d=0;this.packetLength=c;this.userattributes=[];for(var e=b;c!=d;){var f=0;192>a[e].charCodeAt()?(packet_length=a[e++].charCodeAt(),f=1):192<=a[e].charCodeAt()&&224>a[e].charCodeAt()?(packet_length=(a[e++].charCodeAt()-192<<8)+a[e++].charCodeAt()+192,f=2):223<a[e].charCodeAt()&&255>a[e].charCodeAt()?
+(packet_length=1<<(a[e++].charCodeAt()&31),f=1):(f=5,e++,packet_length=a[e++].charCodeAt()<<24|a[e++].charCodeAt()<<16|a[e++].charCodeAt()<<8|a[e++].charCodeAt());a[e++].charCodeAt();packet_length--;f++;this.userattributes[0]=[];this.userattributes[0]=a.substring(e,e+packet_length);e+=packet_length;d+=f+packet_length}this.packetLength=e-b;return this};this.read_nodes=function(a,b,c,d){this.parentNode=a;for(var e=c,f=d;b.length!=e;){var g=openpgp_packet.read_packet(b,e,f);if(null==g){util.print_error("openpgp.packet.userattribute.js\n[user_attr] parsing ends here @:"+
+e+" l:"+f);break}else switch(g.tagType){case 2:15<g.signatureType&&20>g.signatureType?this.certificationSignatures[this.certificationSignatures.length]=g:32==g.signatureType&&(this.certificationRevocationSignatures[this.certificationRevocationSignatures.length]=g);e+=g.packetLength+g.headerLength;f=d-(e-c);break;default:return this.data=b,this.position=c-a.packetLength,this.len=e-c}}this.data=b;this.position=c-a.packetLength;return this.len=e-c};this.toString=function(){for(var a="5.12.  User Attribute Packet (Tag 17)\n    AttributePackets: (count = "+
+this.userattributes.length+")\n",b=0;b<this.userattributes.length;b++)a+="    ("+this.userattributes[b].length+") bytes: ["+util.hexidump(this.userattributes[b])+"]\n";return a}}
+function openpgp_packet_encrypteddata(){this.tagType=9;this.decryptedData=this.encryptedData=this.packetLength=null;this.decrypt_sym=function(a,b){this.decryptedData=openpgp_crypto_symmetricDecrypt(a,b,this.encryptedData,!0);util.print_debug("openpgp.packet.encryptedintegrityprotecteddata.js\ndata: "+util.hexstrdump(this.decryptedData));return this.decryptedData};this.toString=function(){return"5.7.  Symmetrically Encrypted Data Packet (Tag 9)\n    length:  "+this.packetLength+"\n    Used symmetric algorithm: "+
+this.algorithmType+"\n    encrypted data: Bytes ["+util.hexstrdump(this.encryptedData)+"]\n"};this.read_packet=function(a,b,c){this.packetLength=c;this.encryptedData=a.substring(b,b+c);return this};this.write_packet=function(a,b,c){a=""+openpgp_crypto_symmetricEncrypt(openpgp_crypto_getPrefixRandom(a),a,b,c,!0);return a=openpgp_packet.write_packet_header(9,a.length)+a}}
 function openpgp_packet_signature(){function a(b,a){var d;d=""+openpgp_packet.encode_length(a.length+1);d+=String.fromCharCode(b);return d+a}this.tagType=2;this.embeddedSignature=this.signatureTargetHash=this.signatureTargetHashAlgorithm=this.signatureTargetPublicKeyAlgorithm=this.reasonForRevocationString=this.reasonForRevocationFlag=this.signersUserId=this.keyFlags=this.policyURI=this.isPrimaryUserID=this.preferredKeyServer=this.keyServerPreferences=this.preferredCompressionAlgorithms=this.preferredHashAlgorithms=
 this.notationValue=this.notationName=this.notationFlags=this.issuerKeyId=this.revocationKeyFingerprint=this.revocationKeyAlgorithm=this.revocationKeyClass=this.preferredSymmetricAlgorithms=this.keyNeverExpires=this.keyExpirationTime=this.revocable=this.regular_expression=this.trustAmount=this.trustLevel=this.exportable=this.hashAlgorithm=this.publicKeyAlgorithm=this.MPIs=this.signedHashValue=this.signatureNeverExpires=this.signatureExpirationTime=this.signatureData=this.keyId=this.creationTime=this.signatureType=
 null;this._raw_read_signature_sub_packet=function(b,a,d){0>d&&util.print_debug("openpgp.packet.signature.js\n_raw_read_signature_sub_packet length < 0 @:"+a);var e=a,f=0;192>b[e].charCodeAt()?f=b[e++].charCodeAt():192<=b[e].charCodeAt()&&224>b[e].charCodeAt()?f=(b[e++].charCodeAt()-192<<8)+b[e++].charCodeAt()+192:223<b[e].charCodeAt()&&255>b[e].charCodeAt()?f=1<<(b[e++].charCodeAt()&31):255>b[e].charCodeAt()&&(e++,f=b[e++].charCodeAt()<<24|b[e++].charCodeAt()<<16|b[e++].charCodeAt()<<8|b[e++].charCodeAt());
-var h=b[e++].charCodeAt()&127;switch(h){case 2:this.creationTime=new Date(1E3*(b[e++].charCodeAt()<<24|b[e++].charCodeAt()<<16|b[e++].charCodeAt()<<8|b[e++].charCodeAt()));break;case 3:this.signatureExpirationTime=b[e++].charCodeAt()<<24|b[e++].charCodeAt()<<16|b[e++].charCodeAt()<<8|b[e++].charCodeAt();this.signatureNeverExpires=0==this.signature_expiration_time;break;case 4:this.exportable=1==b[e++].charCodeAt();break;case 5:this.trustLevel=b[e++].charCodeAt();this.trustAmount=b[e++].charCodeAt();
-break;case 6:this.regular_expression=new String;for(h=0;h<f-1;h++)this.regular_expression+=b[e++];break;case 7:this.revocable=1==b[e++].charCodeAt();break;case 9:this.keyExpirationTime=b[e++].charCodeAt()<<24|b[e++].charCodeAt()<<16|b[e++].charCodeAt()<<8|b[e++].charCodeAt();this.keyNeverExpires=0==this.keyExpirationTime;break;case 11:this.preferredSymmetricAlgorithms=[];for(h=0;h<f-1;h++)this.preferredSymmetricAlgorithms=b[e++].charCodeAt();break;case 12:this.revocationKeyClass=b[e++].charCodeAt();
-this.revocationKeyAlgorithm=b[e++].charCodeAt();this.revocationKeyFingerprint=[];for(h=0;20>h;h++)this.revocationKeyFingerprint=b[e++].charCodeAt();break;case 16:this.issuerKeyId=b.substring(e,e+8);e+=8;break;case 20:this.notationFlags=b[e++].charCodeAt()<<24|b[e++].charCodeAt()<<16|b[e++].charCodeAt()<<8|b[e++].charCodeAt();d=b[e++].charCodeAt()<<8|b[e++].charCodeAt();f=b[e++].charCodeAt()<<8|b[e++].charCodeAt();this.notationName="";for(h=0;h<d;h++)this.notationName+=b[e++];this.notationValue="";
-for(h=0;h<f;h++)this.notationValue+=b[e++];break;case 21:this.preferredHashAlgorithms=[];for(h=0;h<f-1;h++)this.preferredHashAlgorithms=b[e++].charCodeAt();break;case 22:this.preferredCompressionAlgorithms=[];for(h=0;h<f-1;h++)this.preferredCompressionAlgorithms=b[e++].charCodeAt();break;case 23:this.keyServerPreferences=[];for(h=0;h<f-1;h++)this.keyServerPreferences=b[e++].charCodeAt();break;case 24:this.preferredKeyServer=new String;for(h=0;h<f-1;h++)this.preferredKeyServer+=b[e++];break;case 25:this.isPrimaryUserID=
-0!=b[e++];break;case 26:this.policyURI=new String;for(h=0;h<f-1;h++)this.policyURI+=b[e++];break;case 27:this.keyFlags=[];for(h=0;h<f-1;h++)this.keyFlags=b[e++].charCodeAt();break;case 28:this.signersUserId=new String;for(h=0;h<f-1;h++)this.signersUserId+=b[e++];break;case 29:this.reasonForRevocationFlag=b[e++].charCodeAt();this.reasonForRevocationString=new String;for(h=0;h<f-2;h++)this.reasonForRevocationString+=b[e++];break;case 30:return f+1;case 31:this.signatureTargetPublicKeyAlgorithm=b[e++].charCodeAt();
-this.signatureTargetHashAlgorithm=b[e++].charCodeAt();f=0;switch(this.signatureTargetHashAlgorithm){case 1:case 2:f=20;break;case 3:case 8:case 9:case 10:case 11:break;default:return util.print_error("openpgp.packet.signature.js\nunknown signature target hash algorithm:"+this.signatureTargetHashAlgorithm),null}this.signatureTargetHash=[];for(h=0;h<f;h++)this.signatureTargetHash[h]=b[e++];case 32:return this.embeddedSignature=new openpgp_packet_signature,this.embeddedSignature.read_packet(b,e,d-(e-
-a)),e+this.embeddedSignature.packetLength-a;case 100:case 101:case 102:case 103:case 104:case 105:case 106:case 107:case 108:case 109:case 110:return util.print_error("openpgp.packet.signature.js\nprivate or experimental signature subpacket type "+h+" @:"+e+" subplen:"+f+" len:"+d),f+1;default:return util.print_error("openpgp.packet.signature.js\nunknown signature subpacket type "+h+" @:"+e+" subplen:"+f+" len:"+d),f+1}return e-a};this.getIssuerKey=function(){var b=null;if(4==this.version)b=openpgp.keyring.getPublicKeysForKeyId(this.issuerKeyId);
-else if(3==this.version)b=openpgp.keyring.getPublicKeysForKeyId(this.keyId);else return null;return 0==b.length?null:b[0]};this.getIssuer=function(){return 4==this.version?this.issuerKeyId:4==this.verions?this.keyId:null};this.write_message_signature=function(b,c,d){var e=d.privateKeyPacket.publicKey,f=d.getPreferredSignatureHashAlgorithm(),h=String.fromCharCode(4),h=h+String.fromCharCode(b),h=h+String.fromCharCode(e.publicKeyAlgorithm),h=h+String.fromCharCode(f),b=Math.round((new Date).getTime()/
-1E3),b=a(2,""+String.fromCharCode(b>>24&255)+String.fromCharCode(b>>16&255)+String.fromCharCode(b>>8&255)+String.fromCharCode(b&255)),g=a(16,d.getKeyId()),h=h+String.fromCharCode(b.length+g.length>>8&255),h=h+String.fromCharCode(b.length+g.length&255),h=h+b+g,b=""+String.fromCharCode(4),b=b+String.fromCharCode(255),b=b+String.fromCharCode(h.length>>24),b=b+String.fromCharCode(h.length>>16&255),b=b+String.fromCharCode(h.length>>8&255),b=b+String.fromCharCode(h.length&255),g=String.fromCharCode(0),
-g=g+String.fromCharCode(0),k=openpgp_crypto_hashData(f,c+h+b);util.print_debug("DSA Signature is calculated with:|"+c+h+b+"|\n"+util.hexstrdump(c+h+b)+"\n hash:"+util.hexstrdump(k));g+=k.charAt(0);g+=k.charAt(1);g+=openpgp_crypto_signData(f,d.privateKeyPacket.publicKey.publicKeyAlgorithm,e.MPIs,d.privateKeyPacket.secMPIs,c+h+b);return{openpgp:openpgp_packet.write_packet_header(2,(h+g).length)+h+g,hash:util.get_hashAlgorithmString(f)}};this.verify=function(b,a){switch(this.signatureType){case 0:if(4==
+var g=b[e++].charCodeAt()&127;switch(g){case 2:this.creationTime=new Date(1E3*(b[e++].charCodeAt()<<24|b[e++].charCodeAt()<<16|b[e++].charCodeAt()<<8|b[e++].charCodeAt()));break;case 3:this.signatureExpirationTime=b[e++].charCodeAt()<<24|b[e++].charCodeAt()<<16|b[e++].charCodeAt()<<8|b[e++].charCodeAt();this.signatureNeverExpires=0==this.signature_expiration_time;break;case 4:this.exportable=1==b[e++].charCodeAt();break;case 5:this.trustLevel=b[e++].charCodeAt();this.trustAmount=b[e++].charCodeAt();
+break;case 6:this.regular_expression=new String;for(g=0;g<f-1;g++)this.regular_expression+=b[e++];break;case 7:this.revocable=1==b[e++].charCodeAt();break;case 9:this.keyExpirationTime=b[e++].charCodeAt()<<24|b[e++].charCodeAt()<<16|b[e++].charCodeAt()<<8|b[e++].charCodeAt();this.keyNeverExpires=0==this.keyExpirationTime;break;case 11:this.preferredSymmetricAlgorithms=[];for(g=0;g<f-1;g++)this.preferredSymmetricAlgorithms=b[e++].charCodeAt();break;case 12:this.revocationKeyClass=b[e++].charCodeAt();
+this.revocationKeyAlgorithm=b[e++].charCodeAt();this.revocationKeyFingerprint=[];for(g=0;20>g;g++)this.revocationKeyFingerprint=b[e++].charCodeAt();break;case 16:this.issuerKeyId=b.substring(e,e+8);e+=8;break;case 20:this.notationFlags=b[e++].charCodeAt()<<24|b[e++].charCodeAt()<<16|b[e++].charCodeAt()<<8|b[e++].charCodeAt();d=b[e++].charCodeAt()<<8|b[e++].charCodeAt();f=b[e++].charCodeAt()<<8|b[e++].charCodeAt();this.notationName="";for(g=0;g<d;g++)this.notationName+=b[e++];this.notationValue="";
+for(g=0;g<f;g++)this.notationValue+=b[e++];break;case 21:this.preferredHashAlgorithms=[];for(g=0;g<f-1;g++)this.preferredHashAlgorithms=b[e++].charCodeAt();break;case 22:this.preferredCompressionAlgorithms=[];for(g=0;g<f-1;g++)this.preferredCompressionAlgorithms=b[e++].charCodeAt();break;case 23:this.keyServerPreferences=[];for(g=0;g<f-1;g++)this.keyServerPreferences=b[e++].charCodeAt();break;case 24:this.preferredKeyServer=new String;for(g=0;g<f-1;g++)this.preferredKeyServer+=b[e++];break;case 25:this.isPrimaryUserID=
+0!=b[e++];break;case 26:this.policyURI=new String;for(g=0;g<f-1;g++)this.policyURI+=b[e++];break;case 27:this.keyFlags=[];for(g=0;g<f-1;g++)this.keyFlags=b[e++].charCodeAt();break;case 28:this.signersUserId=new String;for(g=0;g<f-1;g++)this.signersUserId+=b[e++];break;case 29:this.reasonForRevocationFlag=b[e++].charCodeAt();this.reasonForRevocationString=new String;for(g=0;g<f-2;g++)this.reasonForRevocationString+=b[e++];break;case 30:return f+1;case 31:this.signatureTargetPublicKeyAlgorithm=b[e++].charCodeAt();
+this.signatureTargetHashAlgorithm=b[e++].charCodeAt();f=0;switch(this.signatureTargetHashAlgorithm){case 1:case 2:f=20;break;case 3:case 8:case 9:case 10:case 11:break;default:return util.print_error("openpgp.packet.signature.js\nunknown signature target hash algorithm:"+this.signatureTargetHashAlgorithm),null}this.signatureTargetHash=[];for(g=0;g<f;g++)this.signatureTargetHash[g]=b[e++];case 32:return this.embeddedSignature=new openpgp_packet_signature,this.embeddedSignature.read_packet(b,e,d-(e-
+a)),e+this.embeddedSignature.packetLength-a;case 100:case 101:case 102:case 103:case 104:case 105:case 106:case 107:case 108:case 109:case 110:return util.print_error("openpgp.packet.signature.js\nprivate or experimental signature subpacket type "+g+" @:"+e+" subplen:"+f+" len:"+d),f+1;default:return util.print_error("openpgp.packet.signature.js\nunknown signature subpacket type "+g+" @:"+e+" subplen:"+f+" len:"+d),f+1}return e-a};this.getIssuerKey=function(){var b=null;if(4==this.version)b=openpgp.keyring.getPublicKeysForKeyId(this.issuerKeyId);
+else if(3==this.version)b=openpgp.keyring.getPublicKeysForKeyId(this.keyId);else return null;return 0==b.length?null:b[0]};this.getIssuer=function(){return 4==this.version?this.issuerKeyId:4==this.verions?this.keyId:null};this.write_message_signature=function(b,c,d){var e=d.privateKeyPacket.publicKey,f=d.getPreferredSignatureHashAlgorithm(),g=String.fromCharCode(4),g=g+String.fromCharCode(b),g=g+String.fromCharCode(e.publicKeyAlgorithm),g=g+String.fromCharCode(f),b=Math.round((new Date).getTime()/
+1E3),b=a(2,""+String.fromCharCode(b>>24&255)+String.fromCharCode(b>>16&255)+String.fromCharCode(b>>8&255)+String.fromCharCode(b&255)),h=a(16,d.getKeyId()),g=g+String.fromCharCode(b.length+h.length>>8&255),g=g+String.fromCharCode(b.length+h.length&255),g=g+b+h,b=""+String.fromCharCode(4),b=b+String.fromCharCode(255),b=b+String.fromCharCode(g.length>>24),b=b+String.fromCharCode(g.length>>16&255),b=b+String.fromCharCode(g.length>>8&255),b=b+String.fromCharCode(g.length&255),h=String.fromCharCode(0),
+h=h+String.fromCharCode(0),k=openpgp_crypto_hashData(f,c+g+b);util.print_debug("DSA Signature is calculated with:|"+c+g+b+"|\n"+util.hexstrdump(c+g+b)+"\n hash:"+util.hexstrdump(k));h+=k.charAt(0);h+=k.charAt(1);h+=openpgp_crypto_signData(f,d.privateKeyPacket.publicKey.publicKeyAlgorithm,e.MPIs,d.privateKeyPacket.secMPIs,c+g+b);return{openpgp:openpgp_packet.write_packet_header(2,(g+h).length)+g+h,hash:util.get_hashAlgorithmString(f)}};this.verify=function(b,a){switch(this.signatureType){case 0:if(4==
 this.version){var d;d=""+String.fromCharCode(this.version);d+=String.fromCharCode(255);d+=String.fromCharCode(this.signatureData.length>>24);d+=String.fromCharCode(this.signatureData.length>>16&255);d+=String.fromCharCode(this.signatureData.length>>8&255);d+=String.fromCharCode(this.signatureData.length&255);return openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.MPIs,a.obj.publicKeyPacket.MPIs,b.substring(i)+this.signatureData+d)}if(3==this.version)return!1;case 1:if(4==
 this.version)return d=""+String.fromCharCode(this.version),d+=String.fromCharCode(255),d+=String.fromCharCode(this.signatureData.length>>24),d+=String.fromCharCode(this.signatureData.length>>16&255),d+=String.fromCharCode(this.signatureData.length>>8&255),d+=String.fromCharCode(this.signatureData.length&255),openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.MPIs,a.obj.publicKeyPacket.MPIs,b+this.signatureData+d);if(3==this.version)return!1;case 2:if(3==this.version)return!1;
 d=""+String.fromCharCode(this.version);d+=String.fromCharCode(255);d+=String.fromCharCode(this.signatureData.length>>24);d+=String.fromCharCode(this.signatureData.length>>16&255);d+=String.fromCharCode(this.signatureData.length>>8&255);d+=String.fromCharCode(this.signatureData.length&255);return openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.MPIs,a.obj.publicKeyPacket.MPIs,this.signatureData+d);case 16:case 17:case 18:case 19:case 48:return d=""+String.fromCharCode(this.version),
@@ -30,53 +52,6 @@ this.toString=function(){for(var b=3==this.version?"5.2. Signature Packet (Tag 2
 " "+this.keyNeverExpires+"\nPreferred Symmetric Algorithms     :"+this.preferredSymmetricAlgorithms+"\nRevocation Key\n   ( 1 octet of class,             :"+this.revocationKeyClass+"\n     1 octet of public-key ID,     :"+this.revocationKeyAlgorithm+"\n    20 octets of fingerprint)      :"+this.revocationKeyFingerprint+"\nIssuer                             :"+util.hexstrdump(this.issuerKeyId)+"\nPreferred Hash Algorithms          :"+this.preferredHashAlgorithms+"\nPreferred Compression Alg.         :"+
 this.preferredCompressionAlgorithms+"\nKey Server Preferences             :"+this.keyServerPreferences+"\nPreferred Key Server               :"+this.preferredKeyServer+"\nPrimary User ID                    :"+this.isPrimaryUserID+"\nPolicy URI                         :"+this.policyURI+"\nKey Flags                          :"+this.keyFlags+"\nSigner's User ID                   :"+this.signersUserId+"\nNotation                           :"+this.notationName+" = "+this.notationValue+"\nReason for Revocation\n      Flag                         :"+
 this.reasonForRevocationFlag+"\n      Reason                       :"+this.reasonForRevocationString+"\nMPI:\n",a=0;a<this.MPIs.length;a++)b+=this.MPIs[a].toString();return b}}
-function openpgp_packet_encryptedintegrityprotecteddata(){this.tagType=18;this.hash=this.decrytpedData=this.encryptedData=this.packetLength=this.version=null;this.write_packet=function(a,b,c){var d=openpgp_crypto_getPrefixRandom(a),e=d+d.charAt(d.length-2)+d.charAt(d.length-1),c=c+String.fromCharCode(211),c=c+String.fromCharCode(20);util.print_debug_hexstr_dump("data to be hashed:",e+c);c+=str_sha1(e+c);util.print_debug_hexstr_dump("hash:",c.substring(c.length-20,c.length));a=openpgp_crypto_symmetricEncrypt(d,
-a,b,c,!1).substring(0,e.length+c.length);b=openpgp_packet.write_packet_header(18,a.length+1)+String.fromCharCode(1);this.encryptedData=a;return b+a};this.read_packet=function(a,b,c){this.packetLength=c;this.version=a[b].charCodeAt();if(1!=this.version)return util.print_error("openpgp.packet.encryptedintegrityprotecteddata.js\nunknown encrypted integrity protected data packet version: "+this.version+" , @ "+b+"hex:"+util.hexstrdump(a)),null;this.encryptedData=a.substring(b+1,b+1+c);util.print_debug("openpgp.packet.encryptedintegrityprotecteddata.js\n"+
-this.toString());return this};this.toString=function(){var a="";openpgp.config.debug&&(a="    data: Bytes ["+util.hexstrdump(this.encryptedData)+"]");return"5.13.  Sym. Encrypted Integrity Protected Data Packet (Tag 18)\n    length:  "+this.packetLength+"\n    version: "+this.version+"\n"+a};this.decrypt=function(a,b){this.decryptedData=openpgp_crypto_symmetricDecrypt(a,b,this.encryptedData,!1);this.hash=str_sha1(openpgp_crypto_MDCSystemBytes(a,b,this.encryptedData)+this.decryptedData.substring(0,
-this.decryptedData.length-20));util.print_debug_hexstr_dump("calc hash = ",this.hash);if(this.hash==this.decryptedData.substring(this.decryptedData.length-20,this.decryptedData.length))return this.decryptedData;util.print_error("Decryption stopped: discovered a modification of encrypted data.");return null}}
-function openpgp_packet_modificationdetectioncode(){this.tagType=19;this.hash=null;this.read_packet=function(a,b,c){this.packetLength=c;if(20!=c)return util.print_error("openpgp.packet.modificationdetectioncode.js\ninvalid length for a modification detection code packet!"+c),null;this.hash=a.substring(b,b+20);return this};this.toString=function(){return"5.14 Modification detection code packet\n    bytes ("+this.hash.length+"): ["+util.hexstrdump(this.hash)+"]"}}
-function openpgp_packet_userid(){this.tagType=13;this.certificationSignatures=[];this.certificationRevocationSignatures=[];this.revocationSignatures=[];this.parentNode=null;this.hasCertificationRevocationSignature=function(a){for(var b=0;b<this.certificationRevocationSignatures.length;b++)if(3==this.certificationRevocationSignatures[b].version&&this.certificationRevocationSignatures[b].keyId==a||4==this.certificationRevocationSignatures[b].version&&this.certificationRevocationSignatures[b].issuerKeyId==
-a)return this.certificationRevocationSignatures[b];return null};this.verifyCertificationSignatures=function(a){result=[];for(var b=0;b<this.certificationSignatures.length;b++)if(4==this.certificationSignatures[b].version)if(null!=this.certificationSignatures[b].signatureExpirationTime&&null!=this.certificationSignatures[b].signatureExpirationTime&&0!=this.certificationSignatures[b].signatureExpirationTime&&!this.certificationSignatures[b].signatureNeverExpires&&new Date(this.certificationSignatures[b].creationTime.getTime()+
-1E3*this.certificationSignatures[b].signatureExpirationTime)<new Date)result[b]=this.certificationSignatures[b].issuerKeyId==a.getKeyId()?5:1;else if(null==this.certificationSignatures[b].issuerKeyId)result[b]=0;else{var c=openpgp.keyring.getPublicKeysForKeyId(this.certificationSignatures[b].issuerKeyId);if(null==c||0==c.length)result[b]=2;else if(c=c[0],c=c.obj.getSigningKey(),null==c)result[b]=0;else{var d=this.hasCertificationRevocationSignature(this.certificationSignatures[b].issuerKeyId);if(null!=
-d&&d.creationTime>this.certificationSignatures[b].creationTime){var e=String.fromCharCode(153)+a.header.substring(1)+a.data+String.fromCharCode(180)+String.fromCharCode(this.text.length>>24&255)+String.fromCharCode(this.text.length>>16&255)+String.fromCharCode(this.text.length>>8&255)+String.fromCharCode(this.text.length&255)+this.text;if(d.verify(e,c)){result[b]=this.certificationSignatures[b].issuerKeyId==a.getKeyId()?6:3;continue}}e=String.fromCharCode(153)+a.header.substring(1)+a.data+String.fromCharCode(180)+
-String.fromCharCode(this.text.length>>24&255)+String.fromCharCode(this.text.length>>16&255)+String.fromCharCode(this.text.length>>8&255)+String.fromCharCode(this.text.length&255)+this.text;result[b]=this.certificationSignatures[b].verify(e,c)?4:0}}else if(3==this.certificationSignatures[b].version)if(null==this.certificationSignatures[b].keyId)result[b]=0;else if(c=openpgp.keyring.getPublicKeysForKeyId(this.certificationSignatures[b].keyId),null==c||0==c.length)result[b]=2;else if(c=publicKey.obj.getSigningKey(),
-null==c)result[b]=0;else{d=this.hasCertificationRevocationSignature(this.certificationSignatures[b].keyId);if(null!=d&&d.creationTime>this.certificationSignatures[b].creationTime&&(e=String.fromCharCode(153)+this.publicKeyPacket.header.substring(1)+this.publicKeyPacket.data+this.text,d.verify(e,c))){result[b]=d.keyId==a.getKeyId()?6:3;continue}e=String.fromCharCode(153)+a.header.substring(1)+a.data+this.text;result[b]=this.certificationSignatures[b].verify(e,c)?4:0}else result[b]=0;return result};
-this.verify=function(a){a=this.verifyCertificationSignatures(a);return-1!=a.indexOf(6)?2:-1!=a.indexOf(5)?1:0};this.read_packet=function(a,b,c){this.text="";this.packetLength=c;for(var d=0;d<c;d++)this.text+=a[b+d];return this};this.write_packet=function(a){this.text=a;a=openpgp_packet.write_packet_header(13,this.text.length);return a+=this.text};this.toString=function(){for(var a="     5.11.  User ID Packet (Tag 13)\n    text ("+this.text.length+'): "'+this.text.replace("<","&lt;")+'"\n',a=a+"certification signatures:\n",
-b=0;b<this.certificationSignatures.length;b++)a+="        "+this.certificationSignatures[b].toString();a+="certification revocation signatures:\n";for(b=0;b<this.certificationRevocationSignatures.length;b++)a+="        "+this.certificationRevocationSignatures[b].toString();return a};this.read_nodes=function(a,b,c,d){if(6==a.tagType){this.parentNode=a;for(var e=c,f=d;b.length!=e;){var h=openpgp_packet.read_packet(b,e,f-(e-c));if(null==h){util.print_error("[user_id] parsing ends here @:"+e+" l:"+f);
-break}else switch(e+=h.packetLength+h.headerLength,f=b.length-e,h.tagType){case 2:if(15<h.signatureType&&20>h.signatureType){this.certificationSignatures[this.certificationSignatures.length]=h;break}else if(48==h.signatureType){this.certificationRevocationSignatures[this.certificationRevocationSignatures.length]=h;break}else if(24==h.signatureType){this.certificationSignatures[this.certificationSignatures.length]=h;break}else util.debug("unknown sig t: "+h.signatureType+"@"+(e-(h.packetLength+h.headerLength)));
-default:return this.data=b,this.position=c-a.packetLength,this.len=e-c-(h.headerLength+h.packetLength)}}this.data=b;this.position=c-a.packetLength;return this.len=e-c-(h.headerLength+h.packetLength)}if(5==a.tagType){this.parentNode=a;for(e=c;b.length!=e;)if(h=openpgp_packet.read_packet(b,e,f-(e-c)),null==h){util.print_error("parsing ends here @:"+e+" l:"+f);break}else switch(e+=h.packetLength+h.headerLength,h.tagType){case 2:15<h.signatureType&&20>h.signatureType?this.certificationSignatures[this.certificationSignatures.length]=
-h:48==h.signatureType&&(this.certificationRevocationSignatures[this.certificationRevocationSignatures.length]=h);default:return this.data=b,this.position=c-a.packetLength,this.len=e-c-(h.headerLength+h.packetLength)}}else util.print_error("unknown parent node for a userId packet "+a.tagType)}}
-function openpgp_packet_encryptedsessionkey(){this.read_pub_key_packet=function(a,b,c){this.tagType=1;this.packetLength=c;var d=b;if(10>c)return util.print_error("openpgp.packet.encryptedsessionkey.js\ninvalid length"),null;this.version=a[d++].charCodeAt();this.keyId=new openpgp_type_keyid;this.keyId.read_packet(a,d);d+=8;this.publicKeyAlgorithmUsed=a[d++].charCodeAt();switch(this.publicKeyAlgorithmUsed){case 1:case 2:this.MPIs=[];this.MPIs[0]=new openpgp_type_mpi;this.MPIs[0].read(a,d,d-b);break;
-case 16:this.MPIs=[];this.MPIs[0]=new openpgp_type_mpi;this.MPIs[0].read(a,d,d-b);d+=this.MPIs[0].packetLength;this.MPIs[1]=new openpgp_type_mpi;this.MPIs[1].read(a,d,d-b);break;default:util.print_error("openpgp.packet.encryptedsessionkey.js\nunknown public key packet algorithm type "+this.publicKeyAlgorithmType)}return this};this.read_symmetric_key_packet=function(a,b,c){this.tagType=3;var d=b;this.version=a[d++];this.symmetricKeyAlgorithmUsed=a[d++];this.s2k=new openpgp_type_s2k;this.s2k.read(a,
-d);if(s2k.s2kLength+d<c){this.encryptedSessionKey=[];for(b=d-b;b<c;b++)this.encryptedSessionKey[b]=a[d++]}return this};this.write_pub_key_packet=function(a,b,c,d,e){for(var f=String.fromCharCode(3),d=String.fromCharCode(d),d=d+e,e=util.calc_checksum(e),d=d+String.fromCharCode(e>>8&255),d=d+String.fromCharCode(e&255),f=f+a+String.fromCharCode(c),a=new openpgp_type_mpi,b=openpgp_crypto_asymetricEncrypt(c,b,a.create(openpgp_encoding_eme_pkcs1_encode(d,b[0].mpiByteLength))),c=0;c<b.length;c++)f+=b[c];
-return f=openpgp_packet.write_packet_header(1,f.length)+f};this.toString=function(){if(1==this.tagType){for(var a="5.1.  Public-Key Encrypted Session Key Packets (Tag 1)\n    KeyId:  "+this.keyId.toString()+"\n    length: "+this.packetLength+"\n    version:"+this.version+"\n    pubAlgUs:"+this.publicKeyAlgorithmUsed+"\n",b=0;b<this.MPIs.length;b++)a+=this.MPIs[b].toString();return a}return"5.3 Symmetric-Key Encrypted Session Key Packets (Tag 3)\n    KeyId:  "+this.keyId.toString()+"\n    length: "+
-this.packetLength+"\n    version:"+this.version+"\n    symKeyA:"+this.symmetricKeyAlgorithmUsed+"\n    s2k:    "+this.s2k+"\n"};this.decrypt=function(a,b){if(1==this.tagType){var c=openpgp_crypto_asymetricDecrypt(this.publicKeyAlgorithmUsed,b.publicKey.MPIs,b.secMPIs,this.MPIs).toMPI();c.charCodeAt(c.length-2);c.charCodeAt(c.length-1);var d=openpgp_encoding_eme_pkcs1_decode(c.substring(2,c.length-2),b.publicKey.MPIs[0].getByteLength()),c=d.substring(1),d=d.charCodeAt(0);return 18==a.encryptedData.tagType?
-a.encryptedData.decrypt(d,c):a.encryptedData.decrypt_sym(d,c)}if(3==this.tagType)return util.print_error("Symmetric encrypted sessionkey is not supported!"),null}}
-function openpgp_packet_literaldata(){this.tagType=11;this.read_packet=function(a,b,c){this.packetLength=c;this.format=a[b];this.filename=a.substr(b+2,a.charCodeAt(b+1));this.date=new Date(1E3*parseInt(a.substr(b+2+a.charCodeAt(b+1),4)));this.data=a.substring(b+6+a.charCodeAt(b+1));return this};this.toString=function(){return"5.9.  Literal Data Packet (Tag 11)\n    length: "+this.packetLength+"\n    format: "+this.format+"\n    filename:"+this.filename+"\n    date:   "+this.date+"\n    data:  |"+
-this.data+"|\n    rdata: |"+this.real_data+"|\n"};this.write_packet=function(a){a=a.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n");this.filename="msg.txt";this.date=new Date;this.format="t";var b=openpgp_packet.write_packet_header(11,a.length+6+this.filename.length),b=b+this.format,b=b+String.fromCharCode(this.filename.length),b=b+this.filename,b=b+String.fromCharCode(Math.round(this.date.getTime()/1E3)>>24&255),b=b+String.fromCharCode(Math.round(this.date.getTime()/1E3)>>16&255),b=b+String.fromCharCode(Math.round(this.date.getTime()/
-1E3)>>8&255),b=b+String.fromCharCode(Math.round(this.date.getTime()/1E3)&255);this.data=a;return b+a}}
-function openpgp_packet_encrypteddata(){this.tagType=9;this.decryptedData=this.encryptedData=this.packetLength=null;this.decrypt_sym=function(a,b){this.decryptedData=openpgp_crypto_symmetricDecrypt(a,b,this.encryptedData,!0);util.print_debug("openpgp.packet.encryptedintegrityprotecteddata.js\ndata: "+util.hexstrdump(this.decryptedData));return this.decryptedData};this.toString=function(){return"5.7.  Symmetrically Encrypted Data Packet (Tag 9)\n    length:  "+this.packetLength+"\n    Used symmetric algorithm: "+
-this.algorithmType+"\n    encrypted data: Bytes ["+util.hexstrdump(this.encryptedData)+"]\n"};this.read_packet=function(a,b,c){this.packetLength=c;this.encryptedData=a.substring(b,b+c);return this};this.write_packet=function(a,b,c){a=""+openpgp_crypto_symmetricEncrypt(openpgp_crypto_getPrefixRandom(a),a,b,c,!0);return a=openpgp_packet.write_packet_header(9,a.length)+a}}
-function openpgp_packet_userattribute(){this.tagType=17;this.certificationSignatures=[];this.certificationRevocationSignatures=[];this.revocationSignatures=[];this.parentNode=null;this.read_packet=function(a,b,c){var d=0;this.packetLength=c;this.userattributes=[];for(var e=b;c!=d;){var f=0;192>a[e].charCodeAt()?(packet_length=a[e++].charCodeAt(),f=1):192<=a[e].charCodeAt()&&224>a[e].charCodeAt()?(packet_length=(a[e++].charCodeAt()-192<<8)+a[e++].charCodeAt()+192,f=2):223<a[e].charCodeAt()&&255>a[e].charCodeAt()?
-(packet_length=1<<(a[e++].charCodeAt()&31),f=1):(f=5,e++,packet_length=a[e++].charCodeAt()<<24|a[e++].charCodeAt()<<16|a[e++].charCodeAt()<<8|a[e++].charCodeAt());a[e++].charCodeAt();packet_length--;f++;this.userattributes[0]=[];this.userattributes[0]=a.substring(e,e+packet_length);e+=packet_length;d+=f+packet_length}this.packetLength=e-b;return this};this.read_nodes=function(a,b,c,d){this.parentNode=a;for(var e=c,f=d;b.length!=e;){var h=openpgp_packet.read_packet(b,e,f);if(null==h){util.print_error("openpgp.packet.userattribute.js\n[user_attr] parsing ends here @:"+
-e+" l:"+f);break}else switch(h.tagType){case 2:15<h.signatureType&&20>h.signatureType?this.certificationSignatures[this.certificationSignatures.length]=h:32==h.signatureType&&(this.certificationRevocationSignatures[this.certificationRevocationSignatures.length]=h);e+=h.packetLength+h.headerLength;f=d-(e-c);break;default:return this.data=b,this.position=c-a.packetLength,this.len=e-c}}this.data=b;this.position=c-a.packetLength;return this.len=e-c};this.toString=function(){for(var a="5.12.  User Attribute Packet (Tag 17)\n    AttributePackets: (count = "+
-this.userattributes.length+")\n",b=0;b<this.userattributes.length;b++)a+="    ("+this.userattributes[b].length+") bytes: ["+util.hexidump(this.userattributes[b])+"]\n";return a}}
-function _openpgp_packet(){function a(b){result="";192>b?result+=String.fromCharCode(b):191<b&&8384>b?(result+=String.fromCharCode((b-192>>8)+192),result+=String.fromCharCode(b-192&255)):(result+=String.fromCharCode(255),result+=String.fromCharCode(b>>24&255),result+=String.fromCharCode(b>>16&255),result+=String.fromCharCode(b>>8&255),result+=String.fromCharCode(b&255));return result}this.encode_length=a;this.write_old_packet_header=function(b,a){var d="";256>a?(d+=String.fromCharCode(128|b<<2),d+=
-String.fromCharCode(a)):(65536>a?(d+=String.fromCharCode(b<<2|129),d+=String.fromCharCode(a>>8)):(d+=String.fromCharCode(b<<2|130),d+=String.fromCharCode(a>>24&255),d+=String.fromCharCode(a>>16&255),d+=String.fromCharCode(a>>8&255)),d+=String.fromCharCode(a&255));return d};this.write_packet_header=function(b,c){var d;d=""+String.fromCharCode(192|b);return d+=a(c)};this.read_packet=function(b,a){if(null==b||b.length<=a||2>b.substring(a).length||0==(b[a].charCodeAt()&128))return util.print_error("Error during parsing. This message / key is propably not containing a valid OpenPGP format."),
-null;var d=a,e=-1,f=-1,f=0;0!=(b[d].charCodeAt()&64)&&(f=1);var h;f?e=b[d].charCodeAt()&63:(e=(b[d].charCodeAt()&63)>>2,h=b[d].charCodeAt()&3);d++;var g=null,k=-1;if(f)if(192>b[d].charCodeAt())packet_length=b[d++].charCodeAt(),util.print_debug("1 byte length:"+packet_length);else if(192<=b[d].charCodeAt()&&224>b[d].charCodeAt())packet_length=(b[d++].charCodeAt()-192<<8)+b[d++].charCodeAt()+192,util.print_debug("2 byte length:"+packet_length);else if(223<b[d].charCodeAt()&&255>b[d].charCodeAt()){packet_length=
-1<<(b[d++].charCodeAt()&31);util.print_debug("4 byte length:"+packet_length);k=d+packet_length;for(g=b.substring(d,d+packet_length);;)if(192>b[k].charCodeAt()){f=b[k++].charCodeAt();packet_length+=f;g+=b.substring(k,k+f);k+=f;break}else if(192<=b[k].charCodeAt()&&224>b[k].charCodeAt()){f=(b[k++].charCodeAt()-192<<8)+b[k++].charCodeAt()+192;packet_length+=f;g+=b.substring(k,k+f);k+=f;break}else if(223<b[k].charCodeAt()&&255>b[k].charCodeAt())f=1<<(b[k++].charCodeAt()&31),packet_length+=f,g+=b.substring(k,
-k+f),k+=f;else{k++;f=b[k++].charCodeAt()<<24|b[k++].charCodeAt()<<16|b[k++].charCodeAt()<<8|b[k++].charCodeAt();g+=b.substring(k,k+f);packet_length+=f;k+=f;break}}else d++,packet_length=b[d++].charCodeAt()<<24|b[d++].charCodeAt()<<16|b[d++].charCodeAt()<<8|b[d++].charCodeAt();else switch(h){case 0:packet_length=b[d++].charCodeAt();break;case 1:packet_length=b[d++].charCodeAt()<<8|b[d++].charCodeAt();break;case 2:packet_length=b[d++].charCodeAt()<<24|b[d++].charCodeAt()<<16|b[d++].charCodeAt()<<8|
-b[d++].charCodeAt()}-1==k&&(k=packet_length);null==g&&(g=b.substring(d,d+k));switch(e){case 0:break;case 1:e=new openpgp_packet_encryptedsessionkey;if(null!=e.read_pub_key_packet(g,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 2:e=new openpgp_packet_signature;if(null!=e.read_packet(g,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 3:e=new openpgp_packet_encryptedsessionkey;if(null!=e.read_symmetric_key_packet(g,0,packet_length))return e.headerLength=
-d-a,e.packetLength=k,e;break;case 4:e=new openpgp_packet_onepasssignature;if(e.read_packet(g,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 5:e=new openpgp_packet_keymaterial;e.header=b.substring(a,d);if(null!=e.read_tag5(g,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 6:e=new openpgp_packet_keymaterial;e.header=b.substring(a,d);if(null!=e.read_tag6(g,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 7:e=new openpgp_packet_keymaterial;
-if(null!=e.read_tag7(g,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 8:e=new openpgp_packet_compressed;if(null!=e.read_packet(g,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 9:e=new openpgp_packet_encrypteddata;if(null!=e.read_packet(g,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 10:e=new openpgp_packet_marker;if(null!=e.read_packet(g,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 11:e=new openpgp_packet_literaldata;
-if(null!=e.read_packet(g,0,packet_length))return e.headerLength=d-a,e.header=b.substring(a,d),e.packetLength=k,e;break;case 12:break;case 13:e=new openpgp_packet_userid;if(null!=e.read_packet(g,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 14:e=new openpgp_packet_keymaterial;e.header=b.substring(a,d);if(null!=e.read_tag14(g,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 17:e=new openpgp_packet_userattribute;if(null!=e.read_packet(g,0,packet_length))return e.headerLength=
-d-a,e.packetLength=k,e;break;case 18:e=new openpgp_packet_encryptedintegrityprotecteddata;if(null!=e.read_packet(g,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 19:e=new openpgp_packet_modificationdetectioncode;if(null!=e.read_packet(g,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;default:return util.print_error("openpgp.packet.js\n[ERROR] openpgp_packet: failed to parse packet @:"+d+"\nchar:'"+util.hexstrdump(b.substring(d))+"'\ninput:"+util.hexstrdump(b)),
-null}}}var openpgp_packet=new _openpgp_packet;
-function openpgp_packet_compressed(){this.tagType=8;this.read_packet=function(a,b,c){this.packetLength=c;var d=b;this.type=a.charCodeAt(d++);this.compressedData=a.substring(b+1,b+c);return this};this.toString=function(){return"5.6.  Compressed Data Packet (Tag 8)\n    length:  "+this.packetLength+"\n    Compression Algorithm = "+this.type+"\n    Compressed Data: Byte ["+util.hexstrdump(this.compressedData)+"]\n"};this.compress=function(a,b){this.type=a;this.decompressedData=b;switch(this.type){case 0:this.compressedData=
-this.decompressedData;break;case 1:util.print_error("Compression algorithm ZIP [RFC1951] is not implemented.");break;case 2:util.print_error("Compression algorithm ZLIB [RFC1950] is not implemented.");break;case 3:util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");break;default:util.print_error("Compression algorithm unknown :"+this.type)}this.packetLength=this.compressedData.length+1;return this.compressedData};this.decompress=function(){if(null!=this.decompressedData)return this.decompressedData;
-if(null==this.type)return null;switch(this.type){case 0:this.decompressedData=this.compressedData;break;case 1:var a=(new zip.Inflater).append(util.str2Uint8Array(this.compressedData)),a=util.Uint8Array2str(a),a=openpgp_packet.read_packet(a,0,a.length);util.print_info("Decompressed packet [Type 1-ZIP]: "+a);this.decompressedData=a.data;break;case 2:8==this.compressedData.charCodeAt(0)%16?(a=this.compressedData.substring(0,this.compressedData.length-4),a=s2r(a).replace(/\n/g,""),a=JXG.decompress(a),
-a=openpgp_packet.read_packet(a,0,a.length),util.print_info("Decompressed packet [Type 2-ZLIB]: "+a),this.decompressedData=a.data):util.print_error("Compression algorithm ZLIB only supports DEFLATE compression method.");break;case 3:util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");break;default:util.print_error("Compression algorithm unknown :"+this.type)}util.print_debug("decompressed:"+util.hexstrdump(this.decompressedData));return this.decompressedData};this.write_packet=
-function(a,b){this.decompressedData=b;if(null==a)this.type=1;var c=String.fromCharCode(this.type)+this.compress(this.type);return openpgp_packet.write_packet_header(8,c.length)+c}}
 function openpgp_packet_keymaterial(){this.subKeyRevocationSignature=this.subKeySignature=this.parentNode=this.checksum=this.hasUnencryptedSecretKeyData=this.encryptedMPIData=this.IVLength=this.s2kUsageConventions=this.symmetricEncryptionAlgorithm=this.publicKey=this.secMPIs=this.MPIs=this.expiration=this.version=this.creationTime=this.tagType=this.publicKeyAlgorithm=null;this.read_tag5=function(a,b,c){this.tagType=5;this.read_priv_key(a,b,c);return this};this.read_tag6=function(a,b,c){this.tagType=
 6;this.packetLength=c;this.read_pub_key(a,b,c);return this};this.read_tag7=function(a,b,c){this.tagType=7;this.packetLength=c;return this.read_priv_key(a,b,c)};this.read_tag14=function(a,b,c){this.subKeySignature=null;this.subKeyRevocationSignature=[];this.tagType=14;this.packetLength=c;this.read_pub_key(a,b,c);return this};this.toString=function(){var a="";switch(this.tagType){case 6:a+="5.5.1.1. Public-Key Packet (Tag 6)\n    length:             "+this.packetLength+"\n    version:            "+
 this.version+"\n    creation time:      "+this.creationTime+"\n    expiration time:    "+this.expiration+"\n    publicKeyAlgorithm: "+this.publicKeyAlgorithm+"\n";break;case 14:a+="5.5.1.2. Public-Subkey Packet (Tag 14)\n    length:             "+this.packetLength+"\n    version:            "+this.version+"\n    creation time:      "+this.creationTime+"\n    expiration time:    "+this.expiration+"\n    publicKeyAlgorithm: "+this.publicKeyAlgorithm+"\n";break;case 5:a+="5.5.1.3. Secret-Key Packet (Tag 5)\n    length:             "+
@@ -103,105 +78,242 @@ a);return a}};this.getFingerprint=function(){if(4==this.version)return tohash=St
 this.write_private_key=function(a,b,c,d,e,f){this.symmetricEncryptionAlgorithm=e;e=String.fromCharCode(4);e+=f;switch(a){case 1:e+=String.fromCharCode(a);e+=b.n.toMPI();e+=b.ee.toMPI();if(c)switch(e+=String.fromCharCode(254),e+=String.fromCharCode(this.symmetricEncryptionAlgorithm),e+=String.fromCharCode(3),e+=String.fromCharCode(d),a=b.d.toMPI()+b.p.toMPI()+b.q.toMPI()+b.u.toMPI(),b=str_sha1(a),util.print_debug_hexstr_dump("write_private_key sha1: ",b),f=openpgp_crypto_getRandomBytes(8),util.print_debug_hexstr_dump("write_private_key Salt: ",
 f),e=e+f+String.fromCharCode(96),util.print_debug("write_private_key c: 96"),c=(new openpgp_type_s2k).write(3,d,c,f,96),this.symmetricEncryptionAlgorithm){case 3:this.IVLength=8;this.IV=openpgp_crypto_getRandomBytes(this.IVLength);ciphertextMPIs=normal_cfb_encrypt(function(b,a){var c=new openpgp_symenc_cast5;c.setKey(a);return c.encrypt(util.str2bin(b))},this.IVLength,util.str2bin(c.substring(0,16)),a+b,this.IV);e+=this.IV+ciphertextMPIs;break;case 7:case 8:case 9:this.IVLength=16,this.IV=openpgp_crypto_getRandomBytes(this.IVLength),
 ciphertextMPIs=normal_cfb_encrypt(AESencrypt,this.IVLength,c,a+b,this.IV),e+=this.IV+ciphertextMPIs}else e+=String.fromCharCode(0),e+=b.d.toMPI()+b.p.toMPI()+b.q.toMPI()+b.u.toMPI(),c=util.calc_checksum(b.d.toMPI()+b.p.toMPI()+b.q.toMPI()+b.u.toMPI()),e+=String.fromCharCode(c/256)+String.fromCharCode(c%256),util.print_debug_hexstr_dump("write_private_key basic checksum: "+c);break;default:e="",util.print_error("openpgp.packet.keymaterial.js\nerror writing private key, unknown type :"+a)}c=openpgp_packet.write_packet_header(5,
-e.length);return{string:c+e,header:c,body:e}};this.write_public_key=function(a,b,c){var d=String.fromCharCode(4),d=d+c;switch(a){case 1:d+=String.fromCharCode(1);d+=b.n.toMPI();d+=b.ee.toMPI();break;default:util.print_error("openpgp.packet.keymaterial.js\nerror writing private key, unknown type :"+a)}a=openpgp_packet.write_packet_header(6,d.length);return{string:a+d,header:a,body:d}}}function MD5(a){a=md5(a);return util.hex2bin(a)}
-function md5cycle(a,b){var c=a[0],d=a[1],e=a[2],f=a[3],c=ff(c,d,e,f,b[0],7,-680876936),f=ff(f,c,d,e,b[1],12,-389564586),e=ff(e,f,c,d,b[2],17,606105819),d=ff(d,e,f,c,b[3],22,-1044525330),c=ff(c,d,e,f,b[4],7,-176418897),f=ff(f,c,d,e,b[5],12,1200080426),e=ff(e,f,c,d,b[6],17,-1473231341),d=ff(d,e,f,c,b[7],22,-45705983),c=ff(c,d,e,f,b[8],7,1770035416),f=ff(f,c,d,e,b[9],12,-1958414417),e=ff(e,f,c,d,b[10],17,-42063),d=ff(d,e,f,c,b[11],22,-1990404162),c=ff(c,d,e,f,b[12],7,1804603682),f=ff(f,c,d,e,b[13],12,
--40341101),e=ff(e,f,c,d,b[14],17,-1502002290),d=ff(d,e,f,c,b[15],22,1236535329),c=gg(c,d,e,f,b[1],5,-165796510),f=gg(f,c,d,e,b[6],9,-1069501632),e=gg(e,f,c,d,b[11],14,643717713),d=gg(d,e,f,c,b[0],20,-373897302),c=gg(c,d,e,f,b[5],5,-701558691),f=gg(f,c,d,e,b[10],9,38016083),e=gg(e,f,c,d,b[15],14,-660478335),d=gg(d,e,f,c,b[4],20,-405537848),c=gg(c,d,e,f,b[9],5,568446438),f=gg(f,c,d,e,b[14],9,-1019803690),e=gg(e,f,c,d,b[3],14,-187363961),d=gg(d,e,f,c,b[8],20,1163531501),c=gg(c,d,e,f,b[13],5,-1444681467),
-f=gg(f,c,d,e,b[2],9,-51403784),e=gg(e,f,c,d,b[7],14,1735328473),d=gg(d,e,f,c,b[12],20,-1926607734),c=hh(c,d,e,f,b[5],4,-378558),f=hh(f,c,d,e,b[8],11,-2022574463),e=hh(e,f,c,d,b[11],16,1839030562),d=hh(d,e,f,c,b[14],23,-35309556),c=hh(c,d,e,f,b[1],4,-1530992060),f=hh(f,c,d,e,b[4],11,1272893353),e=hh(e,f,c,d,b[7],16,-155497632),d=hh(d,e,f,c,b[10],23,-1094730640),c=hh(c,d,e,f,b[13],4,681279174),f=hh(f,c,d,e,b[0],11,-358537222),e=hh(e,f,c,d,b[3],16,-722521979),d=hh(d,e,f,c,b[6],23,76029189),c=hh(c,d,
-e,f,b[9],4,-640364487),f=hh(f,c,d,e,b[12],11,-421815835),e=hh(e,f,c,d,b[15],16,530742520),d=hh(d,e,f,c,b[2],23,-995338651),c=ii(c,d,e,f,b[0],6,-198630844),f=ii(f,c,d,e,b[7],10,1126891415),e=ii(e,f,c,d,b[14],15,-1416354905),d=ii(d,e,f,c,b[5],21,-57434055),c=ii(c,d,e,f,b[12],6,1700485571),f=ii(f,c,d,e,b[3],10,-1894986606),e=ii(e,f,c,d,b[10],15,-1051523),d=ii(d,e,f,c,b[1],21,-2054922799),c=ii(c,d,e,f,b[8],6,1873313359),f=ii(f,c,d,e,b[15],10,-30611744),e=ii(e,f,c,d,b[6],15,-1560198380),d=ii(d,e,f,c,b[13],
-21,1309151649),c=ii(c,d,e,f,b[4],6,-145523070),f=ii(f,c,d,e,b[11],10,-1120210379),e=ii(e,f,c,d,b[2],15,718787259),d=ii(d,e,f,c,b[9],21,-343485551);a[0]=add32(c,a[0]);a[1]=add32(d,a[1]);a[2]=add32(e,a[2]);a[3]=add32(f,a[3])}function cmn(a,b,c,d,e,f){b=add32(add32(b,a),add32(d,f));return add32(b<<e|b>>>32-e,c)}function ff(a,b,c,d,e,f,h){return cmn(b&c|~b&d,a,b,e,f,h)}function gg(a,b,c,d,e,f,h){return cmn(b&d|c&~d,a,b,e,f,h)}function hh(a,b,c,d,e,f,h){return cmn(b^c^d,a,b,e,f,h)}
-function ii(a,b,c,d,e,f,h){return cmn(c^(b|~d),a,b,e,f,h)}function md51(a){txt="";var b=a.length,c=[1732584193,-271733879,-1732584194,271733878],d;for(d=64;d<=a.length;d+=64)md5cycle(c,md5blk(a.substring(d-64,d)));var a=a.substring(d-64),e=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(d=0;d<a.length;d++)e[d>>2]|=a.charCodeAt(d)<<(d%4<<3);e[d>>2]|=128<<(d%4<<3);if(55<d){md5cycle(c,e);for(d=0;16>d;d++)e[d]=0}e[14]=8*b;md5cycle(c,e);return c}
-function md5blk(a){var b=[],c;for(c=0;64>c;c+=4)b[c>>2]=a.charCodeAt(c)+(a.charCodeAt(c+1)<<8)+(a.charCodeAt(c+2)<<16)+(a.charCodeAt(c+3)<<24);return b}var hex_chr="0123456789abcdef".split("");function rhex(a){for(var b="",c=0;4>c;c++)b+=hex_chr[a>>8*c+4&15]+hex_chr[a>>8*c&15];return b}function hex(a){for(var b=0;b<a.length;b++)a[b]=rhex(a[b]);return a.join("")}function md5(a){return hex(md51(a))}function add32(a,b){return a+b&4294967295}
-"5d41402abc4b2a76b9719d911017c592"!=md5("hello")&&(add32=function(a,b){var c=(a&65535)+(b&65535);return(a>>16)+(b>>16)+(c>>16)<<16|c&65535});
-var jsSHA=function(){var a=function(b,a){this.highOrder=b;this.lowOrder=a},b=function(b){var a=[],c=8*b.length,d;for(d=0;d<c;d+=8)a[d>>5]|=(b.charCodeAt(d/8)&255)<<24-d%32;return a},c=function(b){var a=[],c=b.length,d,e;for(d=0;d<c;d+=2){e=parseInt(b.substr(d,2),16);if(isNaN(e))return"INVALID HEX STRING";a[d>>3]|=e<<24-4*(d%8)}return a},d=function(b){var a="",c=4*b.length,d,e;for(d=0;d<c;d+=1)e=b[d>>2]>>8*(3-d%4),a+="0123456789abcdef".charAt(e>>4&15)+"0123456789abcdef".charAt(e&15);return a},e=function(b){var a=
-"",c=4*b.length,d,e,f;for(d=0;d<c;d+=3){f=(b[d>>2]>>8*(3-d%4)&255)<<16|(b[d+1>>2]>>8*(3-(d+1)%4)&255)<<8|b[d+2>>2]>>8*(3-(d+2)%4)&255;for(e=0;4>e;e+=1)a=8*d+6*e<=32*b.length?a+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(f>>6*(3-e)&63):a+""}return a},f=function(b){for(var a="",c=0;c<32*b.length;c+=8)a+=String.fromCharCode(b[c>>5]>>>24-c%32&255);return a},h=function(b,a){return b<<a|b>>>32-a},g=function(b,a){return b>>>a|b<<32-a},k=function(b,c){return 32>=c?new a(b.highOrder>>>
-c|b.lowOrder<<32-c,b.lowOrder>>>c|b.highOrder<<32-c):new a(b.lowOrder>>>c|b.highOrder<<32-c,b.highOrder>>>c|b.lowOrder<<32-c)},j=function(b,c){return 32>=c?new a(b.highOrder>>>c,b.lowOrder>>>c|b.highOrder<<32-c):new a(0,b.highOrder<<32-c)},l=function(b,a,c){return b&a^~b&c},q=function(b,c,d){return new a(b.highOrder&c.highOrder^~b.highOrder&d.highOrder,b.lowOrder&c.lowOrder^~b.lowOrder&d.lowOrder)},u=function(b,a,c){return b&a^b&c^a&c},m=function(b,c,d){return new a(b.highOrder&c.highOrder^b.highOrder&
-d.highOrder^c.highOrder&d.highOrder,b.lowOrder&c.lowOrder^b.lowOrder&d.lowOrder^c.lowOrder&d.lowOrder)},o=function(b){return g(b,2)^g(b,13)^g(b,22)},M=function(b){var c=k(b,28),d=k(b,34),b=k(b,39);return new a(c.highOrder^d.highOrder^b.highOrder,c.lowOrder^d.lowOrder^b.lowOrder)},O=function(b){return g(b,6)^g(b,11)^g(b,25)},D=function(b){var c=k(b,14),d=k(b,18),b=k(b,41);return new a(c.highOrder^d.highOrder^b.highOrder,c.lowOrder^d.lowOrder^b.lowOrder)},B=function(b){return g(b,7)^g(b,18)^b>>>3},
-A=function(b){var c=k(b,1),d=k(b,8),b=j(b,7);return new a(c.highOrder^d.highOrder^b.highOrder,c.lowOrder^d.lowOrder^b.lowOrder)},ga=function(b){return g(b,17)^g(b,19)^b>>>10},ia=function(b){var c=k(b,19),d=k(b,61),b=j(b,6);return new a(c.highOrder^d.highOrder^b.highOrder,c.lowOrder^d.lowOrder^b.lowOrder)},aa=function(b,a){var c=(b&65535)+(a&65535);return((b>>>16)+(a>>>16)+(c>>>16)&65535)<<16|c&65535},ha=function(b,a,c,d){var e=(b&65535)+(a&65535)+(c&65535)+(d&65535);return((b>>>16)+(a>>>16)+(c>>>
-16)+(d>>>16)+(e>>>16)&65535)<<16|e&65535},K=function(b,a,c,d,e){var f=(b&65535)+(a&65535)+(c&65535)+(d&65535)+(e&65535);return((b>>>16)+(a>>>16)+(c>>>16)+(d>>>16)+(e>>>16)+(f>>>16)&65535)<<16|f&65535},E=function(b,c){var d,e,f;d=(b.lowOrder&65535)+(c.lowOrder&65535);e=(b.lowOrder>>>16)+(c.lowOrder>>>16)+(d>>>16);f=(e&65535)<<16|d&65535;d=(b.highOrder&65535)+(c.highOrder&65535)+(e>>>16);e=(b.highOrder>>>16)+(c.highOrder>>>16)+(d>>>16);return new a((e&65535)<<16|d&65535,f)},V=function(b,c,d,e){var f,
-g,h;f=(b.lowOrder&65535)+(c.lowOrder&65535)+(d.lowOrder&65535)+(e.lowOrder&65535);g=(b.lowOrder>>>16)+(c.lowOrder>>>16)+(d.lowOrder>>>16)+(e.lowOrder>>>16)+(f>>>16);h=(g&65535)<<16|f&65535;f=(b.highOrder&65535)+(c.highOrder&65535)+(d.highOrder&65535)+(e.highOrder&65535)+(g>>>16);g=(b.highOrder>>>16)+(c.highOrder>>>16)+(d.highOrder>>>16)+(e.highOrder>>>16)+(f>>>16);return new a((g&65535)<<16|f&65535,h)},ma=function(b,c,d,e,f){var g,h,k;g=(b.lowOrder&65535)+(c.lowOrder&65535)+(d.lowOrder&65535)+(e.lowOrder&
-65535)+(f.lowOrder&65535);h=(b.lowOrder>>>16)+(c.lowOrder>>>16)+(d.lowOrder>>>16)+(e.lowOrder>>>16)+(f.lowOrder>>>16)+(g>>>16);k=(h&65535)<<16|g&65535;g=(b.highOrder&65535)+(c.highOrder&65535)+(d.highOrder&65535)+(e.highOrder&65535)+(f.highOrder&65535)+(h>>>16);h=(b.highOrder>>>16)+(c.highOrder>>>16)+(d.highOrder>>>16)+(e.highOrder>>>16)+(f.highOrder>>>16)+(g>>>16);return new a((h&65535)<<16|g&65535,k)},Z=function(b,a){var c=[],d,e,f,g,k,j,l,o,q,z=[1732584193,4023233417,2562383102,271733878,3285377520],
-m=[1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,
-2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782];b[a>>5]|=128<<24-a%32;b[(a+65>>9<<4)+15]=a;q=b.length;for(l=0;l<q;l+=16){d=z[0];e=z[1];f=z[2];g=z[3];k=z[4];for(o=0;80>o;o+=1)c[o]=
-16>o?b[o+l]:h(c[o-3]^c[o-8]^c[o-14]^c[o-16],1),j=20>o?K(h(d,5),e&f^~e&g,k,m[o],c[o]):40>o?K(h(d,5),e^f^g,k,m[o],c[o]):60>o?K(h(d,5),u(e,f,g),k,m[o],c[o]):K(h(d,5),e^f^g,k,m[o],c[o]),k=g,g=f,f=h(e,30),e=d,d=j;z[0]=aa(d,z[0]);z[1]=aa(e,z[1]);z[2]=aa(f,z[2]);z[3]=aa(g,z[3]);z[4]=aa(k,z[4])}return z},ba=function(b,c,d){var e,f,g,h,k,j,Z,ba,da,z,ya,ja,ea,Ga,za,fa,Aa,Ba,Ca,Da,va,qa,Ea,ka,t,wa,Q=[],Ia;if("SHA-224"===d||"SHA-256"===d)ya=64,e=(c+65>>9<<4)+15,Ga=16,za=1,t=Number,fa=aa,Aa=ha,Ba=K,Ca=B,Da=ga,
-va=o,qa=O,ka=u,Ea=l,wa=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,
-3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],z="SHA-224"===d?[3238371032,914150663,812702999,4144912697,4290775857,1750603025,1694076839,3204075428]:[1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225];else if("SHA-384"===d||"SHA-512"===d)ya=80,e=(c+128>>10<<5)+31,Ga=32,za=2,t=a,fa=E,Aa=V,Ba=ma,Ca=A,Da=ia,
-va=M,qa=D,ka=m,Ea=q,wa=[new t(1116352408,3609767458),new t(1899447441,602891725),new t(3049323471,3964484399),new t(3921009573,2173295548),new t(961987163,4081628472),new t(1508970993,3053834265),new t(2453635748,2937671579),new t(2870763221,3664609560),new t(3624381080,2734883394),new t(310598401,1164996542),new t(607225278,1323610764),new t(1426881987,3590304994),new t(1925078388,4068182383),new t(2162078206,991336113),new t(2614888103,633803317),new t(3248222580,3479774868),new t(3835390401,2666613458),
-new t(4022224774,944711139),new t(264347078,2341262773),new t(604807628,2007800933),new t(770255983,1495990901),new t(1249150122,1856431235),new t(1555081692,3175218132),new t(1996064986,2198950837),new t(2554220882,3999719339),new t(2821834349,766784016),new t(2952996808,2566594879),new t(3210313671,3203337956),new t(3336571891,1034457026),new t(3584528711,2466948901),new t(113926993,3758326383),new t(338241895,168717936),new t(666307205,1188179964),new t(773529912,1546045734),new t(1294757372,1522805485),
-new t(1396182291,2643833823),new t(1695183700,2343527390),new t(1986661051,1014477480),new t(2177026350,1206759142),new t(2456956037,344077627),new t(2730485921,1290863460),new t(2820302411,3158454273),new t(3259730800,3505952657),new t(3345764771,106217008),new t(3516065817,3606008344),new t(3600352804,1432725776),new t(4094571909,1467031594),new t(275423344,851169720),new t(430227734,3100823752),new t(506948616,1363258195),new t(659060556,3750685593),new t(883997877,3785050280),new t(958139571,
-3318307427),new t(1322822218,3812723403),new t(1537002063,2003034995),new t(1747873779,3602036899),new t(1955562222,1575990012),new t(2024104815,1125592928),new t(2227730452,2716904306),new t(2361852424,442776044),new t(2428436474,593698344),new t(2756734187,3733110249),new t(3204031479,2999351573),new t(3329325298,3815920427),new t(3391569614,3928383900),new t(3515267271,566280711),new t(3940187606,3454069534),new t(4118630271,4000239992),new t(116418474,1914138554),new t(174292421,2731055270),new t(289380356,
-3203993006),new t(460393269,320620315),new t(685471733,587496836),new t(852142971,1086792851),new t(1017036298,365543100),new t(1126000580,2618297676),new t(1288033470,3409855158),new t(1501505948,4234509866),new t(1607167915,987167468),new t(1816402316,1246189591)],z="SHA-384"===d?[new t(3418070365,3238371032),new t(1654270250,914150663),new t(2438529370,812702999),new t(355462360,4144912697),new t(1731405415,4290775857),new t(41048885895,1750603025),new t(3675008525,1694076839),new t(1203062813,
-3204075428)]:[new t(1779033703,4089235720),new t(3144134277,2227873595),new t(1013904242,4271175723),new t(2773480762,1595750129),new t(1359893119,2917565137),new t(2600822924,725511199),new t(528734635,4215389547),new t(1541459225,327033209)];b[c>>5]|=128<<24-c%32;b[e]=c;Ia=b.length;for(ja=0;ja<Ia;ja+=Ga){c=z[0];e=z[1];f=z[2];g=z[3];h=z[4];k=z[5];j=z[6];Z=z[7];for(ea=0;ea<ya;ea+=1)Q[ea]=16>ea?new t(b[ea*za+ja],b[ea*za+ja+1]):Aa(Da(Q[ea-2]),Q[ea-7],Ca(Q[ea-15]),Q[ea-16]),ba=Ba(Z,qa(h),Ea(h,k,j),wa[ea],
-Q[ea]),da=fa(va(c),ka(c,e,f)),Z=j,j=k,k=h,h=fa(g,ba),g=f,f=e,e=c,c=fa(ba,da);z[0]=fa(c,z[0]);z[1]=fa(e,z[1]);z[2]=fa(f,z[2]);z[3]=fa(g,z[3]);z[4]=fa(h,z[4]);z[5]=fa(k,z[5]);z[6]=fa(j,z[6]);z[7]=fa(Z,z[7])}switch(d){case "SHA-224":return[z[0],z[1],z[2],z[3],z[4],z[5],z[6]];case "SHA-256":return z;case "SHA-384":return[z[0].highOrder,z[0].lowOrder,z[1].highOrder,z[1].lowOrder,z[2].highOrder,z[2].lowOrder,z[3].highOrder,z[3].lowOrder,z[4].highOrder,z[4].lowOrder,z[5].highOrder,z[5].lowOrder];case "SHA-512":return[z[0].highOrder,
-z[0].lowOrder,z[1].highOrder,z[1].lowOrder,z[2].highOrder,z[2].lowOrder,z[3].highOrder,z[3].lowOrder,z[4].highOrder,z[4].lowOrder,z[5].highOrder,z[5].lowOrder,z[6].highOrder,z[6].lowOrder,z[7].highOrder,z[7].lowOrder];default:return[]}},da=function(a,d){this.strToHash=this.strBinLen=this.sha512=this.sha384=this.sha256=this.sha224=this.sha1=null;if("HEX"===d){if(0!==a.length%2)return"TEXT MUST BE IN BYTE INCREMENTS";this.strBinLen=4*a.length;this.strToHash=c(a)}else if("ASCII"===d||"undefined"===typeof d)this.strBinLen=
-8*a.length,this.strToHash=b(a);else return"UNKNOWN TEXT INPUT TYPE"};da.prototype={getHash:function(b,a){var c=null,g=this.strToHash.slice();switch(a){case "HEX":c=d;break;case "B64":c=e;break;case "ASCII":c=f;break;default:return"FORMAT NOT RECOGNIZED"}switch(b){case "SHA-1":if(null===this.sha1)this.sha1=Z(g,this.strBinLen);return c(this.sha1);case "SHA-224":if(null===this.sha224)this.sha224=ba(g,this.strBinLen,b);return c(this.sha224);case "SHA-256":if(null===this.sha256)this.sha256=ba(g,this.strBinLen,
-b);return c(this.sha256);case "SHA-384":if(null===this.sha384)this.sha384=ba(g,this.strBinLen,b);return c(this.sha384);case "SHA-512":if(null===this.sha512)this.sha512=ba(g,this.strBinLen,b);return c(this.sha512);default:return"HASH NOT RECOGNIZED"}},getHMAC:function(a,g,h,k){var j,o,l,q,m;o=[];var A=[];switch(k){case "HEX":k=d;break;case "B64":k=e;break;case "ASCII":k=f;break;default:return"FORMAT NOT RECOGNIZED"}switch(h){case "SHA-1":j=64;m=160;break;case "SHA-224":j=64;m=224;break;case "SHA-256":j=
-64;m=256;break;case "SHA-384":j=128;m=384;break;case "SHA-512":j=128;m=512;break;default:return"HASH NOT RECOGNIZED"}if("HEX"===g){if(0!==a.length%2)return"KEY MUST BE IN BYTE INCREMENTS";g=c(a);q=4*a.length}else if("ASCII"===g)g=b(a),q=8*a.length;else return"UNKNOWN KEY INPUT TYPE";a=8*j;l=j/4-1;j<q/8?(g="SHA-1"===h?Z(g,q):ba(g,q,h),g[l]&=4294967040):j>q/8&&(g[l]&=4294967040);for(j=0;j<=l;j+=1)o[j]=g[j]^909522486,A[j]=g[j]^1549556828;"SHA-1"===h?(o=Z(o.concat(this.strToHash),a+this.strBinLen),o=
-Z(A.concat(o),a+m)):(o=ba(o.concat(this.strToHash),a+this.strBinLen,h),o=ba(A.concat(o),a+m,h));return k(o)}};return da}();function str_sha1(a){return(new jsSHA(a,"ASCII")).getHash("SHA-1","ASCII")}function str_sha224(a){return(new jsSHA(a,"ASCII")).getHash("SHA-224","ASCII")}function str_sha256(a){return(new jsSHA(a,"ASCII")).getHash("SHA-256","ASCII")}function str_sha384(a){return(new jsSHA(a,"ASCII")).getHash("SHA-384","ASCII")}
-function str_sha512(a){return(new jsSHA(a,"ASCII")).getHash("SHA-512","ASCII")}var RMDsize=160,X=[];function ROL(a,b){return new Number(a<<b|a>>>32-b)}function F(a,b,c){return new Number(a^b^c)}function G(a,b,c){return new Number(a&b|~a&c)}function H(a,b,c){return new Number((a|~b)^c)}function I(a,b,c){return new Number(a&c|b&~c)}function J(a,b,c){return new Number(a^(b|~c))}
-function mixOneRound(a,b,c,d,e,f,h,g){switch(g){case 0:a+=F(b,c,d)+f+0;break;case 1:a+=G(b,c,d)+f+1518500249;break;case 2:a+=H(b,c,d)+f+1859775393;break;case 3:a+=I(b,c,d)+f+2400959708;break;case 4:a+=J(b,c,d)+f+2840853838;break;case 5:a+=J(b,c,d)+f+1352829926;break;case 6:a+=I(b,c,d)+f+1548603684;break;case 7:a+=H(b,c,d)+f+1836072691;break;case 8:a+=G(b,c,d)+f+2053994217;break;case 9:a+=F(b,c,d)+f+0;break;default:document.write("Bogus round number")}a=ROL(a,h)+e;c=ROL(c,10);g=[];g[0]=a&4294967295;
-g[1]=b&4294967295;g[2]=c&4294967295;g[3]=d&4294967295;g[4]=e&4294967295;g[5]=f;g[6]=h;return g}function MDinit(a){a[0]=1732584193;a[1]=4023233417;a[2]=2562383102;a[3]=271733878;a[4]=3285377520}
-var ROLs=[[11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8],[7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12],[11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5],[11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12],[9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6],[8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6],[9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11],[9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5],[15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8],[8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11]],indexes=[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[7,4,13,1,10,6,15,3,12,
-0,9,5,2,14,11,8],[3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12],[1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2],[4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13],[5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12],[6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2],[15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13],[8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14],[12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11]];
-function compress(a,b){blockA=[];blockB=[];for(var c,d=0;5>d;d++)blockA[d]=new Number(a[d]),blockB[d]=new Number(a[d]);for(var e=0,f=0;5>f;f++)for(d=0;16>d;d++)c=mixOneRound(blockA[(e+0)%5],blockA[(e+1)%5],blockA[(e+2)%5],blockA[(e+3)%5],blockA[(e+4)%5],b[indexes[f][d]],ROLs[f][d],f),blockA[(e+0)%5]=c[0],blockA[(e+1)%5]=c[1],blockA[(e+2)%5]=c[2],blockA[(e+3)%5]=c[3],blockA[(e+4)%5]=c[4],e+=4;e=0;for(f=5;10>f;f++)for(d=0;16>d;d++)c=mixOneRound(blockB[(e+0)%5],blockB[(e+1)%5],blockB[(e+2)%5],blockB[(e+
-3)%5],blockB[(e+4)%5],b[indexes[f][d]],ROLs[f][d],f),blockB[(e+0)%5]=c[0],blockB[(e+1)%5]=c[1],blockB[(e+2)%5]=c[2],blockB[(e+3)%5]=c[3],blockB[(e+4)%5]=c[4],e+=4;blockB[3]+=blockA[2]+a[1];a[1]=a[2]+blockA[3]+blockB[4];a[2]=a[3]+blockA[4]+blockB[0];a[3]=a[4]+blockA[0]+blockB[1];a[4]=a[0]+blockA[1]+blockB[2];a[0]=blockB[3]}function zeroX(a){for(var b=0;16>b;b++)a[b]=0}
-function MDfinish(a,b,c,d){var e=Array(16);zeroX(e);for(var f=0,h=0;h<(c&63);h++)e[h>>>2]^=(b.charCodeAt(f++)&255)<<8*(h&3);e[c>>>2&15]^=1<<8*(c&3)+7;55<(c&63)&&(compress(a,e),e=Array(16),zeroX(e));e[14]=c<<3;e[15]=c>>>29|d<<3;compress(a,e)}function BYTES_TO_DWORD(a){var b=(a.charCodeAt(3)&255)<<24,b=b|(a.charCodeAt(2)&255)<<16,b=b|(a.charCodeAt(1)&255)<<8;return b|=a.charCodeAt(0)&255}
-function RMD(a){var b=Array(RMDsize/32),c=Array(RMDsize/8),d,e;MDinit(b);d=a.length;var f=Array(16);zeroX(f);var h=0;for(e=d;63<e;e-=64){for(var g=0;16>g;g++)f[g]=BYTES_TO_DWORD(a.substr(h,4)),h+=4;compress(b,f)}MDfinish(b,a.substr(h),d,0);for(g=0;g<RMDsize/8;g+=4)c[g]=b[g>>>2]&255,c[g+1]=b[g>>>2]>>>8&255,c[g+2]=b[g>>>2]>>>16&255,c[g+3]=b[g>>>2]>>>24&255;return c}function RMDstring(a){for(var a=RMD(a),b="",c=0;c<RMDsize/8;c++)b+=String.fromCharCode(a[c]);return b}function Blowfish(){}
-Blowfish.prototype.BLOCKSIZE=8;
-Blowfish.prototype.SBOXES=[[3509652390,2564797868,805139163,3491422135,3101798381,1780907670,3128725573,4046225305,614570311,3012652279,134345442,2240740374,1667834072,1901547113,2757295779,4103290238,227898511,1921955416,1904987480,2182433518,2069144605,3260701109,2620446009,720527379,3318853667,677414384,3393288472,3101374703,2390351024,1614419982,1822297739,2954791486,3608508353,3174124327,2024746970,1432378464,3864339955,2857741204,1464375394,1676153920,1439316330,715854006,3033291828,289532110,
-2706671279,2087905683,3018724369,1668267050,732546397,1947742710,3462151702,2609353502,2950085171,1814351708,2050118529,680887927,999245976,1800124847,3300911131,1713906067,1641548236,4213287313,1216130144,1575780402,4018429277,3917837745,3693486850,3949271944,596196993,3549867205,258830323,2213823033,772490370,2760122372,1774776394,2652871518,566650946,4142492826,1728879713,2882767088,1783734482,3629395816,2517608232,2874225571,1861159788,326777828,3124490320,2130389656,2716951837,967770486,1724537150,
-2185432712,2364442137,1164943284,2105845187,998989502,3765401048,2244026483,1075463327,1455516326,1322494562,910128902,469688178,1117454909,936433444,3490320968,3675253459,1240580251,122909385,2157517691,634681816,4142456567,3825094682,3061402683,2540495037,79693498,3249098678,1084186820,1583128258,426386531,1761308591,1047286709,322548459,995290223,1845252383,2603652396,3431023940,2942221577,3202600964,3727903485,1712269319,422464435,3234572375,1170764815,3523960633,3117677531,1434042557,442511882,
-3600875718,1076654713,1738483198,4213154764,2393238008,3677496056,1014306527,4251020053,793779912,2902807211,842905082,4246964064,1395751752,1040244610,2656851899,3396308128,445077038,3742853595,3577915638,679411651,2892444358,2354009459,1767581616,3150600392,3791627101,3102740896,284835224,4246832056,1258075500,768725851,2589189241,3069724005,3532540348,1274779536,3789419226,2764799539,1660621633,3471099624,4011903706,913787905,3497959166,737222580,2514213453,2928710040,3937242737,1804850592,3499020752,
-2949064160,2386320175,2390070455,2415321851,4061277028,2290661394,2416832540,1336762016,1754252060,3520065937,3014181293,791618072,3188594551,3933548030,2332172193,3852520463,3043980520,413987798,3465142937,3030929376,4245938359,2093235073,3534596313,375366246,2157278981,2479649556,555357303,3870105701,2008414854,3344188149,4221384143,3956125452,2067696032,3594591187,2921233993,2428461,544322398,577241275,1471733935,610547355,4027169054,1432588573,1507829418,2025931657,3646575487,545086370,48609733,
-2200306550,1653985193,298326376,1316178497,3007786442,2064951626,458293330,2589141269,3591329599,3164325604,727753846,2179363840,146436021,1461446943,4069977195,705550613,3059967265,3887724982,4281599278,3313849956,1404054877,2845806497,146425753,1854211946],[1266315497,3048417604,3681880366,3289982499,290971E4,1235738493,2632868024,2414719590,3970600049,1771706367,1449415276,3266420449,422970021,1963543593,2690192192,3826793022,1062508698,1531092325,1804592342,2583117782,2714934279,4024971509,1294809318,
-4028980673,1289560198,2221992742,1669523910,35572830,157838143,1052438473,1016535060,1802137761,1753167236,1386275462,3080475397,2857371447,1040679964,2145300060,2390574316,1461121720,2956646967,4031777805,4028374788,33600511,2920084762,1018524850,629373528,3691585981,3515945977,2091462646,2486323059,586499841,988145025,935516892,3367335476,2599673255,2839830854,265290510,3972581182,2759138881,3795373465,1005194799,847297441,406762289,1314163512,1332590856,1866599683,4127851711,750260880,613907577,
-1450815602,3165620655,3734664991,3650291728,3012275730,3704569646,1427272223,778793252,1343938022,2676280711,2052605720,1946737175,3164576444,3914038668,3967478842,3682934266,1661551462,3294938066,4011595847,840292616,3712170807,616741398,312560963,711312465,1351876610,322626781,1910503582,271666773,2175563734,1594956187,70604529,3617834859,1007753275,1495573769,4069517037,2549218298,2663038764,504708206,2263041392,3941167025,2249088522,1514023603,1998579484,1312622330,694541497,2582060303,2151582166,
-1382467621,776784248,2618340202,3323268794,2497899128,2784771155,503983604,4076293799,907881277,423175695,432175456,1378068232,4145222326,3954048622,3938656102,3820766613,2793130115,2977904593,26017576,3274890735,3194772133,1700274565,1756076034,4006520079,3677328699,720338349,1533947780,354530856,688349552,3973924725,1637815568,332179504,3949051286,53804574,2852348879,3044236432,1282449977,3583942155,3416972820,4006381244,1617046695,2628476075,3002303598,1686838959,431878346,2686675385,1700445008,
-1080580658,1009431731,832498133,3223435511,2605976345,2271191193,2516031870,1648197032,4164389018,2548247927,300782431,375919233,238389289,3353747414,2531188641,2019080857,1475708069,455242339,2609103871,448939670,3451063019,1395535956,2413381860,1841049896,1491858159,885456874,4264095073,4001119347,1565136089,3898914787,1108368660,540939232,1173283510,2745871338,3681308437,4207628240,3343053890,4016749493,1699691293,1103962373,3625875870,2256883143,3830138730,1031889488,3479347698,1535977030,4236805024,
-3251091107,2132092099,1774941330,1199868427,1452454533,157007616,2904115357,342012276,595725824,1480756522,206960106,497939518,591360097,863170706,2375253569,3596610801,1814182875,2094937945,3421402208,1082520231,3463918190,2785509508,435703966,3908032597,1641649973,2842273706,3305899714,1510255612,2148256476,2655287854,3276092548,4258621189,236887753,3681803219,274041037,1734335097,3815195456,3317970021,1899903192,1026095262,4050517792,356393447,2410691914,3873677099,3682840055],[3913112168,2491498743,
-4132185628,2489919796,1091903735,1979897079,3170134830,3567386728,3557303409,857797738,1136121015,1342202287,507115054,2535736646,337727348,3213592640,1301675037,2528481711,1895095763,1721773893,3216771564,62756741,2142006736,835421444,2531993523,1442658625,3659876326,2882144922,676362277,1392781812,170690266,3921047035,1759253602,3611846912,1745797284,664899054,1329594018,3901205900,3045908486,2062866102,2865634940,3543621612,3464012697,1080764994,553557557,3656615353,3996768171,991055499,499776247,
-1265440854,648242737,3940784050,980351604,3713745714,1749149687,3396870395,4211799374,3640570775,1161844396,3125318951,1431517754,545492359,4268468663,3499529547,1437099964,2702547544,3433638243,2581715763,2787789398,1060185593,1593081372,2418618748,4260947970,69676912,2159744348,86519011,2512459080,3838209314,1220612927,3339683548,133810670,1090789135,1078426020,1569222167,845107691,3583754449,4072456591,1091646820,628848692,1613405280,3757631651,526609435,236106946,48312990,2942717905,3402727701,
-1797494240,859738849,992217954,4005476642,2243076622,3870952857,3732016268,765654824,3490871365,2511836413,1685915746,3888969200,1414112111,2273134842,3281911079,4080962846,172450625,2569994100,980381355,4109958455,2819808352,2716589560,2568741196,3681446669,3329971472,1835478071,660984891,3704678404,4045999559,3422617507,3040415634,1762651403,1719377915,3470491036,2693910283,3642056355,3138596744,1364962596,2073328063,1983633131,926494387,3423689081,2150032023,4096667949,1749200295,3328846651,309677260,
-2016342300,1779581495,3079819751,111262694,1274766160,443224088,298511866,1025883608,3806446537,1145181785,168956806,3641502830,3584813610,1689216846,3666258015,3200248200,1692713982,2646376535,4042768518,1618508792,1610833997,3523052358,4130873264,2001055236,3610705100,2202168115,4028541809,2961195399,1006657119,2006996926,3186142756,1430667929,3210227297,1314452623,4074634658,4101304120,2273951170,1399257539,3367210612,3027628629,1190975929,2062231137,2333990788,2221543033,2438960610,1181637006,
-548689776,2362791313,3372408396,3104550113,3145860560,296247880,1970579870,3078560182,3769228297,1714227617,3291629107,3898220290,166772364,1251581989,493813264,448347421,195405023,2709975567,677966185,3703036547,1463355134,2715995803,1338867538,1343315457,2802222074,2684532164,233230375,2599980071,2000651841,3277868038,1638401717,4028070440,3237316320,6314154,819756386,300326615,590932579,1405279636,3267499572,3150704214,2428286686,3959192993,3461946742,1862657033,1266418056,963775037,2089974820,
-2263052895,1917689273,448879540,3550394620,3981727096,150775221,3627908307,1303187396,508620638,2975983352,2726630617,1817252668,1876281319,1457606340,908771278,3720792119,3617206836,2455994898,1729034894,1080033504],[976866871,3556439503,2881648439,1522871579,1555064734,1336096578,3548522304,2579274686,3574697629,3205460757,3593280638,3338716283,3079412587,564236357,2993598910,1781952180,1464380207,3163844217,3332601554,1699332808,1393555694,1183702653,3581086237,1288719814,691649499,2847557200,
-2895455976,3193889540,2717570544,1781354906,1676643554,2592534050,3230253752,1126444790,2770207658,2633158820,2210423226,2615765581,2414155088,3127139286,673620729,2805611233,1269405062,4015350505,3341807571,4149409754,1057255273,2012875353,2162469141,2276492801,2601117357,993977747,3918593370,2654263191,753973209,36408145,2530585658,25011837,3520020182,2088578344,530523599,2918365339,1524020338,1518925132,3760827505,3759777254,1202760957,3985898139,3906192525,674977740,4174734889,2031300136,2019492241,
-3983892565,4153806404,3822280332,352677332,2297720250,60907813,90501309,3286998549,1016092578,2535922412,2839152426,457141659,509813237,4120667899,652014361,1966332200,2975202805,55981186,2327461051,676427537,3255491064,2882294119,3433927263,1307055953,942726286,933058658,2468411793,3933900994,4215176142,1361170020,2001714738,2830558078,3274259782,1222529897,1679025792,2729314320,3714953764,1770335741,151462246,3013232138,1682292957,1483529935,471910574,1539241949,458788160,3436315007,1807016891,
-3718408830,978976581,1043663428,3165965781,1927990952,4200891579,2372276910,3208408903,3533431907,1412390302,2931980059,4132332400,1947078029,3881505623,4168226417,2941484381,1077988104,1320477388,886195818,18198404,3786409E3,2509781533,112762804,3463356488,1866414978,891333506,18488651,661792760,1628790961,3885187036,3141171499,876946877,2693282273,1372485963,791857591,2686433993,3759982718,3167212022,3472953795,2716379847,445679433,3561995674,3504004811,3574258232,54117162,3331405415,2381918588,
-3769707343,4154350007,1140177722,4074052095,668550556,3214352940,367459370,261225585,2610173221,4209349473,3468074219,3265815641,314222801,3066103646,3808782860,282218597,3406013506,3773591054,379116347,1285071038,846784868,2669647154,3771962079,3550491691,2305946142,453669953,1268987020,3317592352,3279303384,3744833421,2610507566,3859509063,266596637,3847019092,517658769,3462560207,3443424879,370717030,4247526661,2224018117,4143653529,4112773975,2788324899,2477274417,1456262402,2901442914,1517677493,
-1846949527,2295493580,3734397586,2176403920,1280348187,1908823572,3871786941,846861322,1172426758,3287448474,3383383037,1655181056,3139813346,901632758,1897031941,2986607138,3066810236,3447102507,1393639104,373351379,950779232,625454576,3124240540,4148612726,2007998917,544563296,2244738638,2330496472,2058025392,1291430526,424198748,50039436,29584100,3605783033,2429876329,2791104160,1057563949,3255363231,3075367218,3463963227,1469046755,985887462]];
-Blowfish.prototype.PARRAY=[608135816,2242054355,320440878,57701188,2752067618,698298832,137296536,3964562569,1160258022,953160567,3193202383,887688300,3232508343,3380367581,1065670069,3041331479,2450970073,2306472731];Blowfish.prototype.NN=16;Blowfish.prototype._clean=function(a){0>a&&(a=(a&2147483647)+2147483648);return a};Blowfish.prototype._F=function(a){var b,c,d;d=a&255;a>>>=8;c=a&255;a>>>=8;b=a&255;a=this.sboxes[0][a>>>8&255]+this.sboxes[1][b];a^=this.sboxes[2][c];return a+=this.sboxes[3][d]};
-Blowfish.prototype._encrypt_block=function(a){var b=a[0],c=a[1],d;for(d=0;d<this.NN;++d)var b=b^this.parray[d],c=this._F(b)^c,e=b,b=c,c=e;b^=this.parray[this.NN+0];c^=this.parray[this.NN+1];a[0]=this._clean(c);a[1]=this._clean(b)};Blowfish.prototype.encrypt_block=function(a){var b,c=[0,0],d=this.BLOCKSIZE/2;for(b=0;b<this.BLOCKSIZE/2;++b)c[0]=c[0]<<8|a[b+0]&255,c[1]=c[1]<<8|a[b+d]&255;this._encrypt_block(c);a=[];for(b=0;b<this.BLOCKSIZE/2;++b)a[b+0]=c[0]>>>24-8*b&255,a[b+d]=c[1]>>>24-8*b&255;return a};
-Blowfish.prototype._decrypt_block=function(a){var b=a[0],c=a[1],d;for(d=this.NN+1;1<d;--d)var b=b^this.parray[d],c=this._F(b)^c,e=b,b=c,c=e;b^=this.parray[1];c^=this.parray[0];a[0]=this._clean(c);a[1]=this._clean(b)};
-Blowfish.prototype.init=function(a){var b,c=0;this.parray=[];for(b=0;b<this.NN+2;++b){var d=0,e;for(e=0;4>e;++e)d=d<<8|a[c]&255,++c>=a.length&&(c=0);this.parray[b]=this.PARRAY[b]^d}this.sboxes=[];for(b=0;4>b;++b){this.sboxes[b]=[];for(c=0;256>c;++c)this.sboxes[b][c]=this.SBOXES[b][c]}a=[0,0];for(b=0;b<this.NN+2;b+=2)this._encrypt_block(a),this.parray[b+0]=a[0],this.parray[b+1]=a[1];for(b=0;4>b;++b)for(c=0;256>c;c+=2)this._encrypt_block(a),this.sboxes[b][c+0]=a[0],this.sboxes[b][c+1]=a[1]};
-function BFencrypt(a,b){var c=new Blowfish;c.init(util.str2bin(b));return c.encrypt_block(a)}function desede(a,b){var c=b.substring(0,8),d=b.substring(8,16),e=b.substring(16,24);return util.str2bin(des(des_createKeys(e),des(des_createKeys(d),des(des_createKeys(c),util.bin2str(a),!0,0,null,null),!1,0,null,null),!0,0,null,null))}
-function des(a,b,c,d,e,f){var h=[16843776,0,65536,16843780,16842756,66564,4,65536,1024,16843776,16843780,1024,16778244,16842756,16777216,4,1028,16778240,16778240,66560,66560,16842752,16842752,16778244,65540,16777220,16777220,65540,0,1028,66564,16777216,65536,16843780,4,16842752,16843776,16777216,16777216,1024,16842756,65536,66560,16777220,1024,4,16778244,66564,16843780,65540,16842752,16778244,16777220,1028,66564,16843776,1028,16778240,16778240,0,65540,66560,0,16842756],g=[-2146402272,-2147450880,
+e.length);return{string:c+e,header:c,body:e}};this.write_public_key=function(a,b,c){var d=String.fromCharCode(4),d=d+c;switch(a){case 1:d+=String.fromCharCode(1);d+=b.n.toMPI();d+=b.ee.toMPI();break;default:util.print_error("openpgp.packet.keymaterial.js\nerror writing private key, unknown type :"+a)}a=openpgp_packet.write_packet_header(6,d.length);return{string:a+d,header:a,body:d}}}
+function openpgp_packet_marker(){this.tagType=10;this.read_packet=function(a,b){this.packetLength=3;return 80==a[b].charCodeAt()&&71==a[b+1].charCodeAt()&&80==a[b+2].charCodeAt()?this:null};this.toString=function(){return'5.8.  Marker Packet (Obsolete Literal Packet) (Tag 10)\n     packet reads: "PGP"\n'}}
+function openpgp_packet_modificationdetectioncode(){this.tagType=19;this.hash=null;this.read_packet=function(a,b,c){this.packetLength=c;if(20!=c)return util.print_error("openpgp.packet.modificationdetectioncode.js\ninvalid length for a modification detection code packet!"+c),null;this.hash=a.substring(b,b+20);return this};this.toString=function(){return"5.14 Modification detection code packet\n    bytes ("+this.hash.length+"): ["+util.hexstrdump(this.hash)+"]"}}
+function _openpgp_packet(){function a(b){result="";192>b?result+=String.fromCharCode(b):191<b&&8384>b?(result+=String.fromCharCode((b-192>>8)+192),result+=String.fromCharCode(b-192&255)):(result+=String.fromCharCode(255),result+=String.fromCharCode(b>>24&255),result+=String.fromCharCode(b>>16&255),result+=String.fromCharCode(b>>8&255),result+=String.fromCharCode(b&255));return result}this.encode_length=a;this.write_old_packet_header=function(b,a){var d="";256>a?(d+=String.fromCharCode(128|b<<2),d+=
+String.fromCharCode(a)):(65536>a?(d+=String.fromCharCode(b<<2|129),d+=String.fromCharCode(a>>8)):(d+=String.fromCharCode(b<<2|130),d+=String.fromCharCode(a>>24&255),d+=String.fromCharCode(a>>16&255),d+=String.fromCharCode(a>>8&255)),d+=String.fromCharCode(a&255));return d};this.write_packet_header=function(b,c){var d;d=""+String.fromCharCode(192|b);return d+=a(c)};this.read_packet=function(b,a){if(null==b||b.length<=a||2>b.substring(a).length||0==(b[a].charCodeAt()&128))return util.print_error("Error during parsing. This message / key is propably not containing a valid OpenPGP format."),
+null;var d=a,e=-1,f=-1,f=0;0!=(b[d].charCodeAt()&64)&&(f=1);var g;f?e=b[d].charCodeAt()&63:(e=(b[d].charCodeAt()&63)>>2,g=b[d].charCodeAt()&3);d++;var h=null,k=-1;if(f)if(192>b[d].charCodeAt())packet_length=b[d++].charCodeAt(),util.print_debug("1 byte length:"+packet_length);else if(192<=b[d].charCodeAt()&&224>b[d].charCodeAt())packet_length=(b[d++].charCodeAt()-192<<8)+b[d++].charCodeAt()+192,util.print_debug("2 byte length:"+packet_length);else if(223<b[d].charCodeAt()&&255>b[d].charCodeAt()){packet_length=
+1<<(b[d++].charCodeAt()&31);util.print_debug("4 byte length:"+packet_length);k=d+packet_length;for(h=b.substring(d,d+packet_length);;)if(192>b[k].charCodeAt()){f=b[k++].charCodeAt();packet_length+=f;h+=b.substring(k,k+f);k+=f;break}else if(192<=b[k].charCodeAt()&&224>b[k].charCodeAt()){f=(b[k++].charCodeAt()-192<<8)+b[k++].charCodeAt()+192;packet_length+=f;h+=b.substring(k,k+f);k+=f;break}else if(223<b[k].charCodeAt()&&255>b[k].charCodeAt())f=1<<(b[k++].charCodeAt()&31),packet_length+=f,h+=b.substring(k,
+k+f),k+=f;else{k++;f=b[k++].charCodeAt()<<24|b[k++].charCodeAt()<<16|b[k++].charCodeAt()<<8|b[k++].charCodeAt();h+=b.substring(k,k+f);packet_length+=f;k+=f;break}}else d++,packet_length=b[d++].charCodeAt()<<24|b[d++].charCodeAt()<<16|b[d++].charCodeAt()<<8|b[d++].charCodeAt();else switch(g){case 0:packet_length=b[d++].charCodeAt();break;case 1:packet_length=b[d++].charCodeAt()<<8|b[d++].charCodeAt();break;case 2:packet_length=b[d++].charCodeAt()<<24|b[d++].charCodeAt()<<16|b[d++].charCodeAt()<<8|
+b[d++].charCodeAt()}-1==k&&(k=packet_length);null==h&&(h=b.substring(d,d+k));switch(e){case 0:break;case 1:e=new openpgp_packet_encryptedsessionkey;if(null!=e.read_pub_key_packet(h,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 2:e=new openpgp_packet_signature;if(null!=e.read_packet(h,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 3:e=new openpgp_packet_encryptedsessionkey;if(null!=e.read_symmetric_key_packet(h,0,packet_length))return e.headerLength=
+d-a,e.packetLength=k,e;break;case 4:e=new openpgp_packet_onepasssignature;if(e.read_packet(h,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 5:e=new openpgp_packet_keymaterial;e.header=b.substring(a,d);if(null!=e.read_tag5(h,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 6:e=new openpgp_packet_keymaterial;e.header=b.substring(a,d);if(null!=e.read_tag6(h,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 7:e=new openpgp_packet_keymaterial;
+if(null!=e.read_tag7(h,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 8:e=new openpgp_packet_compressed;if(null!=e.read_packet(h,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 9:e=new openpgp_packet_encrypteddata;if(null!=e.read_packet(h,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 10:e=new openpgp_packet_marker;if(null!=e.read_packet(h,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 11:e=new openpgp_packet_literaldata;
+if(null!=e.read_packet(h,0,packet_length))return e.headerLength=d-a,e.header=b.substring(a,d),e.packetLength=k,e;break;case 12:break;case 13:e=new openpgp_packet_userid;if(null!=e.read_packet(h,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 14:e=new openpgp_packet_keymaterial;e.header=b.substring(a,d);if(null!=e.read_tag14(h,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 17:e=new openpgp_packet_userattribute;if(null!=e.read_packet(h,0,packet_length))return e.headerLength=
+d-a,e.packetLength=k,e;break;case 18:e=new openpgp_packet_encryptedintegrityprotecteddata;if(null!=e.read_packet(h,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;case 19:e=new openpgp_packet_modificationdetectioncode;if(null!=e.read_packet(h,0,packet_length))return e.headerLength=d-a,e.packetLength=k,e;break;default:return util.print_error("openpgp.packet.js\n[ERROR] openpgp_packet: failed to parse packet @:"+d+"\nchar:'"+util.hexstrdump(b.substring(d))+"'\ninput:"+util.hexstrdump(b)),
+null}}}var openpgp_packet=new _openpgp_packet;
+function openpgp_packet_literaldata(){this.tagType=11;this.read_packet=function(a,b,c){this.packetLength=c;this.format=a[b];this.filename=a.substr(b+2,a.charCodeAt(b+1));this.date=new Date(1E3*parseInt(a.substr(b+2+a.charCodeAt(b+1),4)));this.data=a.substring(b+6+a.charCodeAt(b+1));return this};this.toString=function(){return"5.9.  Literal Data Packet (Tag 11)\n    length: "+this.packetLength+"\n    format: "+this.format+"\n    filename:"+this.filename+"\n    date:   "+this.date+"\n    data:  |"+
+this.data+"|\n    rdata: |"+this.real_data+"|\n"};this.write_packet=function(a){a=a.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n");this.filename="msg.txt";this.date=new Date;this.format="t";var b=openpgp_packet.write_packet_header(11,a.length+6+this.filename.length),b=b+this.format,b=b+String.fromCharCode(this.filename.length),b=b+this.filename,b=b+String.fromCharCode(Math.round(this.date.getTime()/1E3)>>24&255),b=b+String.fromCharCode(Math.round(this.date.getTime()/1E3)>>16&255),b=b+String.fromCharCode(Math.round(this.date.getTime()/
+1E3)>>8&255),b=b+String.fromCharCode(Math.round(this.date.getTime()/1E3)&255);this.data=a;return b+a}}
+function openpgp_packet_compressed(){this.tagType=8;this.read_packet=function(a,b,c){this.packetLength=c;var d=b;this.type=a.charCodeAt(d++);this.compressedData=a.substring(b+1,b+c);return this};this.toString=function(){return"5.6.  Compressed Data Packet (Tag 8)\n    length:  "+this.packetLength+"\n    Compression Algorithm = "+this.type+"\n    Compressed Data: Byte ["+util.hexstrdump(this.compressedData)+"]\n"};this.compress=function(a,b){this.type=a;this.decompressedData=b;switch(this.type){case 0:this.compressedData=
+this.decompressedData;break;case 1:util.print_error("Compression algorithm ZIP [RFC1951] is not implemented.");break;case 2:util.print_error("Compression algorithm ZLIB [RFC1950] is not implemented.");break;case 3:util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");break;default:util.print_error("Compression algorithm unknown :"+this.type)}this.packetLength=this.compressedData.length+1;return this.compressedData};this.decompress=function(){if(null!=this.decompressedData)return this.decompressedData;
+if(null==this.type)return null;switch(this.type){case 0:this.decompressedData=this.compressedData;break;case 1:var a=this.compressedData,a=s2r(a).replace(/\n/g,""),a=new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(a)),a=unescape(a.deflate()[0][0]),a=openpgp_packet.read_packet(a,0,a.length);util.print_info("Decompressed packet [Type 1-ZIP]: "+a);this.decompressedData=a.data;break;case 2:8==this.compressedData.charCodeAt(0)%16?(a=this.compressedData.substring(0,this.compressedData.length-4),a=s2r(a).replace(/\n/g,
+""),a=JXG.decompress(a),a=openpgp_packet.read_packet(a,0,a.length),util.print_info("Decompressed packet [Type 2-ZLIB]: "+a),this.decompressedData=a.data):util.print_error("Compression algorithm ZLIB only supports DEFLATE compression method.");break;case 3:util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");break;default:util.print_error("Compression algorithm unknown :"+this.type)}util.print_debug("decompressed:"+util.hexstrdump(this.decompressedData));return this.decompressedData};
+this.write_packet=function(a,b){this.decompressedData=b;if(null==a)this.type=1;var c=String.fromCharCode(this.type)+this.compress(this.type);return openpgp_packet.write_packet_header(8,c.length)+c}}
+function openpgp_packet_userid(){this.tagType=13;this.certificationSignatures=[];this.certificationRevocationSignatures=[];this.revocationSignatures=[];this.parentNode=null;this.hasCertificationRevocationSignature=function(a){for(var b=0;b<this.certificationRevocationSignatures.length;b++)if(3==this.certificationRevocationSignatures[b].version&&this.certificationRevocationSignatures[b].keyId==a||4==this.certificationRevocationSignatures[b].version&&this.certificationRevocationSignatures[b].issuerKeyId==
+a)return this.certificationRevocationSignatures[b];return null};this.verifyCertificationSignatures=function(a){result=[];for(var b=0;b<this.certificationSignatures.length;b++)if(4==this.certificationSignatures[b].version)if(null!=this.certificationSignatures[b].signatureExpirationTime&&null!=this.certificationSignatures[b].signatureExpirationTime&&0!=this.certificationSignatures[b].signatureExpirationTime&&!this.certificationSignatures[b].signatureNeverExpires&&new Date(this.certificationSignatures[b].creationTime.getTime()+
+1E3*this.certificationSignatures[b].signatureExpirationTime)<new Date)result[b]=this.certificationSignatures[b].issuerKeyId==a.getKeyId()?5:1;else if(null==this.certificationSignatures[b].issuerKeyId)result[b]=0;else{var c=openpgp.keyring.getPublicKeysForKeyId(this.certificationSignatures[b].issuerKeyId);if(null==c||0==c.length)result[b]=2;else if(c=c[0],c=c.obj.getSigningKey(),null==c)result[b]=0;else{var d=this.hasCertificationRevocationSignature(this.certificationSignatures[b].issuerKeyId);if(null!=
+d&&d.creationTime>this.certificationSignatures[b].creationTime){var e=String.fromCharCode(153)+a.header.substring(1)+a.data+String.fromCharCode(180)+String.fromCharCode(this.text.length>>24&255)+String.fromCharCode(this.text.length>>16&255)+String.fromCharCode(this.text.length>>8&255)+String.fromCharCode(this.text.length&255)+this.text;if(d.verify(e,c)){result[b]=this.certificationSignatures[b].issuerKeyId==a.getKeyId()?6:3;continue}}e=String.fromCharCode(153)+a.header.substring(1)+a.data+String.fromCharCode(180)+
+String.fromCharCode(this.text.length>>24&255)+String.fromCharCode(this.text.length>>16&255)+String.fromCharCode(this.text.length>>8&255)+String.fromCharCode(this.text.length&255)+this.text;result[b]=this.certificationSignatures[b].verify(e,c)?4:0}}else if(3==this.certificationSignatures[b].version)if(null==this.certificationSignatures[b].keyId)result[b]=0;else if(c=openpgp.keyring.getPublicKeysForKeyId(this.certificationSignatures[b].keyId),null==c||0==c.length)result[b]=2;else if(c=publicKey.obj.getSigningKey(),
+null==c)result[b]=0;else{d=this.hasCertificationRevocationSignature(this.certificationSignatures[b].keyId);if(null!=d&&d.creationTime>this.certificationSignatures[b].creationTime&&(e=String.fromCharCode(153)+this.publicKeyPacket.header.substring(1)+this.publicKeyPacket.data+this.text,d.verify(e,c))){result[b]=d.keyId==a.getKeyId()?6:3;continue}e=String.fromCharCode(153)+a.header.substring(1)+a.data+this.text;result[b]=this.certificationSignatures[b].verify(e,c)?4:0}else result[b]=0;return result};
+this.verify=function(a){a=this.verifyCertificationSignatures(a);return-1!=a.indexOf(6)?2:-1!=a.indexOf(5)?1:0};this.read_packet=function(a,b,c){this.text="";this.packetLength=c;for(var d=0;d<c;d++)this.text+=a[b+d];return this};this.write_packet=function(a){this.text=a;a=openpgp_packet.write_packet_header(13,this.text.length);return a+=this.text};this.toString=function(){for(var a="     5.11.  User ID Packet (Tag 13)\n    text ("+this.text.length+'): "'+this.text.replace("<","&lt;")+'"\n',a=a+"certification signatures:\n",
+b=0;b<this.certificationSignatures.length;b++)a+="        "+this.certificationSignatures[b].toString();a+="certification revocation signatures:\n";for(b=0;b<this.certificationRevocationSignatures.length;b++)a+="        "+this.certificationRevocationSignatures[b].toString();return a};this.read_nodes=function(a,b,c,d){if(6==a.tagType){this.parentNode=a;for(var e=c,f=d;b.length!=e;){var g=openpgp_packet.read_packet(b,e,f-(e-c));if(null==g){util.print_error("[user_id] parsing ends here @:"+e+" l:"+f);
+break}else switch(e+=g.packetLength+g.headerLength,f=b.length-e,g.tagType){case 2:if(15<g.signatureType&&20>g.signatureType){this.certificationSignatures[this.certificationSignatures.length]=g;break}else if(48==g.signatureType){this.certificationRevocationSignatures[this.certificationRevocationSignatures.length]=g;break}else if(24==g.signatureType){this.certificationSignatures[this.certificationSignatures.length]=g;break}else util.debug("unknown sig t: "+g.signatureType+"@"+(e-(g.packetLength+g.headerLength)));
+default:return this.data=b,this.position=c-a.packetLength,this.len=e-c-(g.headerLength+g.packetLength)}}this.data=b;this.position=c-a.packetLength;return this.len=e-c-(g.headerLength+g.packetLength)}if(5==a.tagType){this.parentNode=a;for(e=c;b.length!=e;)if(g=openpgp_packet.read_packet(b,e,f-(e-c)),null==g){util.print_error("parsing ends here @:"+e+" l:"+f);break}else switch(e+=g.packetLength+g.headerLength,g.tagType){case 2:15<g.signatureType&&20>g.signatureType?this.certificationSignatures[this.certificationSignatures.length]=
+g:48==g.signatureType&&(this.certificationRevocationSignatures[this.certificationRevocationSignatures.length]=g);default:return this.data=b,this.position=c-a.packetLength,this.len=e-c-(g.headerLength+g.packetLength)}}else util.print_error("unknown parent node for a userId packet "+a.tagType)}}
+function openpgp_packet_encryptedintegrityprotecteddata(){this.tagType=18;this.hash=this.decrytpedData=this.encryptedData=this.packetLength=this.version=null;this.write_packet=function(a,b,c){var d=openpgp_crypto_getPrefixRandom(a),e=d+d.charAt(d.length-2)+d.charAt(d.length-1),c=c+String.fromCharCode(211),c=c+String.fromCharCode(20);util.print_debug_hexstr_dump("data to be hashed:",e+c);c+=str_sha1(e+c);util.print_debug_hexstr_dump("hash:",c.substring(c.length-20,c.length));a=openpgp_crypto_symmetricEncrypt(d,
+a,b,c,!1).substring(0,e.length+c.length);b=openpgp_packet.write_packet_header(18,a.length+1)+String.fromCharCode(1);this.encryptedData=a;return b+a};this.read_packet=function(a,b,c){this.packetLength=c;this.version=a[b].charCodeAt();if(1!=this.version)return util.print_error("openpgp.packet.encryptedintegrityprotecteddata.js\nunknown encrypted integrity protected data packet version: "+this.version+" , @ "+b+"hex:"+util.hexstrdump(a)),null;this.encryptedData=a.substring(b+1,b+1+c);util.print_debug("openpgp.packet.encryptedintegrityprotecteddata.js\n"+
+this.toString());return this};this.toString=function(){var a="";openpgp.config.debug&&(a="    data: Bytes ["+util.hexstrdump(this.encryptedData)+"]");return"5.13.  Sym. Encrypted Integrity Protected Data Packet (Tag 18)\n    length:  "+this.packetLength+"\n    version: "+this.version+"\n"+a};this.decrypt=function(a,b){this.decryptedData=openpgp_crypto_symmetricDecrypt(a,b,this.encryptedData,!1);this.hash=str_sha1(openpgp_crypto_MDCSystemBytes(a,b,this.encryptedData)+this.decryptedData.substring(0,
+this.decryptedData.length-20));util.print_debug_hexstr_dump("calc hash = ",this.hash);if(this.hash==this.decryptedData.substring(this.decryptedData.length-20,this.decryptedData.length))return this.decryptedData;util.print_error("Decryption stopped: discovered a modification of encrypted data.");return null}}
+function openpgp_packet_onepasssignature(){this.tagType=4;this.flags=this.signingKeyId=this.publicKeyAlgorithm=this.hashAlgorithm=this.version=null;this.read_packet=function(a,b,c){this.packetLength=c;this.version=a.charCodeAt(b++);this.type=a.charCodeAt(b++);this.hashAlgorithm=a.charCodeAt(b++);this.publicKeyAlgorithm=a.charCodeAt(b++);this.signingKeyId=new openpgp_type_keyid;this.signingKeyId.read_packet(a,b);b+=8;this.flags=a.charCodeAt(b++);return this};this.toString=function(){return"5.4.  One-Pass Signature Packets (Tag 4)\n    length: "+
+this.packetLength+"\n    type:   "+this.type+"\n    keyID:  "+this.signingKeyId.toString()+"\n    hashA:  "+this.hashAlgorithm+"\n    pubKeyA:"+this.publicKeyAlgorithm+"\n    flags:  "+this.flags+"\n    version:"+this.version+"\n"};this.write_packet=function(a,b,c,d,e){d=""+openpgp_packet.write_packet_header(4,13);d+=String.fromCharCode(3);d+=String.fromCharCode(a);d+=String.fromCharCode(b);d+=String.fromCharCode(c.privateKeyPacket.publicKey.publicKeyAlgorithm);d+=c.getKeyId();return d=e?d+String.fromCharCode(0):
+d+String.fromCharCode(1)}}
+function openpgp_config(){this.config=null;this.default_config={prefer_hash_algorithm:2,encryption_cipher:9,compression:1,show_version:!0,show_comment:!0,integrity_protect:!0,composition_behavior:0,keyserver:"keyserver.linux.it"};this.versionstring="OpenPGP.js v.1.20120827";this.commentstring="http://openpgpjs.org";this.debug=!1;this.read=function(){var a=JSON.parse(window.localStorage.getItem("config"));null==a?(this.config=this.default_config,this.write()):this.config=a};this.write=function(){window.localStorage.setItem("config",
+JSON.stringify(this.config))}}
+function openpgp_type_s2k(){this.read=function(a,b){var c=b;this.type=a[c++].charCodeAt();switch(this.type){case 0:this.hashAlgorithm=a[c++].charCodeAt();this.s2kLength=1;break;case 1:this.hashAlgorithm=a[c++].charCodeAt();this.saltValue=a.substring(c,c+8);this.s2kLength=9;break;case 3:this.hashAlgorithm=a[c++].charCodeAt();this.saltValue=a.substring(c,c+8);c+=8;this.EXPBIAS=6;c=a[c++].charCodeAt();this.count=16+(c&15)<<(c>>4)+this.EXPBIAS;this.s2kLength=10;break;default:util.print_error("unknown s2k type! "+this.type)}return this};
+this.write=function(a,b,c,d,e){this.type=a;if(3==this.type)this.saltValue=d,this.hashAlgorithm=b,this.count=16+(e&15)<<(e>>4)+6,this.s2kLength=10;return this.produce_key(c)};this.produce_key=function(a,b){if(0==this.type)return openpgp_crypto_hashData(this.hashAlgorithm,a);if(1==this.type)return openpgp_crypto_hashData(this.hashAlgorithm,this.saltValue+a);if(3==this.type){var c=[];for(c[0]=this.saltValue+a;c.length*(this.saltValue+a).length<this.count;)c.push(this.saltValue+a);c=c.join("");c.length>
+this.count&&(c=c.substr(0,this.count));return b&&(24==b||32==b)?openpgp_crypto_hashData(this.hashAlgorithm,c)+openpgp_crypto_hashData(this.hashAlgorithm,String.fromCharCode(0)+c):openpgp_crypto_hashData(this.hashAlgorithm,c)}return null}}
+function openpgp_type_mpi(){this.data=this.mpiByteLength=this.mpiBitLength=this.MPI=null;this.read=function(a,b){var c=b;this.mpiBitLength=a[c++].charCodeAt()<<8|a[c++].charCodeAt();this.mpiByteLength=(this.mpiBitLength-this.mpiBitLength%8)/8;0!=this.mpiBitLength%8&&this.mpiByteLength++;this.MPI=a.substring(c,c+this.mpiByteLength);this.data=a.substring(b,b+2+this.mpiByteLength);this.packetLength=this.mpiByteLength+2;return this};this.toBigInteger=function(){return new BigInteger(util.hexstrdump(this.MPI),
+16)};this.toString=function(){var a="    MPI("+this.mpiBitLength+"b/"+this.mpiByteLength+"B) : 0x",a=a+util.hexstrdump(this.MPI);return a+"\n"};this.create=function(a){this.MPI=a;var b=8*(a.length-1),c;a:for(var d=a.charCodeAt(0),e=0;9>e;e++)if(0==d>>e){c=e;break a}this.mpiBitLength=b+c;this.mpiByteLength=a.length;return this};this.toBin=function(){var a=String.fromCharCode(this.mpiBitLength>>8&255),a=a+String.fromCharCode(this.mpiBitLength&255);return a+=this.MPI};this.getByteLength=function(){return this.mpiByteLength}}
+function openpgp_type_keyid(){this.read_packet=function(a,b){this.bytes=a.substring(b,b+8);return this};this.toString=function(){return util.hexstrdump(this.bytes)}}
+function openpgp_msg_message(){this.text="";this.decrypt=function(a,b){return this.decryptAndVerifySignature(a,b).text};this.decryptAndVerifySignature=function(a,b,c){if(null==a||null==b||""==b)return null;a=b.decrypt(this,a.keymaterial);if(null==a)return null;var d,b=0,e=a.length,f=[];for(util.print_debug_hexstr_dump("openpgp.msg.messge decrypt:\n",a);b!=a.length&&null!=(d=openpgp_packet.read_packet(a,b,e));){if(8==d.tagType)this.text=d.decompress(),a=d.decompress();util.print_debug(d.toString());
+b+=d.headerLength+d.packetLength;38<b&&util.print_debug_hexstr_dump("openpgp.msg.messge decrypt:\n",a.substring(b));e=a.length-b;if(11==d.tagType)this.text=d.data,util.print_info("message successfully decrypted");if(19!=d.tagType&&2==d.tagType&&3>d.signatureType){if(!c||0==c.length)c=openpgp.keyring.getPublicKeysForKeyId(d.issuerKeyId);0==c.length?(util.print_warning("Unable to verify signature of issuer: "+util.hexstrdump(d.issuerKeyId)+". Public key not found in keyring."),f[f.length]=!1):d.verify(this.text.replace(/\r\n/g,
+"\n").replace(/\n/g,"\r\n"),c[0])&&c[0].obj.validate()?(util.print_info("Found Good Signature from "+c[0].obj.userIds[0].text+" (0x"+util.hexstrdump(c[0].obj.getKeyId()).substring(8)+")"),f[f.length]=!0):(util.print_error("Signature verification failed: Bad Signature from "+c[0].obj.userIds[0].text+" (0x"+util.hexstrdump(c[0].obj.getKeyId()).substring(8)+")"),f[f.length]=!1)}}if(""==this.text)this.text=a;return{text:this.text,validSignatures:f}};this.verifySignature=function(a){var b=!1;if(2==this.type){if(!a||
+0==a.length)if(4==this.signature.version)a=openpgp.keyring.getPublicKeysForKeyId(this.signature.issuerKeyId);else if(3==this.signature.version)a=openpgp.keyring.getPublicKeysForKeyId(this.signature.keyId);else return util.print_error("unknown signature type on message!"),!1;if(0==a.length)util.print_warning("Unable to verify signature of issuer: "+util.hexstrdump(this.signature.issuerKeyId)+". Public key not found in keyring.");else for(var c=0;c<a.length;c++){var d=this.text.replace(/\r\n/g,"\n").replace(/\n/g,
+"\r\n");this.signature.verify(d.substring(0,d.length-2),a[c])?(util.print_info("Found Good Signature from "+a[c].obj.userIds[c].text+" (0x"+util.hexstrdump(a[c].obj.getKeyId()).substring(8)+")"),b=!0):util.print_error("Signature verification failed: Bad Signature from "+a[c].obj.userIds[0].text+" (0x"+util.hexstrdump(a[0].obj.getKeyId()).substring(8)+")")}}return b};this.toString=function(){var a="Session Keys:\n";if(null!=this.sessionKeys)for(var b=0;b<this.sessionKeys.length;b++)a+=this.sessionKeys[b].toString();
+a+="\n\n EncryptedData:\n";null!=this.encryptedData&&(a+=this.encryptedData.toString());a+="\n\n Signature:\n";null!=this.signature&&(a+=this.signature.toString());a+="\n\n Text:\n";null!=this.signature&&(a+=this.text);return a}}
+var Util=function(){this.emailRegEx=/[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;this.hexdump=function(a){for(var b=[],c=a.length,d=0,e,f=0;d<c;){for(e=a.charCodeAt(d++).toString(16);2>e.length;)e="0"+e;b.push(" "+e);f++;0==f%32&&b.push("\n           ")}return b.join("")};this.hexstrdump=function(a){if(null==a)return"";for(var b=[],c=a.length,d=0,e;d<c;){for(e=a[d++].charCodeAt().toString(16);2>e.length;)e=
+"0"+e;b.push(""+e)}return b.join("")};this.hex2bin=function(a){for(var b="",c=0;c<a.length;c+=2)b+=String.fromCharCode(parseInt(a.substr(c,2),16));return b};this.hexidump=function(a){for(var b=[],c=a.length,d=0,e;d<c;){for(e=a[d++].toString(16);2>e.length;)e="0"+e;b.push(""+e)}return b.join("")};this.str2bin=function(a){for(var b=[],c=0;c<a.length;c++)b[c]=a.charCodeAt(c);return b};this.bin2str=function(a){for(var b=[],c=0;c<a.length;c++)b.push(String.fromCharCode(a[c]));return b.join("")};this.str2Uint8Array=
+function(a){for(var b=new Uint8Array(new ArrayBuffer(a.length)),c=0;c<a.length;c++)b[c]=a.charCodeAt(c);return b};this.Uint8Array2str=function(a){var b=[];for(n=0;n<a.length;n++)b[n]=String.fromCharCode(a[n]);return b.join("")};this.calc_checksum=function(a){for(var b={s:0,add:function(b){this.s=(this.s+b)%65536}},c=0;c<a.length;c++)b.add(a.charCodeAt(c));return b.s};this.print_debug=function(a){openpgp.config.debug&&(a=openpgp_encoding_html_encode(a),showMessages('<tt><p style="background-color: #ffffff; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;">'+
+a.replace(/\n/g,"<br>")+"</p></tt>"))};this.print_debug_hexstr_dump=function(a,b){openpgp.config.debug&&(a+=this.hexstrdump(b),a=openpgp_encoding_html_encode(a),showMessages('<tt><p style="background-color: #ffffff; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;">'+a.replace(/\n/g,"<br>")+"</p></tt>"))};this.print_error=function(a){a=openpgp_encoding_html_encode(a);showMessages('<p style="font-size: 80%; background-color: #FF8888; margin:0; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;"><span style="color: #888;"><b>ERROR:</b></span>\t'+
+a.replace(/\n/g,"<br>")+"</p>")};this.print_info=function(a){a=openpgp_encoding_html_encode(a);showMessages('<p style="font-size: 80%; background-color: #88FF88; margin:0; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;"><span style="color: #888;"><b>INFO:</b></span>\t'+a.replace(/\n/g,"<br>")+"</p>")};this.print_warning=function(a){a=openpgp_encoding_html_encode(a);showMessages('<p style="font-size: 80%; background-color: #FFAA88; margin:0; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;"><span style="color: #888;"><b>WARNING:</b></span>\t'+
+a.replace(/\n/g,"<br>")+"</p>")};this.getLeftNBits=function(a,b){var c=b%8;return 0==c?a.substring(0,b/8):this.shiftRight(a.substring(0,(b-c)/8+1),8-c)};this.shiftRight=function(a,b){var c=util.str2bin(a);if(0!=b%8)for(var d=c.length-1;0<=d;d--)c[d]>>=b%8,0<d&&(c[d]|=c[d-1]<<8-b%8&255);else return a;return util.bin2str(c)};this.get_hashAlgorithmString=function(a){switch(a){case 1:return"MD5";case 2:return"SHA1";case 3:return"RIPEMD160";case 8:return"SHA256";case 9:return"SHA384";case 10:return"SHA512";
+case 11:return"SHA224"}return"unknown"}},util=new Util;JXG={exists:function(a){return function(b){return!(b===a||null===b)}}()};JXG.decompress=function(a){return unescape((new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(a))).unzip()[0][0])};JXG.Util={};
+JXG.Util.Unzip=function(a){function b(){Q+=8;return ca<ea.length?ea[ca++]:-1}function c(){var a;Q++;a=da&1;da>>=1;0==da&&(da=b(),a=da&1,da=da>>1|128);return a}function d(b){for(var a=0,d=b;d--;)a=a<<1|c();b&&(a=fa[a]>>8-b);return a}function e(b){na++;o[A++]=b;l.push(String.fromCharCode(b));32768==A&&(A=0)}function f(){this.b1=this.b0=0;this.jump=null;this.jumppos=-1}function g(){for(;;){if(ga[T]>=sa)return-1;if(oa[ga[T]]==T)return ga[T]++;ga[T]++}}function h(){var b=P[ha],a;p&&document.write("<br>len:"+
+T+" treepos:"+ha);if(17==T)return-1;ha++;T++;a=g();p&&document.write("<br>IsPat "+a);if(0<=a)b.b0=a,p&&document.write("<br>b0 "+b.b0);else if(b.b0=32768,p&&document.write("<br>b0 "+b.b0),h())return-1;a=g();if(0<=a)b.b1=a,p&&document.write("<br>b1 "+b.b1),b.jump=null;else if(b.b1=32768,p&&document.write("<br>b1 "+b.b1),b.jump=P[ha],b.jumppos=ha,h())return-1;T--;return 0}function k(b,a,c,d){p&&document.write("currentTree "+b+" numval "+a+" lengths "+c+" show "+d);P=b;ha=0;oa=c;sa=a;for(b=0;17>b;b++)ga[b]=
+0;T=0;if(h())return p&&alert("invalid huffman tree\n"),-1;if(p){document.write("<br>Tree: "+P.length);for(b=0;32>b;b++)document.write("Places["+b+"].b0="+P[b].b0+"<br>"),document.write("Places["+b+"].b1="+P[b].b1+"<br>")}return 0}function j(b){for(var a,d,e=0,f=b[e];;)if(a=c(),p&&document.write("b="+a),a){if(!(f.b1&32768))return p&&document.write("ret1"),f.b1;f=f.jump;a=b.length;for(d=0;d<a;d++)if(b[d]===f){e=d;break}}else{if(!(f.b0&32768))return p&&document.write("ret2"),f.b0;e++;f=b[e]}p&&document.write("ret3");
+return-1}function m(){var a,h,g,E,m;do{a=c();g=d(2);switch(g){case 0:p&&alert("Stored\n");break;case 1:p&&alert("Fixed Huffman codes\n");break;case 2:p&&alert("Dynamic Huffman codes\n");break;case 3:p&&alert("Reserved block type!!\n");break;default:p&&alert("Unexpected value %d!\n",g)}if(0==g){da=1;g=b();g|=b()<<8;h=b();h|=b()<<8;for((g^~h)&65535&&document.write("BlockLen checksum mismatch\n");g--;)h=b(),e(h)}else if(1==g)for(;;)if(g=fa[d(7)]>>1,23<g?(g=g<<1|c(),199<g?(g-=128,g=g<<1|c()):(g-=48,143<
+g&&(g+=136))):g+=256,256>g)e(g);else if(256==g)break;else{var N;g-=257;m=d(O[g])+la[g];g=fa[d(5)]>>3;8<Z[g]?(N=d(8),N|=d(Z[g]-8)<<8):N=d(Z[g]);N+=M[g];for(g=0;g<m;g++)h=o[A-N&32767],e(h)}else if(2==g){var u=Array(320);h=257+d(5);N=1+d(5);E=4+d(4);for(g=0;19>g;g++)u[g]=0;for(g=0;g<E;g++)u[qa[g]]=d(3);m=K.length;for(E=0;E<m;E++)K[E]=new f;if(k(K,19,u,0))return A=0,1;if(p){document.write("<br>distanceTree");for(g=0;g<K.length;g++)document.write("<br>"+K[g].b0+" "+K[g].b1+" "+K[g].jump+" "+K[g].jumppos)}m=
+h+N;E=0;var Y=-1;for(p&&document.write("<br>n="+m+" bits: "+Q+"<br>");E<m;)if(Y++,g=j(K),p&&document.write("<br>"+Y+" i:"+E+" decode: "+g+"    bits "+Q+"<br>"),16>g)u[E++]=g;else if(16==g){var l;g=3+d(2);if(E+g>m)return A=0,1;for(l=E?u[E-1]:0;g--;)u[E++]=l}else{g=17==g?3+d(3):11+d(7);if(E+g>m)return A=0,1;for(;g--;)u[E++]=0}m=aa.length;for(E=0;E<m;E++)aa[E]=new f;if(k(aa,h,u,0))return A=0,1;m=aa.length;for(E=0;E<m;E++)K[E]=new f;g=[];for(E=h;E<u.length;E++)g[E-h]=u[E];if(k(K,N,g,0))return A=0,1;for(p&&
+document.write("<br>literalTree");;)if(g=j(aa),256<=g){g-=256;if(0==g)break;g--;m=d(O[g])+la[g];g=j(K);8<Z[g]?(N=d(8),N|=d(Z[g]-8)<<8):N=d(Z[g]);for(N+=M[g];m--;)h=o[A-N&32767],e(h)}else e(g)}}while(!a);A=0;da=1;return 0}function u(){p&&alert("NEXTFILE");l=[];var a=[];ka=!1;a[0]=b();a[1]=b();p&&alert("type: "+a[0]+" "+a[1]);120==a[0]&&218==a[1]&&(p&&alert("GEONExT-GZIP"),m(),p&&alert(l.join("")),z[L]=Array(2),z[L][0]=l.join(""),z[L][1]="geonext.gxt",L++);120==a[0]&&156==a[1]&&(p&&alert("ZLIB"),m(),
+p&&alert(l.join("")),z[L]=Array(2),z[L][0]=l.join(""),z[L][1]="ZLIB",L++);31==a[0]&&139==a[1]&&(p&&alert("GZIP"),D(),p&&alert(l.join("")),z[L]=Array(2),z[L][0]=l.join(""),z[L][1]="file",L++);if(80==a[0]&&75==a[1]&&(ka=!0,a[2]=b(),a[3]=b(),3==a[2]&&4==a[3])){a[0]=b();a[1]=b();p&&alert("ZIP-Version: "+a[1]+" "+a[0]/10+"."+a[0]%10);W=b();W|=b()<<8;p&&alert("gpflags: "+W);a=b();a|=b()<<8;p&&alert("method: "+a);b();b();b();b();var c=b(),c=c|b()<<8,c=c|b()<<16,c=c|b()<<24,d=b(),d=d|b()<<8,d=d|b()<<16,d=
+d|b()<<24,e=b(),e=e|b()<<8,e=e|b()<<16,e=e|b()<<24;p&&alert("local CRC: "+c+"\nlocal Size: "+e+"\nlocal CompSize: "+d);c=b();c|=b()<<8;d=b();d|=b()<<8;p&&alert("filelen "+c);f=0;for(N=[];c--;)e=b(),"/"==e|":"==e?f=0:f<E-1&&(N[f++]=String.fromCharCode(e));p&&alert("nameBuf: "+N);Y||(Y=N);for(var f=0;f<d;)b(),f++;na=0;8==a&&(m(),p&&alert(l.join("")),z[L]=Array(2),z[L][0]=l.join(""),z[L][1]=N.join(""),L++);D()}}function D(){var a=[],c;W&8&&(a[0]=b(),a[1]=b(),a[2]=b(),a[3]=b(),80==a[0]&&75==a[1]&&7==
+a[2]&&8==a[3]&&(b(),b(),b(),b()),b(),b(),b(),b(),b(),b(),b(),b(),p&&alert("CRC:"));ka&&u();a[0]=b();if(8!=a[0])return p&&alert("Unknown compression method!"),0;W=b();p&&W&-32&&alert("Unknown flags set!");b();b();b();b();b();b();if(W&4){a[0]=b();a[2]=b();T=a[0]+256*a[1];p&&alert("Extra field size: "+T);for(a=0;a<T;a++)b()}if(W&8){a=0;for(N=[];c=b();){if("7"==c||":"==c)a=0;a<E-1&&(N[a++]=c)}p&&alert("original file name: "+N)}if(W&16)for(;b(););W&2&&(b(),b());m();b();b();b();b();b();b();b();b();ka&&
+u()}var l=[],p=!1,W,L=0,z=[],o=Array(32768),A=0,ka=!1,na,fa=[0,128,64,192,32,160,96,224,16,144,80,208,48,176,112,240,8,136,72,200,40,168,104,232,24,152,88,216,56,184,120,248,4,132,68,196,36,164,100,228,20,148,84,212,52,180,116,244,12,140,76,204,44,172,108,236,28,156,92,220,60,188,124,252,2,130,66,194,34,162,98,226,18,146,82,210,50,178,114,242,10,138,74,202,42,170,106,234,26,154,90,218,58,186,122,250,6,134,70,198,38,166,102,230,22,150,86,214,54,182,118,246,14,142,78,206,46,174,110,238,30,158,94,222,
+62,190,126,254,1,129,65,193,33,161,97,225,17,145,81,209,49,177,113,241,9,137,73,201,41,169,105,233,25,153,89,217,57,185,121,249,5,133,69,197,37,165,101,229,21,149,85,213,53,181,117,245,13,141,77,205,45,173,109,237,29,157,93,221,61,189,125,253,3,131,67,195,35,163,99,227,19,147,83,211,51,179,115,243,11,139,75,203,43,171,107,235,27,155,91,219,59,187,123,251,7,135,71,199,39,167,103,231,23,151,87,215,55,183,119,247,15,143,79,207,47,175,111,239,31,159,95,223,63,191,127,255],la=[3,4,5,6,7,8,9,10,11,13,15,
+17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],O=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,99,99],M=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],Z=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],qa=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],ea=a,ca=0,da=1,Q=0,E=256,N=[],Y,aa=Array(288),K=Array(32),ha=0,P=null,T=0,ga=Array(17);ga[0]=0;var oa,sa;JXG.Util.Unzip.prototype.unzipFile=
+function(a){var b;this.unzip();for(b=0;b<z.length;b++)if(z[b][1]==a)return z[b][0]};JXG.Util.Unzip.prototype.deflate=function(){l=[];ka=!1;m();p&&alert(l.join(""));z[L]=Array(2);z[L][0]=l.join("");z[L][1]="DEFLATE";L++;return z};JXG.Util.Unzip.prototype.unzip=function(){p&&alert(ea);u();return z}};
+JXG.Util.Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(a){for(var b=[],c,d,e,f,g,h,k=0,a=JXG.Util.Base64._utf8_encode(a);k<a.length;)c=a.charCodeAt(k++),d=a.charCodeAt(k++),e=a.charCodeAt(k++),f=c>>2,c=(c&3)<<4|d>>4,g=(d&15)<<2|e>>6,h=e&63,isNaN(d)?g=h=64:isNaN(e)&&(h=64),b.push([this._keyStr.charAt(f),this._keyStr.charAt(c),this._keyStr.charAt(g),this._keyStr.charAt(h)].join(""));return b.join("")},decode:function(a,b){for(var c=[],d,e,f,g,h,
+k=0,a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");k<a.length;)d=this._keyStr.indexOf(a.charAt(k++)),e=this._keyStr.indexOf(a.charAt(k++)),g=this._keyStr.indexOf(a.charAt(k++)),h=this._keyStr.indexOf(a.charAt(k++)),d=d<<2|e>>4,e=(e&15)<<4|g>>2,f=(g&3)<<6|h,c.push(String.fromCharCode(d)),64!=g&&c.push(String.fromCharCode(e)),64!=h&&c.push(String.fromCharCode(f));c=c.join("");b&&(c=JXG.Util.Base64._utf8_decode(c));return c},_utf8_encode:function(a){for(var a=a.replace(/\r\n/g,"\n"),b="",c=0;c<a.length;c++){var d=
+a.charCodeAt(c);128>d?b+=String.fromCharCode(d):(127<d&&2048>d?b+=String.fromCharCode(d>>6|192):(b+=String.fromCharCode(d>>12|224),b+=String.fromCharCode(d>>6&63|128)),b+=String.fromCharCode(d&63|128))}return b},_utf8_decode:function(a){for(var b=[],c=0,d=0,e=0,f=0;c<a.length;)d=a.charCodeAt(c),128>d?(b.push(String.fromCharCode(d)),c++):191<d&&224>d?(e=a.charCodeAt(c+1),b.push(String.fromCharCode((d&31)<<6|e&63)),c+=2):(e=a.charCodeAt(c+1),f=a.charCodeAt(c+2),b.push(String.fromCharCode((d&15)<<12|
+(e&63)<<6|f&63)),c+=3);return b.join("")},_destrip:function(a,b){var c=[],d,e,f=[];null==b&&(b=76);a.replace(/ /g,"");d=a.length/b;for(e=0;e<d;e++)c[e]=a.substr(e*b,b);d!=a.length/b&&(c[c.length]=a.substr(d*b,a.length-d*b));for(e=0;e<c.length;e++)f.push(c[e]);return f.join("\n")},decodeAsArray:function(a){var a=this.decode(a),b=[],c;for(c=0;c<a.length;c++)b[c]=a.charCodeAt(c);return b},decodeGEONExT:function(a){return decodeAsArray(destrip(a),!1)}};
+JXG.Util.asciiCharCodeAt=function(a,b){var c=a.charCodeAt(b);if(255<c)switch(c){case 8364:c=128;break;case 8218:c=130;break;case 402:c=131;break;case 8222:c=132;break;case 8230:c=133;break;case 8224:c=134;break;case 8225:c=135;break;case 710:c=136;break;case 8240:c=137;break;case 352:c=138;break;case 8249:c=139;break;case 338:c=140;break;case 381:c=142;break;case 8216:c=145;break;case 8217:c=146;break;case 8220:c=147;break;case 8221:c=148;break;case 8226:c=149;break;case 8211:c=150;break;case 8212:c=
+151;break;case 732:c=152;break;case 8482:c=153;break;case 353:c=154;break;case 8250:c=155;break;case 339:c=156;break;case 382:c=158;break;case 376:c=159}return c};
+JXG.Util.utf8Decode=function(a){var b=[],c=0,d=0,e=0,f;if(!JXG.exists(a))return"";for(;c<a.length;)d=a.charCodeAt(c),128>d?(b.push(String.fromCharCode(d)),c++):191<d&&224>d?(e=a.charCodeAt(c+1),b.push(String.fromCharCode((d&31)<<6|e&63)),c+=2):(e=a.charCodeAt(c+1),f=a.charCodeAt(c+2),b.push(String.fromCharCode((d&15)<<12|(e&63)<<6|f&63)),c+=3);return b.join("")};
+JXG.Util.genUUID=function(){for(var a="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),b=Array(36),c=0,d,e=0;36>e;e++)8==e||13==e||18==e||23==e?b[e]="-":14==e?b[e]="4":(2>=c&&(c=33554432+16777216*Math.random()|0),d=c&15,c>>=4,b[e]=a[19==e?d&3|8:d]);return b.join("")};(function(a){a.zip={useWebWorkers:!1}})(this);
+(function(a){function b(){function a(b,c,d,Ca,j,Q,w,E,m,q,r){var N,p,v,s,x,t,Y,B,aa,ba;Y=0;v=d;do e[b[c+Y]]++,Y++,v--;while(0!==v);if(e[0]==d)return w[0]=-1,E[0]=0,h;t=E[0];for(s=1;s<=O&&!(0!==e[s]);s++);x=s;t<s&&(t=s);for(v=O;0!==v&&!(0!==e[v]);v--);p=v;t>v&&(t=v);E[0]=t;for(E=1<<s;s<v;s++,E<<=1)if(0>(E-=e[s]))return u;if(0>(E-=e[v]))return u;e[v]+=E;k[1]=s=0;Y=1;for(B=2;0!==--v;)k[B]=s+=e[Y],B++,Y++;Y=v=0;do{if(0!==(s=b[c+Y]))r[k[s]++]=v;Y++}while(++v<d);d=k[p];Y=k[0]=v=0;c=-1;aa=-t;for(ba=B=g[0]=
+0;x<=p;x++)for(b=e[x];0!==b--;){for(;x>aa+t;){c++;aa+=t;ba=p-aa;ba=ba>t?t:ba;if((N=1<<(s=x-aa))>b+1)if(N-=b+1,B=x,s<ba)for(;++s<ba&&!((N<<=1)<=e[++B]);)N-=e[B];ba=1<<s;if(q[0]+ba>W)return u;g[c]=B=q[0];q[0]+=ba;0!==c?(k[c]=v,f[0]=s,f[1]=t,s=v>>>aa-t,f[2]=B-g[c-1]-s,m.set(f,3*(g[c-1]+s))):w[0]=B}f[1]=x-aa;Y>=d?f[0]=192:r[Y]<Ca?(f[0]=256>r[Y]?0:96,f[2]=r[Y++]):(f[0]=Q[r[Y]-Ca]+16+64,f[2]=j[r[Y++]-Ca]);N=1<<x-aa;for(s=v>>>aa;s<ba;s+=N)m.set(f,3*(B+s));for(s=1<<x-1;0!==(v&s);s>>>=1)v^=s;v^=s;for(s=(1<<
+aa)-1;(v&s)!=k[c];)c--,aa-=t,s=(1<<aa)-1}return 0!==E&&1!=p?l:h}function b(a){var h;c||(c=[],d=[],e=new Int32Array(O+1),f=[],g=new Int32Array(O),k=new Int32Array(O+1));d.length<a&&(d=[]);for(h=0;h<a;h++)d[h]=0;for(h=0;h<O+1;h++)e[h]=0;for(h=0;3>h;h++)f[h]=0;g.set(e.subarray(0,O),0);k.set(e.subarray(0,O+1),0)}var c,d,e,f,g,k;this.inflate_trees_bits=function(e,f,g,h,k){b(19);c[0]=0;e=a(e,0,19,19,null,null,g,f,h,c,d);if(e==u)k.msg="oversubscribed dynamic bit lengths tree";else if(e==l||0===f[0])k.msg=
+"incomplete dynamic bit lengths tree",e=u;return e};this.inflate_trees_dynamic=function(e,f,g,k,j,Q,w,E,m){b(288);c[0]=0;Q=a(g,0,e,257,ka,na,Q,k,E,c,d);if(Q!=h||0===k[0]){if(Q==u)m.msg="oversubscribed literal/length tree";else if(Q!=D)m.msg="incomplete literal/length tree",Q=u;return Q}b(288);Q=a(g,e,f,0,fa,la,w,j,E,c,d);if(Q!=h||0===j[0]&&257<e){if(Q==u)m.msg="oversubscribed distance tree";else if(Q==l)m.msg="incomplete distance tree",Q=u;else if(Q!=D)m.msg="empty distance tree with lengths",Q=u;
+return Q}return h}}function c(){var a,b=0,c,d=0,e=0,f=0,g=0,j=0,t=0,B=0,l,aa=0,A,D=0;this.init=function(b,d,e,f,g,h){a=M;t=b;B=d;l=e;aa=f;A=g;D=h;c=null};this.proc=function(w,y,V){var q,r,U=0,C=0,v=0,s,x,o,v=y.next_in_index;s=y.avail_in;U=w.bitb;C=w.bitk;x=w.write;for(o=x<w.read?w.read-x-1:w.end-x;;)switch(a){case M:if(258<=o&&10<=s){w.bitb=U;w.bitk=C;y.avail_in=s;y.total_in+=v-y.next_in_index;y.next_in_index=v;w.write=x;a:{V=l;U=aa;C=A;v=D;s=w;x=y;var K=void 0,z=void 0,ha=void 0,L=r=q=o=void 0,T=
+void 0,P=void 0,oa=void 0,W=void 0,ga=void 0,R=void 0,O=K=K=void 0,L=x.next_in_index,T=x.avail_in;q=s.bitb;r=s.bitk;P=s.write;oa=P<s.read?s.read-P-1:s.end-P;W=p[t];ga=p[B];do{for(;20>r;)T--,q|=(x.read_byte(L++)&255)<<r,r+=8;K=q&W;z=V;ha=U;O=3*(ha+K);if(0===(o=z[O]))q>>=z[O+1],r-=z[O+1],s.window[P++]=z[O+2],oa--;else{do{q>>=z[O+1];r-=z[O+1];if(0!==(o&16)){o&=15;R=z[O+2]+(q&p[o]);q>>=o;for(r-=o;15>r;)T--,q|=(x.read_byte(L++)&255)<<r,r+=8;K=q&ga;z=C;ha=v;O=3*(ha+K);o=z[O];do if(q>>=z[O+1],r-=z[O+1],
+0!==(o&16)){for(o&=15;r<o;)T--,q|=(x.read_byte(L++)&255)<<r,r+=8;K=z[O+2]+(q&p[o]);q>>=o;r-=o;oa-=R;if(P>=K)K=P-K,0<P-K&&2>P-K?(s.window[P++]=s.window[K++],s.window[P++]=s.window[K++]):(s.window.set(s.window.subarray(K,K+2),P),P+=2,K+=2),R-=2;else{K=P-K;do K+=s.end;while(0>K);o=s.end-K;if(R>o){R-=o;if(0<P-K&&o>P-K){do s.window[P++]=s.window[K++];while(0!==--o)}else s.window.set(s.window.subarray(K,K+o),P),P+=o;K=0}}if(0<P-K&&R>P-K){do s.window[P++]=s.window[K++];while(0!==--R)}else s.window.set(s.window.subarray(K,
+K+R),P),P+=R;break}else if(0===(o&64))K+=z[O+2],K+=q&p[o],O=3*(ha+K),o=z[O];else{x.msg="invalid distance code";R=x.avail_in-T;R=r>>3<R?r>>3:R;T+=R;L-=R;r-=R<<3;s.bitb=q;s.bitk=r;x.avail_in=T;x.total_in+=L-x.next_in_index;x.next_in_index=L;s.write=P;V=u;break a}while(1);break}if(0===(o&64)){if(K+=z[O+2],K+=q&p[o],O=3*(ha+K),0===(o=z[O])){q>>=z[O+1];r-=z[O+1];s.window[P++]=z[O+2];oa--;break}}else{if(0!==(o&32)){R=x.avail_in-T;R=r>>3<R?r>>3:R;T+=R;L-=R;r-=R<<3;s.bitb=q;s.bitk=r;x.avail_in=T;x.total_in+=
+L-x.next_in_index;x.next_in_index=L;s.write=P;V=k;break a}x.msg="invalid literal/length code";R=x.avail_in-T;R=r>>3<R?r>>3:R;T+=R;L-=R;r-=R<<3;s.bitb=q;s.bitk=r;x.avail_in=T;x.total_in+=L-x.next_in_index;x.next_in_index=L;s.write=P;V=u;break a}}while(1)}}while(258<=oa&&10<=T);R=x.avail_in-T;R=r>>3<R?r>>3:R;T+=R;L-=R;r-=R<<3;s.bitb=q;s.bitk=r;x.avail_in=T;x.total_in+=L-x.next_in_index;x.next_in_index=L;s.write=P;V=h}v=y.next_in_index;s=y.avail_in;U=w.bitb;C=w.bitk;x=w.write;o=x<w.read?w.read-x-1:w.end-
+x;if(V!=h){a=V==k?E:Y;break}}e=t;c=l;d=aa;a=Z;case Z:for(q=e;C<q;){if(0!==s)V=h;else return w.bitb=U,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,V);s--;U|=(y.read_byte(v++)&255)<<C;C+=8}q=3*(d+(U&p[q]));U>>>=c[q+1];C-=c[q+1];r=c[q];if(0===r){f=c[q+2];a=Q;break}if(0!==(r&16)){g=r&15;b=c[q+2];a=qa;break}if(0===(r&64)){e=r;d=q/3+c[q+2];break}if(0!==(r&32)){a=E;break}a=Y;y.msg="invalid literal/length code";V=u;w.bitb=U;w.bitk=C;y.avail_in=s;y.total_in+=
+v-y.next_in_index;y.next_in_index=v;w.write=x;return w.inflate_flush(y,V);case qa:for(q=g;C<q;){if(0!==s)V=h;else return w.bitb=U,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,V);s--;U|=(y.read_byte(v++)&255)<<C;C+=8}b+=U&p[q];U>>=q;C-=q;e=B;c=A;d=D;a=ea;case ea:for(q=e;C<q;){if(0!==s)V=h;else return w.bitb=U,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,V);s--;U|=(y.read_byte(v++)&255)<<C;C+=8}q=
+3*(d+(U&p[q]));U>>=c[q+1];C-=c[q+1];r=c[q];if(0!==(r&16)){g=r&15;j=c[q+2];a=ca;break}if(0===(r&64)){e=r;d=q/3+c[q+2];break}a=Y;y.msg="invalid distance code";V=u;w.bitb=U;w.bitk=C;y.avail_in=s;y.total_in+=v-y.next_in_index;y.next_in_index=v;w.write=x;return w.inflate_flush(y,V);case ca:for(q=g;C<q;){if(0!==s)V=h;else return w.bitb=U,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,V);s--;U|=(y.read_byte(v++)&255)<<C;C+=8}j+=U&p[q];U>>=q;C-=q;a=da;case da:for(q=
+x-j;0>q;)q+=w.end;for(;0!==b;){if(0===o&&(x==w.end&&0!==w.read&&(x=0,o=x<w.read?w.read-x-1:w.end-x),0===o&&(w.write=x,V=w.inflate_flush(y,V),x=w.write,o=x<w.read?w.read-x-1:w.end-x,x==w.end&&0!==w.read&&(x=0,o=x<w.read?w.read-x-1:w.end-x),0===o)))return w.bitb=U,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,V);w.window[x++]=w.window[q++];o--;q==w.end&&(q=0);b--}a=M;break;case Q:if(0===o&&(x==w.end&&0!==w.read&&(x=0,o=x<w.read?w.read-x-1:w.end-x),
+0===o&&(w.write=x,V=w.inflate_flush(y,V),x=w.write,o=x<w.read?w.read-x-1:w.end-x,x==w.end&&0!==w.read&&(x=0,o=x<w.read?w.read-x-1:w.end-x),0===o)))return w.bitb=U,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,V);V=h;w.window[x++]=f;o--;a=M;break;case E:7<C&&(C-=8,s++,v--);w.write=x;V=w.inflate_flush(y,V);x=w.write;if(w.read!=w.write)return w.bitb=U,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,
+V);a=N;case N:return V=k,w.bitb=U,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,V);case Y:return V=u,w.bitb=U,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,V);default:return V=m,w.bitb=U,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,V)}};this.free=function(){}}function d(a,d){var e=this,f=K,g=0,j=0,Q=0,E,N=[0],t=[0],o=new c,Y=0,A=new Int32Array(3*
+W),D=new b;e.bitk=0;e.bitb=0;e.window=new Uint8Array(d);e.end=d;e.read=0;e.write=0;e.reset=function(a,b){b&&(b[0]=0);f==sa&&o.free(a);f=K;e.bitk=0;e.bitb=0;e.read=e.write=0};e.reset(a,null);e.inflate_flush=function(a,b){var c,d,f;d=a.next_out_index;f=e.read;c=(f<=e.write?e.write:e.end)-f;if(c>a.avail_out)c=a.avail_out;0!==c&&b==l&&(b=h);a.avail_out-=c;a.total_out+=c;a.next_out.set(e.window.subarray(f,f+c),d);d+=c;f+=c;if(f==e.end){f=0;if(e.write==e.end)e.write=0;c=e.write-f;if(c>a.avail_out)c=a.avail_out;
+0!==c&&b==l&&(b=h);a.avail_out-=c;a.total_out+=c;a.next_out.set(e.window.subarray(f,f+c),d);d+=c;f+=c}a.next_out_index=d;e.read=f;return b};e.proc=function(a,c){var d,q,r,l,C,v,s;l=a.next_in_index;C=a.avail_in;q=e.bitb;r=e.bitk;v=e.write;for(s=v<e.read?e.read-v-1:e.end-v;;)switch(f){case K:for(;3>r;){if(0!==C)c=h;else return e.bitb=q,e.bitk=r,a.avail_in=C,a.total_in+=l-a.next_in_index,a.next_in_index=l,e.write=v,e.inflate_flush(a,c);C--;q|=(a.read_byte(l++)&255)<<r;r+=8}d=q&7;Y=d&1;switch(d>>>1){case 0:q>>>=
+3;r-=3;d=r&7;q>>>=d;r-=d;f=ha;break;case 1:d=[];var x=[],z=[[]],ba=[[]];b.inflate_trees_fixed(d,x,z,ba,a);o.init(d[0],x[0],z[0],0,ba[0],0,a);q>>>=3;r-=3;f=sa;break;case 2:q>>>=3;r-=3;f=T;break;case 3:return q>>>=3,r-=3,f=ma,a.msg="invalid block type",c=u,e.bitb=q,e.bitk=r,a.avail_in=C,a.total_in+=l-a.next_in_index,a.next_in_index=l,e.write=v,e.inflate_flush(a,c)}break;case ha:for(;32>r;){if(0!==C)c=h;else return e.bitb=q,e.bitk=r,a.avail_in=C,a.total_in+=l-a.next_in_index,a.next_in_index=l,e.write=
+v,e.inflate_flush(a,c);C--;q|=(a.read_byte(l++)&255)<<r;r+=8}if((~q>>>16&65535)!=(q&65535))return f=ma,a.msg="invalid stored block lengths",c=u,e.bitb=q,e.bitk=r,a.avail_in=C,a.total_in+=l-a.next_in_index,a.next_in_index=l,e.write=v,e.inflate_flush(a,c);g=q&65535;q=r=0;f=0!==g?P:0!==Y?B:K;break;case P:if(0===C||0===s&&(v==e.end&&0!==e.read&&(v=0,s=v<e.read?e.read-v-1:e.end-v),0===s&&(e.write=v,c=e.inflate_flush(a,c),v=e.write,s=v<e.read?e.read-v-1:e.end-v,v==e.end&&0!==e.read&&(v=0,s=v<e.read?e.read-
+v-1:e.end-v),0===s)))return e.bitb=q,e.bitk=r,a.avail_in=C,a.total_in+=l-a.next_in_index,a.next_in_index=l,e.write=v,e.inflate_flush(a,c);c=h;d=g;d>C&&(d=C);d>s&&(d=s);e.window.set(a.read_buf(l,d),v);l+=d;C-=d;v+=d;s-=d;if(0!==(g-=d))break;f=0!==Y?B:K;break;case T:for(;14>r;){if(0!==C)c=h;else return e.bitb=q,e.bitk=r,a.avail_in=C,a.total_in+=l-a.next_in_index,a.next_in_index=l,e.write=v,e.inflate_flush(a,c);C--;q|=(a.read_byte(l++)&255)<<r;r+=8}j=d=q&16383;if(29<(d&31)||29<(d>>5&31))return f=ma,
+a.msg="too many length or distance symbols",c=u,e.bitb=q,e.bitk=r,a.avail_in=C,a.total_in+=l-a.next_in_index,a.next_in_index=l,e.write=v,e.inflate_flush(a,c);d=258+(d&31)+(d>>5&31);if(!E||E.length<d)E=[];else for(s=0;s<d;s++)E[s]=0;q>>>=14;r-=14;Q=0;f=ga;case ga:for(;Q<4+(j>>>10);){for(;3>r;){if(0!==C)c=h;else return e.bitb=q,e.bitk=r,a.avail_in=C,a.total_in+=l-a.next_in_index,a.next_in_index=l,e.write=v,e.inflate_flush(a,c);C--;q|=(a.read_byte(l++)&255)<<r;r+=8}E[aa[Q++]]=q&7;q>>>=3;r-=3}for(;19>
+Q;)E[aa[Q++]]=0;N[0]=7;d=D.inflate_trees_bits(E,N,t,A,a);if(d!=h)return c=d,c==u&&(E=null,f=ma),e.bitb=q,e.bitk=r,a.avail_in=C,a.total_in+=l-a.next_in_index,a.next_in_index=l,e.write=v,e.inflate_flush(a,c);Q=0;f=oa;case oa:for(;;){d=j;if(!(Q<258+(d&31)+(d>>5&31)))break;for(d=N[0];r<d;){if(0!==C)c=h;else return e.bitb=q,e.bitk=r,a.avail_in=C,a.total_in+=l-a.next_in_index,a.next_in_index=l,e.write=v,e.inflate_flush(a,c);C--;q|=(a.read_byte(l++)&255)<<r;r+=8}d=A[3*(t[0]+(q&p[d]))+1];z=A[3*(t[0]+(q&p[d]))+
+2];if(16>z)q>>>=d,r-=d,E[Q++]=z;else{s=18==z?7:z-14;for(x=18==z?11:3;r<d+s;){if(0!==C)c=h;else return e.bitb=q,e.bitk=r,a.avail_in=C,a.total_in+=l-a.next_in_index,a.next_in_index=l,e.write=v,e.inflate_flush(a,c);C--;q|=(a.read_byte(l++)&255)<<r;r+=8}q>>>=d;r-=d;x+=q&p[s];q>>>=s;r-=s;s=Q;d=j;if(s+x>258+(d&31)+(d>>5&31)||16==z&&1>s)return E=null,f=ma,a.msg="invalid bit length repeat",c=u,e.bitb=q,e.bitk=r,a.avail_in=C,a.total_in+=l-a.next_in_index,a.next_in_index=l,e.write=v,e.inflate_flush(a,c);z=
+16==z?E[s-1]:0;do E[s++]=z;while(0!==--x);Q=s}}t[0]=-1;s=[];x=[];z=[];ba=[];s[0]=9;x[0]=6;d=j;d=D.inflate_trees_dynamic(257+(d&31),1+(d>>5&31),E,s,x,z,ba,A,a);if(d!=h)return d==u&&(E=null,f=ma),c=d,e.bitb=q,e.bitk=r,a.avail_in=C,a.total_in+=l-a.next_in_index,a.next_in_index=l,e.write=v,e.inflate_flush(a,c);o.init(s[0],x[0],A,z[0],A,ba[0],a);f=sa;case sa:e.bitb=q;e.bitk=r;a.avail_in=C;a.total_in+=l-a.next_in_index;a.next_in_index=l;e.write=v;if((c=o.proc(e,a,c))!=k)return e.inflate_flush(a,c);c=h;
+o.free(a);l=a.next_in_index;C=a.avail_in;q=e.bitb;r=e.bitk;v=e.write;s=v<e.read?e.read-v-1:e.end-v;if(0===Y){f=K;break}f=B;case B:e.write=v;c=e.inflate_flush(a,c);v=e.write;if(e.read!=e.write)return e.bitb=q,e.bitk=r,a.avail_in=C,a.total_in+=l-a.next_in_index,a.next_in_index=l,e.write=v,e.inflate_flush(a,c);f=Da;case Da:return c=k,e.bitb=q,e.bitk=r,a.avail_in=C,a.total_in+=l-a.next_in_index,a.next_in_index=l,e.write=v,e.inflate_flush(a,c);case ma:return c=u,e.bitb=q,e.bitk=r,a.avail_in=C,a.total_in+=
+l-a.next_in_index,a.next_in_index=l,e.write=v,e.inflate_flush(a,c);default:return c=m,e.bitb=q,e.bitk=r,a.avail_in=C,a.total_in+=l-a.next_in_index,a.next_in_index=l,e.write=v,e.inflate_flush(a,c)}};e.free=function(a){e.reset(a,null);A=e.window=null};e.set_dictionary=function(a,b,c){e.window.set(a.subarray(b,b+c),0);e.read=e.write=c};e.sync_point=function(){return f==ha?1:0}}function e(){function a(b){if(!b||!b.istate)return m;b.total_in=b.total_out=0;b.msg=null;b.istate.mode=ra;b.istate.blocks.reset(b,
+null);return h}var b=this;b.mode=0;b.method=0;b.was=[0];b.need=0;b.marker=0;b.wbits=0;b.inflateEnd=function(a){b.blocks&&b.blocks.free(a);b.blocks=null;return h};b.inflateInit=function(c,e){c.msg=null;b.blocks=null;if(8>e||15<e)return b.inflateEnd(c),m;b.wbits=e;c.istate.blocks=new d(c,1<<e);a(c);return h};b.inflate=function(a,b){var c,d;if(!a||!a.istate||!a.next_in)return m;b=b==z?l:h;for(c=l;;)switch(a.istate.mode){case va:if(0===a.avail_in)return c;c=b;a.avail_in--;a.total_in++;if(((a.istate.method=
+a.read_byte(a.next_in_index++))&15)!=Ba){a.istate.mode=pa;a.msg="unknown compression method";a.istate.marker=5;break}if((a.istate.method>>4)+8>a.istate.wbits){a.istate.mode=pa;a.msg="invalid window size";a.istate.marker=5;break}a.istate.mode=ja;case ja:if(0===a.avail_in)return c;c=b;a.avail_in--;a.total_in++;d=a.read_byte(a.next_in_index++)&255;if(0!==((a.istate.method<<8)+d)%31){a.istate.mode=pa;a.msg="incorrect header check";a.istate.marker=5;break}if(0===(d&ia)){a.istate.mode=ra;break}a.istate.mode=
+wa;case wa:if(0===a.avail_in)return c;c=b;a.avail_in--;a.total_in++;a.istate.need=(a.read_byte(a.next_in_index++)&255)<<24&4278190080;a.istate.mode=xa;case xa:if(0===a.avail_in)return c;c=b;a.avail_in--;a.total_in++;a.istate.need+=(a.read_byte(a.next_in_index++)&255)<<16&16711680;a.istate.mode=ya;case ya:if(0===a.avail_in)return c;c=b;a.avail_in--;a.total_in++;a.istate.need+=(a.read_byte(a.next_in_index++)&255)<<8&65280;a.istate.mode=za;case za:if(0===a.avail_in)return c;a.avail_in--;a.total_in++;
+a.istate.need+=a.read_byte(a.next_in_index++)&255;a.istate.mode=ta;return j;case ta:return a.istate.mode=pa,a.msg="need dictionary",a.istate.marker=0,m;case ra:c=a.istate.blocks.proc(a,c);if(c==u){a.istate.mode=pa;a.istate.marker=0;break}c==h&&(c=b);if(c!=k)return c;a.istate.blocks.reset(a,a.istate.was);a.istate.mode=Aa;case Aa:return k;case pa:return u;default:return m}};b.inflateSetDictionary=function(a,b,c){var d=0,e=c;if(!a||!a.istate||a.istate.mode!=ta)return m;e>=1<<a.istate.wbits&&(e=(1<<a.istate.wbits)-
+1,d=c-e);a.istate.blocks.set_dictionary(b,d,e);a.istate.mode=ra;return h};b.inflateSync=function(b){var c,d,e;if(!b||!b.istate)return m;if(b.istate.mode!=pa)b.istate.mode=pa,b.istate.marker=0;if(0===(c=b.avail_in))return l;d=b.next_in_index;for(e=b.istate.marker;0!==c&&4>e;)b.read_byte(d)==t[e]?e++:e=0!==b.read_byte(d)?0:4-e,d++,c--;b.total_in+=d-b.next_in_index;b.next_in_index=d;b.avail_in=c;b.istate.marker=e;if(4!=e)return u;c=b.total_in;d=b.total_out;a(b);b.total_in=c;b.total_out=d;b.istate.mode=
+ra;return h};b.inflateSyncPoint=function(a){return!a||!a.istate||!a.istate.blocks?m:a.istate.blocks.sync_point()}}function f(){}function g(){var a=new f,b=L,c=new Uint8Array(512),d=!1;a.inflateInit();a.next_out=c;this.append=function(e,f){var g,j=[],Q=0,E=0,m=0,N;if(0!==e.length){a.next_in_index=0;a.next_in=e;a.avail_in=e.length;do{a.next_out_index=0;a.avail_out=512;if(0===a.avail_in&&!d)a.next_in_index=0,d=!0;g=a.inflate(b);if(d&&g==l)return-1;if(g!=h&&g!=k)throw"inflating: "+a.msg;if((d||g==k)&&
+a.avail_out==e.length)return-1;a.next_out_index&&(512==a.next_out_index?j.push(new Uint8Array(c)):j.push(new Uint8Array(c.subarray(0,a.next_out_index))));m+=a.next_out_index;if(f&&0<a.next_in_index&&a.next_in_index!=Q)f(a.next_in_index),Q=a.next_in_index}while(0<a.avail_in||0===a.avail_out);N=new Uint8Array(m);j.forEach(function(a){N.set(a,E);E+=a.length});return N}};this.flush=function(){a.inflateEnd()}}var h=0,k=1,j=2,m=-2,u=-3,D=-4,l=-5,p=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,
+32767,65535],W=1440,L=0,z=4,o=[96,7,256,0,8,80,0,8,16,84,8,115,82,7,31,0,8,112,0,8,48,0,9,192,80,7,10,0,8,96,0,8,32,0,9,160,0,8,0,0,8,128,0,8,64,0,9,224,80,7,6,0,8,88,0,8,24,0,9,144,83,7,59,0,8,120,0,8,56,0,9,208,81,7,17,0,8,104,0,8,40,0,9,176,0,8,8,0,8,136,0,8,72,0,9,240,80,7,4,0,8,84,0,8,20,85,8,227,83,7,43,0,8,116,0,8,52,0,9,200,81,7,13,0,8,100,0,8,36,0,9,168,0,8,4,0,8,132,0,8,68,0,9,232,80,7,8,0,8,92,0,8,28,0,9,152,84,7,83,0,8,124,0,8,60,0,9,216,82,7,23,0,8,108,0,8,44,0,9,184,0,8,12,0,8,140,0,
+8,76,0,9,248,80,7,3,0,8,82,0,8,18,85,8,163,83,7,35,0,8,114,0,8,50,0,9,196,81,7,11,0,8,98,0,8,34,0,9,164,0,8,2,0,8,130,0,8,66,0,9,228,80,7,7,0,8,90,0,8,26,0,9,148,84,7,67,0,8,122,0,8,58,0,9,212,82,7,19,0,8,106,0,8,42,0,9,180,0,8,10,0,8,138,0,8,74,0,9,244,80,7,5,0,8,86,0,8,22,192,8,0,83,7,51,0,8,118,0,8,54,0,9,204,81,7,15,0,8,102,0,8,38,0,9,172,0,8,6,0,8,134,0,8,70,0,9,236,80,7,9,0,8,94,0,8,30,0,9,156,84,7,99,0,8,126,0,8,62,0,9,220,82,7,27,0,8,110,0,8,46,0,9,188,0,8,14,0,8,142,0,8,78,0,9,252,96,7,256,
+0,8,81,0,8,17,85,8,131,82,7,31,0,8,113,0,8,49,0,9,194,80,7,10,0,8,97,0,8,33,0,9,162,0,8,1,0,8,129,0,8,65,0,9,226,80,7,6,0,8,89,0,8,25,0,9,146,83,7,59,0,8,121,0,8,57,0,9,210,81,7,17,0,8,105,0,8,41,0,9,178,0,8,9,0,8,137,0,8,73,0,9,242,80,7,4,0,8,85,0,8,21,80,8,258,83,7,43,0,8,117,0,8,53,0,9,202,81,7,13,0,8,101,0,8,37,0,9,170,0,8,5,0,8,133,0,8,69,0,9,234,80,7,8,0,8,93,0,8,29,0,9,154,84,7,83,0,8,125,0,8,61,0,9,218,82,7,23,0,8,109,0,8,45,0,9,186,0,8,13,0,8,141,0,8,77,0,9,250,80,7,3,0,8,83,0,8,19,85,8,
+195,83,7,35,0,8,115,0,8,51,0,9,198,81,7,11,0,8,99,0,8,35,0,9,166,0,8,3,0,8,131,0,8,67,0,9,230,80,7,7,0,8,91,0,8,27,0,9,150,84,7,67,0,8,123,0,8,59,0,9,214,82,7,19,0,8,107,0,8,43,0,9,182,0,8,11,0,8,139,0,8,75,0,9,246,80,7,5,0,8,87,0,8,23,192,8,0,83,7,51,0,8,119,0,8,55,0,9,206,81,7,15,0,8,103,0,8,39,0,9,174,0,8,7,0,8,135,0,8,71,0,9,238,80,7,9,0,8,95,0,8,31,0,9,158,84,7,99,0,8,127,0,8,63,0,9,222,82,7,27,0,8,111,0,8,47,0,9,190,0,8,15,0,8,143,0,8,79,0,9,254,96,7,256,0,8,80,0,8,16,84,8,115,82,7,31,0,8,112,
+0,8,48,0,9,193,80,7,10,0,8,96,0,8,32,0,9,161,0,8,0,0,8,128,0,8,64,0,9,225,80,7,6,0,8,88,0,8,24,0,9,145,83,7,59,0,8,120,0,8,56,0,9,209,81,7,17,0,8,104,0,8,40,0,9,177,0,8,8,0,8,136,0,8,72,0,9,241,80,7,4,0,8,84,0,8,20,85,8,227,83,7,43,0,8,116,0,8,52,0,9,201,81,7,13,0,8,100,0,8,36,0,9,169,0,8,4,0,8,132,0,8,68,0,9,233,80,7,8,0,8,92,0,8,28,0,9,153,84,7,83,0,8,124,0,8,60,0,9,217,82,7,23,0,8,108,0,8,44,0,9,185,0,8,12,0,8,140,0,8,76,0,9,249,80,7,3,0,8,82,0,8,18,85,8,163,83,7,35,0,8,114,0,8,50,0,9,197,81,7,
+11,0,8,98,0,8,34,0,9,165,0,8,2,0,8,130,0,8,66,0,9,229,80,7,7,0,8,90,0,8,26,0,9,149,84,7,67,0,8,122,0,8,58,0,9,213,82,7,19,0,8,106,0,8,42,0,9,181,0,8,10,0,8,138,0,8,74,0,9,245,80,7,5,0,8,86,0,8,22,192,8,0,83,7,51,0,8,118,0,8,54,0,9,205,81,7,15,0,8,102,0,8,38,0,9,173,0,8,6,0,8,134,0,8,70,0,9,237,80,7,9,0,8,94,0,8,30,0,9,157,84,7,99,0,8,126,0,8,62,0,9,221,82,7,27,0,8,110,0,8,46,0,9,189,0,8,14,0,8,142,0,8,78,0,9,253,96,7,256,0,8,81,0,8,17,85,8,131,82,7,31,0,8,113,0,8,49,0,9,195,80,7,10,0,8,97,0,8,33,
+0,9,163,0,8,1,0,8,129,0,8,65,0,9,227,80,7,6,0,8,89,0,8,25,0,9,147,83,7,59,0,8,121,0,8,57,0,9,211,81,7,17,0,8,105,0,8,41,0,9,179,0,8,9,0,8,137,0,8,73,0,9,243,80,7,4,0,8,85,0,8,21,80,8,258,83,7,43,0,8,117,0,8,53,0,9,203,81,7,13,0,8,101,0,8,37,0,9,171,0,8,5,0,8,133,0,8,69,0,9,235,80,7,8,0,8,93,0,8,29,0,9,155,84,7,83,0,8,125,0,8,61,0,9,219,82,7,23,0,8,109,0,8,45,0,9,187,0,8,13,0,8,141,0,8,77,0,9,251,80,7,3,0,8,83,0,8,19,85,8,195,83,7,35,0,8,115,0,8,51,0,9,199,81,7,11,0,8,99,0,8,35,0,9,167,0,8,3,0,8,131,
+0,8,67,0,9,231,80,7,7,0,8,91,0,8,27,0,9,151,84,7,67,0,8,123,0,8,59,0,9,215,82,7,19,0,8,107,0,8,43,0,9,183,0,8,11,0,8,139,0,8,75,0,9,247,80,7,5,0,8,87,0,8,23,192,8,0,83,7,51,0,8,119,0,8,55,0,9,207,81,7,15,0,8,103,0,8,39,0,9,175,0,8,7,0,8,135,0,8,71,0,9,239,80,7,9,0,8,95,0,8,31,0,9,159,84,7,99,0,8,127,0,8,63,0,9,223,82,7,27,0,8,111,0,8,47,0,9,191,0,8,15,0,8,143,0,8,79,0,9,255],A=[80,5,1,87,5,257,83,5,17,91,5,4097,81,5,5,89,5,1025,85,5,65,93,5,16385,80,5,3,88,5,513,84,5,33,92,5,8193,82,5,9,90,5,2049,
+86,5,129,192,5,24577,80,5,2,87,5,385,83,5,25,91,5,6145,81,5,7,89,5,1537,85,5,97,93,5,24577,80,5,4,88,5,769,84,5,49,92,5,12289,82,5,13,90,5,3073,86,5,193,192,5,24577],ka=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],na=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,112,112],fa=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],la=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,
+11,11,12,12,13,13],O=15;b.inflate_trees_fixed=function(a,b,c,d){a[0]=9;b[0]=5;c[0]=o;d[0]=A;return h};var M=0,Z=1,qa=2,ea=3,ca=4,da=5,Q=6,E=7,N=8,Y=9,aa=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],K=0,ha=1,P=2,T=3,ga=4,oa=5,sa=6,B=7,Da=8,ma=9,ia=32,Ba=8,va=0,ja=1,wa=2,xa=3,ya=4,za=5,ta=6,ra=7,Aa=12,pa=13,t=[0,0,255,255];f.prototype={inflateInit:function(a){this.istate=new e;a||(a=15);return this.istate.inflateInit(this,a)},inflate:function(a){return!this.istate?m:this.istate.inflate(this,a)},
+inflateEnd:function(){if(!this.istate)return m;var a=this.istate.inflateEnd(this);this.istate=null;return a},inflateSync:function(){return!this.istate?m:this.istate.inflateSync(this)},inflateSetDictionary:function(a,b){return!this.istate?m:this.istate.inflateSetDictionary(this,a,b)},read_byte:function(a){return this.next_in.subarray(a,a+1)[0]},read_buf:function(a,b){return this.next_in.subarray(a,a+b)}};var ua;a.zip?a.zip.Inflater=g:(ua=new g,a.addEventListener("message",function(b){b=b.data;b.append&&
+a.postMessage({onappend:!0,data:ua.append(b.data,function(b){a.postMessage({progress:!0,current:b})})});b.flush&&(ua.flush(),a.postMessage({onflush:!0}))},!1))})(this);
+function openpgp_crypto_symmetricEncrypt(a,b,c,d,e){switch(b){case 0:return d;case 2:return openpgp_cfb_encrypt(a,desede,d,8,c,e).substring(0,d.length+10);case 3:return openpgp_cfb_encrypt(a,cast5_encrypt,d,8,c,e).substring(0,d.length+10);case 4:return openpgp_cfb_encrypt(a,BFencrypt,d,8,c,e).substring(0,d.length+10);case 7:case 8:case 9:return openpgp_cfb_encrypt(a,AESencrypt,d,16,keyExpansion(c),e).substring(0,d.length+18);case 10:return openpgp_cfb_encrypt(a,TFencrypt,d,16,c,e).substring(0,d.length+
+18);case 1:return util.print_error("IDEA Algorithm not implemented"),null;default:return null}}
+function openpgp_crypto_symmetricDecrypt(a,b,c,d){util.print_debug_hexstr_dump("openpgp_crypto_symmetricDecrypt:\nalgo:"+a+"\nencrypteddata:",c);var e=0;d||(e=2);switch(a){case 0:return c;case 2:return openpgp_cfb_decrypt(desede,8,b,c,d).substring(e,c.length+e-10);case 3:return openpgp_cfb_decrypt(cast5_encrypt,8,b,c,d).substring(e,c.length+e-10);case 4:return openpgp_cfb_decrypt(BFencrypt,8,b,c,d).substring(e,c.length+e-10);case 7:case 8:case 9:return openpgp_cfb_decrypt(AESencrypt,16,keyExpansion(b),
+c,d).substring(e,c.length+e-18);case 10:return openpgp_cfb_decrypt(TFencrypt,16,b,c,d).substring(e,c.length+e-18);case 1:util.print_error(""+(1==a?"IDEA Algorithm not implemented":"Twofish Algorithm not implemented"))}return null}
+function openpgp_crypto_asymetricEncrypt(a,b,c){switch(a){case 1:case 2:case 3:var a=new RSA,d=b[0].toBigInteger(),b=b[1].toBigInteger(),c=c.toBigInteger();return a.encrypt(c,b,d).toMPI();case 16:var a=new Elgamal,d=b[0].toBigInteger(),e=b[1].toBigInteger(),b=b[2].toBigInteger(),c=c.toBigInteger();return a.encrypt(c,e,d,b);default:return null}}
+function openpgp_crypto_asymetricDecrypt(a,b,c,d){switch(a){case 1:case 2:case 3:var a=new RSA,e=c[0].toBigInteger(),b=c[1].toBigInteger(),f=c[2].toBigInteger(),c=c[3].toBigInteger(),d=d[0].toBigInteger();return a.decrypt(d,e,b,f,c);case 16:return a=new Elgamal,c=c[0].toBigInteger(),e=d[0].toBigInteger(),d=d[1].toBigInteger(),b=b[0].toBigInteger(),a.decrypt(e,d,b,c);default:return null}}
+function openpgp_crypto_getPrefixRandom(a){switch(a){case 2:case 3:case 4:return openpgp_crypto_getRandomBytes(8);case 7:case 8:case 9:case 10:return openpgp_crypto_getRandomBytes(16);default:return null}}
+function openpgp_crypto_MDCSystemBytes(a,b,c){util.print_debug_hexstr_dump("openpgp_crypto_symmetricDecrypt:\nencrypteddata:",c);switch(a){case 0:return c;case 2:return openpgp_cfb_mdc(desede,8,b,c,openpgp_cfb);case 3:return openpgp_cfb_mdc(cast5_encrypt,8,b,c);case 4:return openpgp_cfb_mdc(BFencrypt,8,b,c);case 7:case 8:case 9:return openpgp_cfb_mdc(AESencrypt,16,keyExpansion(b),c);case 10:return openpgp_cfb_mdc(TFencrypt,16,b,c);case 1:util.print_error(""+(1==a?"IDEA Algorithm not implemented":
+"Twofish Algorithm not implemented"))}return null}function openpgp_crypto_generateSessionKey(a){switch(a){case 2:case 8:return openpgp_crypto_getRandomBytes(24);case 3:case 4:case 7:return util.print_debug("length = 16:\n"+util.hexstrdump(openpgp_crypto_getRandomBytes(16))),openpgp_crypto_getRandomBytes(16);case 9:case 10:return openpgp_crypto_getRandomBytes(32)}return null}
+function openpgp_crypto_verifySignature(a,b,c,d,e){var f=openpgp_crypto_hashData(b,e);switch(a){case 1:case 2:case 3:e=new RSA;a=d[0].toBigInteger();d=d[1].toBigInteger();c=c[0].toBigInteger();d=e.verify(c,d,a);b=openpgp_encoding_emsa_pkcs1_decode(b,d.toMPI().substring(2));return-1==b?(util.print_error("PKCS1 padding in message or key incorrect. Aborting..."),!1):b==f;case 16:return util.print_error("signing with Elgamal is not defined in the OpenPGP standard."),null;case 17:var a=new DSA,f=c[0].toBigInteger(),
+c=c[1].toBigInteger(),g=d[0].toBigInteger(),h=d[1].toBigInteger(),k=d[2].toBigInteger(),d=d[3].toBigInteger(),d=a.verify(b,f,c,e,g,h,k,d);return 0==d.compareTo(f);default:return null}}
+function openpgp_crypto_signData(a,b,c,d,e){switch(b){case 1:case 2:case 3:var b=new RSA,d=d[0].toBigInteger(),f=c[0].toBigInteger(),a=openpgp_encoding_emsa_pkcs1_encode(a,e,c[0].mpiByteLength);util.print_debug("signing using RSA");return b.sign(a,d,f).toMPI();case 17:b=new DSA;util.print_debug("DSA Sign: q size in Bytes:"+c[1].getByteLength());var f=c[0].toBigInteger(),g=c[1].toBigInteger(),h=c[2].toBigInteger();c[3].toBigInteger();c=d[0].toBigInteger();a=b.sign(a,e,h,f,g,c);util.print_debug("signing using DSA\n result:"+
+util.hexstrdump(a[0])+"|"+util.hexstrdump(a[1]));return a[0]+a[1];case 16:return util.print_debug("signing with Elgamal is not defined in the OpenPGP standard."),null;default:return null}}function openpgp_crypto_hashData(a,b){var c=null;switch(a){case 1:c=MD5(b);break;case 2:c=str_sha1(b);break;case 3:c=RMDstring(b);break;case 8:c=str_sha256(b);break;case 9:c=str_sha384(b);break;case 10:c=str_sha512(b);break;case 11:c=str_sha224(b)}return c}
+function openpgp_crypto_getHashByteLength(a){switch(a){case 1:return 16;case 2:case 3:return 20;case 8:return 32;case 9:return 48;case 10:return 64;case 11:return 28}return null}function openpgp_crypto_getRandomBytes(a){for(var b="",c=0;c<a;c++)b+=String.fromCharCode(openpgp_crypto_getSecureRandomOctet());return b}function openpgp_crypto_getPseudoRandom(a,b){return Math.round(Math.random()*(b-a))+a}
+function openpgp_crypto_getSecureRandom(a,b){var c=new Uint32Array(1);window.crypto.getRandomValues(c);for(var d=(b-a).toString(2).length;(c[0]&Math.pow(2,d)-1)>b-a;)window.crypto.getRandomValues(c);return a+Math.abs(c[0]&Math.pow(2,d)-1)}function openpgp_crypto_getSecureRandomOctet(){var a=new Uint32Array(1);window.crypto.getRandomValues(a);return a[0]&255}
+function openpgp_crypto_getRandomBigInteger(a){if(0>a)return null;var b=openpgp_crypto_getRandomBytes(Math.floor((a+7)/8));0<a%8&&(b=String.fromCharCode(Math.pow(2,a%8)-1&b.charCodeAt(0))+b.substring(1));return(new openpgp_type_mpi).create(b).toBigInteger()}function openpgp_crypto_getRandomBigIntegerInRange(a,b){if(!(0>=b.compareTo(a))){for(var c=b.subtract(a),d=openpgp_crypto_getRandomBigInteger(c.bitLength());d>c;)d=openpgp_crypto_getRandomBigInteger(c.bitLength());return a.add(d)}}
+function openpgp_crypto_testRSA(a){debugger;var b=new RSA,c=new openpgp_type_mpi;c.create(openpgp_encoding_eme_pkcs1_encode("ABABABAB",128));c=b.encrypt(c.toBigInteger(),a.ee,a.n);b.decrypt(c,a.d,a.p,a.q,a.u)}
+function openpgp_crypto_generateKeyPair(a,b,c,d,e){var f,g,h=new Date,h=h.getTime()/1E3,h=String.fromCharCode(Math.floor(h/16777216%256))+String.fromCharCode(Math.floor(h/65536%256))+String.fromCharCode(Math.floor(h/256%256))+String.fromCharCode(Math.floor(h%256));switch(a){case 1:b=(new RSA).generate(b,"10001");f=(new openpgp_packet_keymaterial).write_private_key(a,b,c,d,e,h);g=(new openpgp_packet_keymaterial).write_public_key(a,b,h);break;default:util.print_error("Unknown keytype "+a)}return{privateKey:f,
+publicKey:g}}var dbits,canary=244837814094590,j_lm=15715070==(canary&16777215);function BigInteger(a,b,c){null!=a&&("number"==typeof a?this.fromNumber(a,b,c):null==b&&"string"!=typeof a?this.fromString(a,256):this.fromString(a,b))}function nbi(){return new BigInteger(null)}function am1(a,b,c,d,e,f){for(;0<=--f;){var g=b*this[a++]+c[d]+e,e=Math.floor(g/67108864);c[d++]=g&67108863}return e}
+function am2(a,b,c,d,e,f){for(var g=b&32767,b=b>>15;0<=--f;){var h=this[a]&32767,k=this[a++]>>15,j=b*h+k*g,h=g*h+((j&32767)<<15)+c[d]+(e&1073741823),e=(h>>>30)+(j>>>15)+b*k+(e>>>30);c[d++]=h&1073741823}return e}function am3(a,b,c,d,e,f){for(var g=b&16383,b=b>>14;0<=--f;){var h=this[a]&16383,k=this[a++]>>14,j=b*h+k*g,h=g*h+((j&16383)<<14)+c[d]+e,e=(h>>28)+(j>>14)+b*k;c[d++]=h&268435455}return e}
+j_lm&&"Microsoft Internet Explorer"==navigator.appName?(BigInteger.prototype.am=am2,dbits=30):j_lm&&"Netscape"!=navigator.appName?(BigInteger.prototype.am=am1,dbits=26):(BigInteger.prototype.am=am3,dbits=28);BigInteger.prototype.DB=dbits;BigInteger.prototype.DM=(1<<dbits)-1;BigInteger.prototype.DV=1<<dbits;var BI_FP=52;BigInteger.prototype.FV=Math.pow(2,BI_FP);BigInteger.prototype.F1=BI_FP-dbits;BigInteger.prototype.F2=2*dbits-BI_FP;var BI_RM="0123456789abcdefghijklmnopqrstuvwxyz",BI_RC=[],rr,vv;
+rr=48;for(vv=0;9>=vv;++vv)BI_RC[rr++]=vv;rr=97;for(vv=10;36>vv;++vv)BI_RC[rr++]=vv;rr=65;for(vv=10;36>vv;++vv)BI_RC[rr++]=vv;function int2char(a){return BI_RM.charAt(a)}function intAt(a,b){var c=BI_RC[a.charCodeAt(b)];return null==c?-1:c}function bnpCopyTo(a){for(var b=this.t-1;0<=b;--b)a[b]=this[b];a.t=this.t;a.s=this.s}function bnpFromInt(a){this.t=1;this.s=0>a?-1:0;0<a?this[0]=a:-1>a?this[0]=a+DV:this.t=0}function nbv(a){var b=nbi();b.fromInt(a);return b}
+function bnpFromString(a,b){var c;if(16==b)c=4;else if(8==b)c=3;else if(256==b)c=8;else if(2==b)c=1;else if(32==b)c=5;else if(4==b)c=2;else{this.fromRadix(a,b);return}this.s=this.t=0;for(var d=a.length,e=!1,f=0;0<=--d;){var g=8==c?a[d]&255:intAt(a,d);0>g?"-"==a.charAt(d)&&(e=!0):(e=!1,0==f?this[this.t++]=g:f+c>this.DB?(this[this.t-1]|=(g&(1<<this.DB-f)-1)<<f,this[this.t++]=g>>this.DB-f):this[this.t-1]|=g<<f,f+=c,f>=this.DB&&(f-=this.DB))}if(8==c&&0!=(a[0]&128))this.s=-1,0<f&&(this[this.t-1]|=(1<<
+this.DB-f)-1<<f);this.clamp();e&&BigInteger.ZERO.subTo(this,this)}function bnpClamp(){for(var a=this.s&this.DM;0<this.t&&this[this.t-1]==a;)--this.t}
+function bnToString(a){if(0>this.s)return"-"+this.negate().toString(a);if(16==a)a=4;else if(8==a)a=3;else if(2==a)a=1;else if(32==a)a=5;else if(4==a)a=2;else return this.toRadix(a);var b=(1<<a)-1,c,d=!1,e="",f=this.t,g=this.DB-f*this.DB%a;if(0<f--){if(g<this.DB&&0<(c=this[f]>>g))d=!0,e=int2char(c);for(;0<=f;)g<a?(c=(this[f]&(1<<g)-1)<<a-g,c|=this[--f]>>(g+=this.DB-a)):(c=this[f]>>(g-=a)&b,0>=g&&(g+=this.DB,--f)),0<c&&(d=!0),d&&(e+=int2char(c))}return d?e:"0"}
+function bnNegate(){var a=nbi();BigInteger.ZERO.subTo(this,a);return a}function bnAbs(){return 0>this.s?this.negate():this}function bnCompareTo(a){var b=this.s-a.s;if(0!=b)return b;var c=this.t,b=c-a.t;if(0!=b)return b;for(;0<=--c;)if(0!=(b=this[c]-a[c]))return b;return 0}function nbits(a){var b=1,c;if(0!=(c=a>>>16))a=c,b+=16;if(0!=(c=a>>8))a=c,b+=8;if(0!=(c=a>>4))a=c,b+=4;if(0!=(c=a>>2))a=c,b+=2;0!=a>>1&&(b+=1);return b}
+function bnBitLength(){return 0>=this.t?0:this.DB*(this.t-1)+nbits(this[this.t-1]^this.s&this.DM)}function bnpDLShiftTo(a,b){var c;for(c=this.t-1;0<=c;--c)b[c+a]=this[c];for(c=a-1;0<=c;--c)b[c]=0;b.t=this.t+a;b.s=this.s}function bnpDRShiftTo(a,b){for(var c=a;c<this.t;++c)b[c-a]=this[c];b.t=Math.max(this.t-a,0);b.s=this.s}
+function bnpLShiftTo(a,b){var c=a%this.DB,d=this.DB-c,e=(1<<d)-1,f=Math.floor(a/this.DB),g=this.s<<c&this.DM,h;for(h=this.t-1;0<=h;--h)b[h+f+1]=this[h]>>d|g,g=(this[h]&e)<<c;for(h=f-1;0<=h;--h)b[h]=0;b[f]=g;b.t=this.t+f+1;b.s=this.s;b.clamp()}
+function bnpRShiftTo(a,b){b.s=this.s;var c=Math.floor(a/this.DB);if(c>=this.t)b.t=0;else{var d=a%this.DB,e=this.DB-d,f=(1<<d)-1;b[0]=this[c]>>d;for(var g=c+1;g<this.t;++g)b[g-c-1]|=(this[g]&f)<<e,b[g-c]=this[g]>>d;0<d&&(b[this.t-c-1]|=(this.s&f)<<e);b.t=this.t-c;b.clamp()}}
+function bnpSubTo(a,b){for(var c=0,d=0,e=Math.min(a.t,this.t);c<e;)d+=this[c]-a[c],b[c++]=d&this.DM,d>>=this.DB;if(a.t<this.t){for(d-=a.s;c<this.t;)d+=this[c],b[c++]=d&this.DM,d>>=this.DB;d+=this.s}else{for(d+=this.s;c<a.t;)d-=a[c],b[c++]=d&this.DM,d>>=this.DB;d-=a.s}b.s=0>d?-1:0;-1>d?b[c++]=this.DV+d:0<d&&(b[c++]=d);b.t=c;b.clamp()}
+function bnpMultiplyTo(a,b){var c=this.abs(),d=a.abs(),e=c.t;for(b.t=e+d.t;0<=--e;)b[e]=0;for(e=0;e<d.t;++e)b[e+c.t]=c.am(0,d[e],b,e,0,c.t);b.s=0;b.clamp();this.s!=a.s&&BigInteger.ZERO.subTo(b,b)}function bnpSquareTo(a){for(var b=this.abs(),c=a.t=2*b.t;0<=--c;)a[c]=0;for(c=0;c<b.t-1;++c){var d=b.am(c,b[c],a,2*c,0,1);if((a[c+b.t]+=b.am(c+1,2*b[c],a,2*c+1,d,b.t-c-1))>=b.DV)a[c+b.t]-=b.DV,a[c+b.t+1]=1}0<a.t&&(a[a.t-1]+=b.am(c,b[c],a,2*c,0,1));a.s=0;a.clamp()}
+function bnpDivRemTo(a,b,c){var d=a.abs();if(!(0>=d.t)){var e=this.abs();if(e.t<d.t)null!=b&&b.fromInt(0),null!=c&&this.copyTo(c);else{null==c&&(c=nbi());var f=nbi(),g=this.s,a=a.s,h=this.DB-nbits(d[d.t-1]);0<h?(d.lShiftTo(h,f),e.lShiftTo(h,c)):(d.copyTo(f),e.copyTo(c));d=f.t;e=f[d-1];if(0!=e){var k=e*(1<<this.F1)+(1<d?f[d-2]>>this.F2:0),j=this.FV/k,k=(1<<this.F1)/k,m=1<<this.F2,u=c.t,D=u-d,l=null==b?nbi():b;f.dlShiftTo(D,l);0<=c.compareTo(l)&&(c[c.t++]=1,c.subTo(l,c));BigInteger.ONE.dlShiftTo(d,
+l);for(l.subTo(f,f);f.t<d;)f[f.t++]=0;for(;0<=--D;){var p=c[--u]==e?this.DM:Math.floor(c[u]*j+(c[u-1]+m)*k);if((c[u]+=f.am(0,p,c,D,0,d))<p){f.dlShiftTo(D,l);for(c.subTo(l,c);c[u]<--p;)c.subTo(l,c)}}null!=b&&(c.drShiftTo(d,b),g!=a&&BigInteger.ZERO.subTo(b,b));c.t=d;c.clamp();0<h&&c.rShiftTo(h,c);0>g&&BigInteger.ZERO.subTo(c,c)}}}}function bnMod(a){var b=nbi();this.abs().divRemTo(a,null,b);0>this.s&&0<b.compareTo(BigInteger.ZERO)&&a.subTo(b,b);return b}function Classic(a){this.m=a}
+function cConvert(a){return 0>a.s||0<=a.compareTo(this.m)?a.mod(this.m):a}function cRevert(a){return a}function cReduce(a){a.divRemTo(this.m,null,a)}function cMulTo(a,b,c){a.multiplyTo(b,c);this.reduce(c)}function cSqrTo(a,b){a.squareTo(b);this.reduce(b)}Classic.prototype.convert=cConvert;Classic.prototype.revert=cRevert;Classic.prototype.reduce=cReduce;Classic.prototype.mulTo=cMulTo;Classic.prototype.sqrTo=cSqrTo;
+function bnpInvDigit(){if(1>this.t)return 0;var a=this[0];if(0==(a&1))return 0;var b=a&3,b=b*(2-(a&15)*b)&15,b=b*(2-(a&255)*b)&255,b=b*(2-((a&65535)*b&65535))&65535,b=b*(2-a*b%this.DV)%this.DV;return 0<b?this.DV-b:-b}function Montgomery(a){this.m=a;this.mp=a.invDigit();this.mpl=this.mp&32767;this.mph=this.mp>>15;this.um=(1<<a.DB-15)-1;this.mt2=2*a.t}
+function montConvert(a){var b=nbi();a.abs().dlShiftTo(this.m.t,b);b.divRemTo(this.m,null,b);0>a.s&&0<b.compareTo(BigInteger.ZERO)&&this.m.subTo(b,b);return b}function montRevert(a){var b=nbi();a.copyTo(b);this.reduce(b);return b}
+function montReduce(a){for(;a.t<=this.mt2;)a[a.t++]=0;for(var b=0;b<this.m.t;++b){var c=a[b]&32767,d=c*this.mpl+((c*this.mph+(a[b]>>15)*this.mpl&this.um)<<15)&a.DM,c=b+this.m.t;for(a[c]+=this.m.am(0,d,a,b,0,this.m.t);a[c]>=a.DV;)a[c]-=a.DV,a[++c]++}a.clamp();a.drShiftTo(this.m.t,a);0<=a.compareTo(this.m)&&a.subTo(this.m,a)}function montSqrTo(a,b){a.squareTo(b);this.reduce(b)}function montMulTo(a,b,c){a.multiplyTo(b,c);this.reduce(c)}Montgomery.prototype.convert=montConvert;
+Montgomery.prototype.revert=montRevert;Montgomery.prototype.reduce=montReduce;Montgomery.prototype.mulTo=montMulTo;Montgomery.prototype.sqrTo=montSqrTo;function bnpIsEven(){return 0==(0<this.t?this[0]&1:this.s)}function bnpExp(a,b){if(4294967295<a||1>a)return BigInteger.ONE;var c=nbi(),d=nbi(),e=b.convert(this),f=nbits(a)-1;for(e.copyTo(c);0<=--f;)if(b.sqrTo(c,d),0<(a&1<<f))b.mulTo(d,e,c);else var g=c,c=d,d=g;return b.revert(c)}
+function bnModPowInt(a,b){var c;c=256>a||b.isEven()?new Classic(b):new Montgomery(b);return this.exp(a,c)}BigInteger.prototype.copyTo=bnpCopyTo;BigInteger.prototype.fromInt=bnpFromInt;BigInteger.prototype.fromString=bnpFromString;BigInteger.prototype.clamp=bnpClamp;BigInteger.prototype.dlShiftTo=bnpDLShiftTo;BigInteger.prototype.drShiftTo=bnpDRShiftTo;BigInteger.prototype.lShiftTo=bnpLShiftTo;BigInteger.prototype.rShiftTo=bnpRShiftTo;BigInteger.prototype.subTo=bnpSubTo;
+BigInteger.prototype.multiplyTo=bnpMultiplyTo;BigInteger.prototype.squareTo=bnpSquareTo;BigInteger.prototype.divRemTo=bnpDivRemTo;BigInteger.prototype.invDigit=bnpInvDigit;BigInteger.prototype.isEven=bnpIsEven;BigInteger.prototype.exp=bnpExp;BigInteger.prototype.toString=bnToString;BigInteger.prototype.negate=bnNegate;BigInteger.prototype.abs=bnAbs;BigInteger.prototype.compareTo=bnCompareTo;BigInteger.prototype.bitLength=bnBitLength;BigInteger.prototype.mod=bnMod;BigInteger.prototype.modPowInt=bnModPowInt;
+BigInteger.ZERO=nbv(0);BigInteger.ONE=nbv(1);function SecureRandom(){this.nextBytes=function(a){for(var b=0;b<a.length;b++)a[b]=openpgp_crypto_getSecureRandomOctet()}}
+function RSA(){function a(){this.n=null;this.e=0;this.u=this.dmq1=this.dmp1=this.q=this.p=this.d=this.ee=null}this.encrypt=function(a,c,d){return a.modPowInt(c,d)};this.decrypt=function(a,c,d,e,f){var g=a.mod(d).modPow(c.mod(d.subtract(BigInteger.ONE)),d),a=a.mod(e).modPow(c.mod(e.subtract(BigInteger.ONE)),e);util.print_debug("rsa.js decrypt\nxpn:"+util.hexstrdump(g.toMPI())+"\nxqn:"+util.hexstrdump(a.toMPI()));c=a.subtract(g);0==c[0]?(c=g.subtract(a),c=c.multiply(f).mod(e),c=e.subtract(c)):c=c.multiply(f).mod(e);
+return c.multiply(d).add(g)};this.verify=function(a,c,d){return a.modPowInt(c,d)};this.sign=function(a,c,d){return a.modPow(c,d)};this.generate=function(b,c){var d=new a,e=new SecureRandom,f=b>>1;d.e=parseInt(c,16);for(d.ee=new BigInteger(c,16);;){for(;!(d.p=new BigInteger(b-f,1,e),0==d.p.subtract(BigInteger.ONE).gcd(d.ee).compareTo(BigInteger.ONE)&&d.p.isProbablePrime(10)););for(;!(d.q=new BigInteger(f,1,e),0==d.q.subtract(BigInteger.ONE).gcd(d.ee).compareTo(BigInteger.ONE)&&d.q.isProbablePrime(10)););
+if(0>=d.p.compareTo(d.q)){var g=d.p;d.p=d.q;d.q=g}var g=d.p.subtract(BigInteger.ONE),h=d.q.subtract(BigInteger.ONE),k=g.multiply(h);if(0==k.gcd(d.ee).compareTo(BigInteger.ONE)){d.n=d.p.multiply(d.q);d.d=d.ee.modInverse(k);d.dmp1=d.d.mod(g);d.dmq1=d.d.mod(h);d.u=d.p.modInverse(d.q);break}}return d};this.keyObject=a}function bnClone(){var a=nbi();this.copyTo(a);return a}
+function bnIntValue(){if(0>this.s){if(1==this.t)return this[0]-this.DV;if(0==this.t)return-1}else{if(1==this.t)return this[0];if(0==this.t)return 0}return(this[1]&(1<<32-this.DB)-1)<<this.DB|this[0]}function bnByteValue(){return 0==this.t?this.s:this[0]<<24>>24}function bnShortValue(){return 0==this.t?this.s:this[0]<<16>>16}function bnpChunkSize(a){return Math.floor(Math.LN2*this.DB/Math.log(a))}function bnSigNum(){return 0>this.s?-1:0>=this.t||1==this.t&&0>=this[0]?0:1}
+function bnpToRadix(a){null==a&&(a=10);if(0==this.signum()||2>a||36<a)return"0";var b=this.chunkSize(a),b=Math.pow(a,b),c=nbv(b),d=nbi(),e=nbi(),f="";for(this.divRemTo(c,d,e);0<d.signum();)f=(b+e.intValue()).toString(a).substr(1)+f,d.divRemTo(c,d,e);return e.intValue().toString(a)+f}
+function bnpFromRadix(a,b){this.fromInt(0);null==b&&(b=10);for(var c=this.chunkSize(b),d=Math.pow(b,c),e=!1,f=0,g=0,h=0;h<a.length;++h){var k=intAt(a,h);0>k?"-"==a.charAt(h)&&0==this.signum()&&(e=!0):(g=b*g+k,++f>=c&&(this.dMultiply(d),this.dAddOffset(g,0),g=f=0))}0<f&&(this.dMultiply(Math.pow(b,f)),this.dAddOffset(g,0));e&&BigInteger.ZERO.subTo(this,this)}
+function bnpFromNumber(a,b,c){if("number"==typeof b)if(2>a)this.fromInt(1);else{this.fromNumber(a,c);this.testBit(a-1)||this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);for(this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(b);)this.dAddOffset(2,0),this.bitLength()>a&&this.subTo(BigInteger.ONE.shiftLeft(a-1),this)}else{var c=[],d=a&7;c.length=(a>>3)+1;b.nextBytes(c);c[0]=0<d?c[0]&(1<<d)-1:0;this.fromString(c,256)}}
+function bnToByteArray(){var a=this.t,b=[];b[0]=this.s;var c=this.DB-a*this.DB%8,d,e=0;if(0<a--){if(c<this.DB&&(d=this[a]>>c)!=(this.s&this.DM)>>c)b[e++]=d|this.s<<this.DB-c;for(;0<=a;)if(8>c?(d=(this[a]&(1<<c)-1)<<8-c,d|=this[--a]>>(c+=this.DB-8)):(d=this[a]>>(c-=8)&255,0>=c&&(c+=this.DB,--a)),0<e||d!=this.s)b[e++]=d}return b}function bnEquals(a){return 0==this.compareTo(a)}function bnMin(a){return 0>this.compareTo(a)?this:a}function bnMax(a){return 0<this.compareTo(a)?this:a}
+function bnpBitwiseTo(a,b,c){var d,e,f=Math.min(a.t,this.t);for(d=0;d<f;++d)c[d]=b(this[d],a[d]);if(a.t<this.t){e=a.s&this.DM;for(d=f;d<this.t;++d)c[d]=b(this[d],e);c.t=this.t}else{e=this.s&this.DM;for(d=f;d<a.t;++d)c[d]=b(e,a[d]);c.t=a.t}c.s=b(this.s,a.s);c.clamp()}function op_and(a,b){return a&b}function bnAnd(a){var b=nbi();this.bitwiseTo(a,op_and,b);return b}function op_or(a,b){return a|b}function bnOr(a){var b=nbi();this.bitwiseTo(a,op_or,b);return b}function op_xor(a,b){return a^b}
+function bnXor(a){var b=nbi();this.bitwiseTo(a,op_xor,b);return b}function op_andnot(a,b){return a&~b}function bnAndNot(a){var b=nbi();this.bitwiseTo(a,op_andnot,b);return b}function bnNot(){for(var a=nbi(),b=0;b<this.t;++b)a[b]=this.DM&~this[b];a.t=this.t;a.s=~this.s;return a}function bnShiftLeft(a){var b=nbi();0>a?this.rShiftTo(-a,b):this.lShiftTo(a,b);return b}function bnShiftRight(a){var b=nbi();0>a?this.lShiftTo(-a,b):this.rShiftTo(a,b);return b}
+function lbit(a){if(0==a)return-1;var b=0;0==(a&65535)&&(a>>=16,b+=16);0==(a&255)&&(a>>=8,b+=8);0==(a&15)&&(a>>=4,b+=4);0==(a&3)&&(a>>=2,b+=2);0==(a&1)&&++b;return b}function bnGetLowestSetBit(){for(var a=0;a<this.t;++a)if(0!=this[a])return a*this.DB+lbit(this[a]);return 0>this.s?this.t*this.DB:-1}function cbit(a){for(var b=0;0!=a;)a&=a-1,++b;return b}function bnBitCount(){for(var a=0,b=this.s&this.DM,c=0;c<this.t;++c)a+=cbit(this[c]^b);return a}
+function bnTestBit(a){var b=Math.floor(a/this.DB);return b>=this.t?0!=this.s:0!=(this[b]&1<<a%this.DB)}function bnpChangeBit(a,b){var c=BigInteger.ONE.shiftLeft(a);this.bitwiseTo(c,b,c);return c}function bnSetBit(a){return this.changeBit(a,op_or)}function bnClearBit(a){return this.changeBit(a,op_andnot)}function bnFlipBit(a){return this.changeBit(a,op_xor)}
+function bnpAddTo(a,b){for(var c=0,d=0,e=Math.min(a.t,this.t);c<e;)d+=this[c]+a[c],b[c++]=d&this.DM,d>>=this.DB;if(a.t<this.t){for(d+=a.s;c<this.t;)d+=this[c],b[c++]=d&this.DM,d>>=this.DB;d+=this.s}else{for(d+=this.s;c<a.t;)d+=a[c],b[c++]=d&this.DM,d>>=this.DB;d+=a.s}b.s=0>d?-1:0;0<d?b[c++]=d:-1>d&&(b[c++]=this.DV+d);b.t=c;b.clamp()}function bnAdd(a){var b=nbi();this.addTo(a,b);return b}function bnSubtract(a){var b=nbi();this.subTo(a,b);return b}
+function bnMultiply(a){var b=nbi();this.multiplyTo(a,b);return b}function bnSquare(){var a=nbi();this.squareTo(a);return a}function bnDivide(a){var b=nbi();this.divRemTo(a,b,null);return b}function bnRemainder(a){var b=nbi();this.divRemTo(a,null,b);return b}function bnDivideAndRemainder(a){var b=nbi(),c=nbi();this.divRemTo(a,b,c);return[b,c]}function bnpDMultiply(a){this[this.t]=this.am(0,a-1,this,0,0,this.t);++this.t;this.clamp()}
+function bnpDAddOffset(a,b){if(0!=a){for(;this.t<=b;)this[this.t++]=0;for(this[b]+=a;this[b]>=this.DV;)this[b]-=this.DV,++b>=this.t&&(this[this.t++]=0),++this[b]}}function NullExp(){}function nNop(a){return a}function nMulTo(a,b,c){a.multiplyTo(b,c)}function nSqrTo(a,b){a.squareTo(b)}NullExp.prototype.convert=nNop;NullExp.prototype.revert=nNop;NullExp.prototype.mulTo=nMulTo;NullExp.prototype.sqrTo=nSqrTo;function bnPow(a){return this.exp(a,new NullExp)}
+function bnpMultiplyLowerTo(a,b,c){var d=Math.min(this.t+a.t,b);c.s=0;for(c.t=d;0<d;)c[--d]=0;var e;for(e=c.t-this.t;d<e;++d)c[d+this.t]=this.am(0,a[d],c,d,0,this.t);for(e=Math.min(a.t,b);d<e;++d)this.am(0,a[d],c,d,0,b-d);c.clamp()}function bnpMultiplyUpperTo(a,b,c){--b;var d=c.t=this.t+a.t-b;for(c.s=0;0<=--d;)c[d]=0;for(d=Math.max(b-this.t,0);d<a.t;++d)c[this.t+d-b]=this.am(b-d,a[d],c,0,0,this.t+d-b);c.clamp();c.drShiftTo(1,c)}
+function Barrett(a){this.r2=nbi();this.q3=nbi();BigInteger.ONE.dlShiftTo(2*a.t,this.r2);this.mu=this.r2.divide(a);this.m=a}function barrettConvert(a){if(0>a.s||a.t>2*this.m.t)return a.mod(this.m);if(0>a.compareTo(this.m))return a;var b=nbi();a.copyTo(b);this.reduce(b);return b}function barrettRevert(a){return a}
+function barrettReduce(a){a.drShiftTo(this.m.t-1,this.r2);if(a.t>this.m.t+1)a.t=this.m.t+1,a.clamp();this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);for(this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);0>a.compareTo(this.r2);)a.dAddOffset(1,this.m.t+1);for(a.subTo(this.r2,a);0<=a.compareTo(this.m);)a.subTo(this.m,a)}function barrettSqrTo(a,b){a.squareTo(b);this.reduce(b)}function barrettMulTo(a,b,c){a.multiplyTo(b,c);this.reduce(c)}Barrett.prototype.convert=barrettConvert;
+Barrett.prototype.revert=barrettRevert;Barrett.prototype.reduce=barrettReduce;Barrett.prototype.mulTo=barrettMulTo;Barrett.prototype.sqrTo=barrettSqrTo;
+function bnModPow(a,b){var c=a.bitLength(),d,e=nbv(1),f;if(0>=c)return e;d=18>c?1:48>c?3:144>c?4:768>c?5:6;f=8>c?new Classic(b):b.isEven()?new Barrett(b):new Montgomery(b);var g=[],h=3,k=d-1,j=(1<<d)-1;g[1]=f.convert(this);if(1<d){c=nbi();for(f.sqrTo(g[1],c);h<=j;)g[h]=nbi(),f.mulTo(c,g[h-2],g[h]),h+=2}for(var m=a.t-1,u,D=!0,l=nbi(),c=nbits(a[m])-1;0<=m;){c>=k?u=a[m]>>c-k&j:(u=(a[m]&(1<<c+1)-1)<<k-c,0<m&&(u|=a[m-1]>>this.DB+c-k));for(h=d;0==(u&1);)u>>=1,--h;if(0>(c-=h))c+=this.DB,--m;if(D)g[u].copyTo(e),
+D=!1;else{for(;1<h;)f.sqrTo(e,l),f.sqrTo(l,e),h-=2;0<h?f.sqrTo(e,l):(h=e,e=l,l=h);f.mulTo(l,g[u],e)}for(;0<=m&&0==(a[m]&1<<c);)f.sqrTo(e,l),h=e,e=l,l=h,0>--c&&(c=this.DB-1,--m)}return f.revert(e)}
+function bnGCD(a){var b=0>this.s?this.negate():this.clone(),a=0>a.s?a.negate():a.clone();if(0>b.compareTo(a))var c=b,b=a,a=c;var c=b.getLowestSetBit(),d=a.getLowestSetBit();if(0>d)return b;c<d&&(d=c);0<d&&(b.rShiftTo(d,b),a.rShiftTo(d,a));for(;0<b.signum();)0<(c=b.getLowestSetBit())&&b.rShiftTo(c,b),0<(c=a.getLowestSetBit())&&a.rShiftTo(c,a),0<=b.compareTo(a)?(b.subTo(a,b),b.rShiftTo(1,b)):(a.subTo(b,a),a.rShiftTo(1,a));0<d&&a.lShiftTo(d,a);return a}
+function bnpModInt(a){if(0>=a)return 0;var b=this.DV%a,c=0>this.s?a-1:0;if(0<this.t)if(0==b)c=this[0]%a;else for(var d=this.t-1;0<=d;--d)c=(b*c+this[d])%a;return c}
+function bnModInverse(a){var b=a.isEven();if(this.isEven()&&b||0==a.signum())return BigInteger.ZERO;for(var c=a.clone(),d=this.clone(),e=nbv(1),f=nbv(0),g=nbv(0),h=nbv(1);0!=c.signum();){for(;c.isEven();){c.rShiftTo(1,c);if(b){if(!e.isEven()||!f.isEven())e.addTo(this,e),f.subTo(a,f);e.rShiftTo(1,e)}else f.isEven()||f.subTo(a,f);f.rShiftTo(1,f)}for(;d.isEven();){d.rShiftTo(1,d);if(b){if(!g.isEven()||!h.isEven())g.addTo(this,g),h.subTo(a,h);g.rShiftTo(1,g)}else h.isEven()||h.subTo(a,h);h.rShiftTo(1,
+h)}0<=c.compareTo(d)?(c.subTo(d,c),b&&e.subTo(g,e),f.subTo(h,f)):(d.subTo(c,d),b&&g.subTo(e,g),h.subTo(f,h))}if(0!=d.compareTo(BigInteger.ONE))return BigInteger.ZERO;if(0<=h.compareTo(a))return h.subtract(a);if(0>h.signum())h.addTo(a,h);else return h;return 0>h.signum()?h.add(a):h}
+var lowprimes=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,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],lplim=67108864/lowprimes[lowprimes.length-1];
+function bnIsProbablePrime(a){var b,c=this.abs();if(1==c.t&&c[0]<=lowprimes[lowprimes.length-1]){for(b=0;b<lowprimes.length;++b)if(c[0]==lowprimes[b])return!0;return!1}if(c.isEven())return!1;for(b=1;b<lowprimes.length;){for(var d=lowprimes[b],e=b+1;e<lowprimes.length&&d<lplim;)d*=lowprimes[e++];for(d=c.modInt(d);b<e;)if(0==d%lowprimes[b++])return!1}return c.millerRabin(a)}
+function nbits(a){var b=1,c;if(0!=(c=a>>>16))a=c,b+=16;if(0!=(c=a>>8))a=c,b+=8;if(0!=(c=a>>4))a=c,b+=4;if(0!=(c=a>>2))a=c,b+=2;0!=a>>1&&(b+=1);return b}function bnToMPI(){var a=this.toByteArray(),b=8*(a.length-1)+nbits(a[0]),c;c=""+String.fromCharCode((b&65280)>>8);c+=String.fromCharCode(b&255);return c+=util.bin2str(a)}
+function bnpMillerRabin(a){var b=this.subtract(BigInteger.ONE),c=b.getLowestSetBit();if(0>=c)return!1;var d=b.shiftRight(c),a=a+1>>1;if(a>lowprimes.length)a=lowprimes.length;for(var e=nbi(),f=0;f<a;++f){e.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);var g=e.modPow(d,this);if(0!=g.compareTo(BigInteger.ONE)&&0!=g.compareTo(b)){for(var h=1;h++<c&&0!=g.compareTo(b);)if(g=g.modPowInt(2,this),0==g.compareTo(BigInteger.ONE))return!1;if(0!=g.compareTo(b))return!1}}return!0}
+BigInteger.prototype.chunkSize=bnpChunkSize;BigInteger.prototype.toRadix=bnpToRadix;BigInteger.prototype.fromRadix=bnpFromRadix;BigInteger.prototype.fromNumber=bnpFromNumber;BigInteger.prototype.bitwiseTo=bnpBitwiseTo;BigInteger.prototype.changeBit=bnpChangeBit;BigInteger.prototype.addTo=bnpAddTo;BigInteger.prototype.dMultiply=bnpDMultiply;BigInteger.prototype.dAddOffset=bnpDAddOffset;BigInteger.prototype.multiplyLowerTo=bnpMultiplyLowerTo;BigInteger.prototype.multiplyUpperTo=bnpMultiplyUpperTo;
+BigInteger.prototype.modInt=bnpModInt;BigInteger.prototype.millerRabin=bnpMillerRabin;BigInteger.prototype.clone=bnClone;BigInteger.prototype.intValue=bnIntValue;BigInteger.prototype.byteValue=bnByteValue;BigInteger.prototype.shortValue=bnShortValue;BigInteger.prototype.signum=bnSigNum;BigInteger.prototype.toByteArray=bnToByteArray;BigInteger.prototype.equals=bnEquals;BigInteger.prototype.min=bnMin;BigInteger.prototype.max=bnMax;BigInteger.prototype.and=bnAnd;BigInteger.prototype.or=bnOr;
+BigInteger.prototype.xor=bnXor;BigInteger.prototype.andNot=bnAndNot;BigInteger.prototype.not=bnNot;BigInteger.prototype.shiftLeft=bnShiftLeft;BigInteger.prototype.shiftRight=bnShiftRight;BigInteger.prototype.getLowestSetBit=bnGetLowestSetBit;BigInteger.prototype.bitCount=bnBitCount;BigInteger.prototype.testBit=bnTestBit;BigInteger.prototype.setBit=bnSetBit;BigInteger.prototype.clearBit=bnClearBit;BigInteger.prototype.flipBit=bnFlipBit;BigInteger.prototype.add=bnAdd;BigInteger.prototype.subtract=bnSubtract;
+BigInteger.prototype.multiply=bnMultiply;BigInteger.prototype.divide=bnDivide;BigInteger.prototype.remainder=bnRemainder;BigInteger.prototype.divideAndRemainder=bnDivideAndRemainder;BigInteger.prototype.modPow=bnModPow;BigInteger.prototype.modInverse=bnModInverse;BigInteger.prototype.pow=bnPow;BigInteger.prototype.gcd=bnGCD;BigInteger.prototype.isProbablePrime=bnIsProbablePrime;BigInteger.prototype.toMPI=bnToMPI;BigInteger.prototype.square=bnSquare;
+function Elgamal(){this.encrypt=function(a,b,c,d){var e=BigInteger.ONE.add(BigInteger.ONE),f=c.subtract(e),e=openpgp_crypto_getRandomBigIntegerInRange(e,f),e=e.mod(f).add(BigInteger.ONE),f=[];f[0]=b.modPow(e,c);f[1]=d.modPow(e,c).multiply(a).mod(c).toMPI();f[0]=f[0].toMPI();return f};this.decrypt=function(a,b,c,d){util.print_debug("Elgamal Decrypt:\nc1:"+util.hexstrdump(a.toMPI())+"\nc2:"+util.hexstrdump(b.toMPI())+"\np:"+util.hexstrdump(c.toMPI())+"\nx:"+util.hexstrdump(d.toMPI()));return a.modPow(d,
+c).modInverse(c).multiply(b).mod(c)}}
+function DSA(){this.select_hash_algorithm=function(a){var b=openpgp.config.config.prefer_hash_algorithm;switch(Math.round(a.bitLength()/8)){case 20:return 2!=b&&11<b&&10!=b&&8>b?2:b;case 28:return 11<b&&8>b?11:b;case 32:return 10<b&&8>b?8:b;default:return util.print_debug("DSA select hash algorithm: returning null for an unknown length of q"),null}};this.sign=function(a,b,c,d,e,f){a=util.getLeftNBits(openpgp_crypto_hashData(a,b),e.bitLength());a=new BigInteger(util.hexstrdump(a),16);b=openpgp_crypto_getRandomBigIntegerInRange(BigInteger.ONE.add(BigInteger.ONE),
+e.subtract(BigInteger.ONE));c=c.modPow(b,d).mod(e);e=b.modInverse(e).multiply(a.add(f.multiply(c))).mod(e);f=[];f[0]=c.toMPI();f[1]=e.toMPI();return f};this.verify=function(a,b,c,d,e,f,g,h){a=util.getLeftNBits(openpgp_crypto_hashData(a,d),f.bitLength());a=new BigInteger(util.hexstrdump(a),16);if(0<BigInteger.ZERO.compareTo(b)||0<b.compareTo(f)||0<BigInteger.ZERO.compareTo(c)||0<c.compareTo(f))return util.print_error("invalid DSA Signature"),null;c=c.modInverse(f);a=a.multiply(c).mod(f);b=b.multiply(c).mod(f);
+return g.modPow(a,e).multiply(h.modPow(b,e)).mod(e).mod(f)}}function desede(a,b){var c=b.substring(0,8),d=b.substring(8,16),e=b.substring(16,24);return util.str2bin(des(des_createKeys(e),des(des_createKeys(d),des(des_createKeys(c),util.bin2str(a),!0,0,null,null),!1,0,null,null),!0,0,null,null))}
+function des(a,b,c,d,e,f){var g=[16843776,0,65536,16843780,16842756,66564,4,65536,1024,16843776,16843780,1024,16778244,16842756,16777216,4,1028,16778240,16778240,66560,66560,16842752,16842752,16778244,65540,16777220,16777220,65540,0,1028,66564,16777216,65536,16843780,4,16842752,16843776,16777216,16777216,1024,16842756,65536,66560,16777220,1024,4,16778244,66564,16843780,65540,16842752,16778244,16777220,1028,66564,16843776,1028,16778240,16778240,0,65540,66560,0,16842756],h=[-2146402272,-2147450880,
 32768,1081376,1048576,32,-2146435040,-2147450848,-2147483616,-2146402272,-2146402304,-2147483648,-2147450880,1048576,32,-2146435040,1081344,1048608,-2147450848,0,-2147483648,32768,1081376,-2146435072,1048608,-2147483616,0,1081344,32800,-2146402304,-2146435072,32800,0,1081376,-2146435040,1048576,-2147450848,-2146435072,-2146402304,32768,-2146435072,-2147450880,32,-2146402272,1081376,32,32768,-2147483648,32800,-2146402304,1048576,-2147483616,1048608,-2147450848,-2147483616,1048608,1081344,0,-2147450880,
 32800,-2147483648,-2146435040,-2146402272,1081344],k=[520,134349312,0,134348808,134218240,0,131592,134218240,131080,134217736,134217736,131072,134349320,131080,134348800,520,134217728,8,134349312,512,131584,134348800,134348808,131592,134218248,131584,131072,134218248,8,134349320,512,134217728,134349312,134217728,131080,520,131072,134349312,134218240,0,512,131080,134349320,134218240,134217736,512,0,134348808,134218248,131072,134217728,134349320,8,131592,131584,134217736,134348800,134218248,520,134348800,
-131592,8,134348808,131584],j=[8396801,8321,8321,128,8396928,8388737,8388609,8193,0,8396800,8396800,8396929,129,0,8388736,8388609,1,8192,8388608,8396801,128,8388608,8193,8320,8388737,1,8320,8388736,8192,8396928,8396929,129,8388736,8388609,8396800,8396929,129,0,0,8396800,8320,8388736,8388737,1,8396801,8321,8321,128,8396929,129,1,8192,8388609,8193,8396928,8388737,8193,8320,8388608,8396801,128,8388608,8192,8396928],l=[256,34078976,34078720,1107296512,524288,256,1073741824,34078720,1074266368,524288,33554688,
-1074266368,1107296512,1107820544,524544,1073741824,33554432,1074266112,1074266112,0,1073742080,1107820800,1107820800,33554688,1107820544,1073742080,0,1107296256,34078976,33554432,1107296256,524544,524288,1107296512,256,33554432,1073741824,34078720,1107296512,1074266368,33554688,1073741824,1107820544,34078976,1074266368,256,33554432,1107820544,1107820800,524544,1107296256,1107820800,34078720,0,1074266112,1107296256,524544,33554688,1073742080,524288,0,1074266112,34078976,1073742080],q=[536870928,541065216,
-16384,541081616,541065216,16,541081616,4194304,536887296,4210704,4194304,536870928,4194320,536887296,536870912,16400,0,4194320,536887312,16384,4210688,536887312,16,541065232,541065232,0,4210704,541081600,16400,4210688,541081600,536870912,536887296,16,541065232,4210688,541081616,4194304,16400,536870928,4194304,536887296,536870912,16400,536870928,541081616,4210688,541065216,4210704,541081600,0,541065232,16,16384,541065216,4210704,16384,4194320,536887312,0,541081600,536870912,4194320,536887312],u=[2097152,
-69206018,67110914,0,2048,67110914,2099202,69208064,69208066,2097152,0,67108866,2,67108864,69206018,2050,67110912,2099202,2097154,67110912,67108866,69206016,69208064,2097154,69206016,2048,2050,69208066,2099200,2,67108864,2099200,67108864,2099200,2097152,67110914,67110914,69206018,69206018,2,2097154,67108864,67110912,2097152,69208064,2050,2099202,69208064,2050,67108866,69208066,69206016,2099200,0,2,69208066,0,2099202,69206016,2048,67108866,67110912,2048,2097154],m=[268439616,4096,262144,268701760,268435456,
-268439616,64,268435456,262208,268697600,268701760,266240,268701696,266304,4096,64,268697600,268435520,268439552,4160,266240,262208,268697664,268701696,4160,0,0,268697664,268435520,268439552,266304,262144,266304,262144,268701696,4096,64,268697664,4096,266304,268439552,64,268435520,268697600,268697664,268435456,262144,268439616,0,268701760,262208,268435520,268697600,268439552,268439616,0,268701760,266240,266240,4160,4160,262208,268435456,268701696],o=0,M,O,D,B,A,ga,ia,aa,ha,K,E,V,ma=b.length,Z=0,ba=
-32==a.length?3:9;ga=3==ba?c?[0,32,2]:[30,-2,-2]:c?[0,32,2,62,30,-2,64,96,2]:[94,62,-2,32,64,2,30,-2,-2];2==f?b+="        ":1==f?(f=8-ma%8,b+=String.fromCharCode(f,f,f,f,f,f,f,f),8==f&&(ma+=8)):f||(b+="\x00\x00\x00\x00\x00\x00\x00\x00");tempresult=result="";1==d&&(ia=e.charCodeAt(o++)<<24|e.charCodeAt(o++)<<16|e.charCodeAt(o++)<<8|e.charCodeAt(o++),ha=e.charCodeAt(o++)<<24|e.charCodeAt(o++)<<16|e.charCodeAt(o++)<<8|e.charCodeAt(o++),o=0);for(;o<ma;){B=b.charCodeAt(o++)<<24|b.charCodeAt(o++)<<16|b.charCodeAt(o++)<<
-8|b.charCodeAt(o++);A=b.charCodeAt(o++)<<24|b.charCodeAt(o++)<<16|b.charCodeAt(o++)<<8|b.charCodeAt(o++);1==d&&(c?(B^=ia,A^=ha):(aa=ia,K=ha,ia=B,ha=A));f=(B>>>4^A)&252645135;A^=f;B^=f<<4;f=(B>>>16^A)&65535;A^=f;B^=f<<16;f=(A>>>2^B)&858993459;B^=f;A^=f<<2;f=(A>>>8^B)&16711935;B^=f;A^=f<<8;f=(B>>>1^A)&1431655765;A^=f;B^=f<<1;B=B<<1|B>>>31;A=A<<1|A>>>31;for(M=0;M<ba;M+=3){E=ga[M+1];V=ga[M+2];for(e=ga[M];e!=E;e+=V)O=A^a[e],D=(A>>>4|A<<28)^a[e+1],f=B,B=A,A=f^(g[O>>>24&63]|j[O>>>16&63]|q[O>>>8&63]|m[O&
-63]|h[D>>>24&63]|k[D>>>16&63]|l[D>>>8&63]|u[D&63]);f=B;B=A;A=f}B=B>>>1|B<<31;A=A>>>1|A<<31;f=(B>>>1^A)&1431655765;A^=f;B^=f<<1;f=(A>>>8^B)&16711935;B^=f;A^=f<<8;f=(A>>>2^B)&858993459;B^=f;A^=f<<2;f=(B>>>16^A)&65535;A^=f;B^=f<<16;f=(B>>>4^A)&252645135;A^=f;B^=f<<4;1==d&&(c?(ia=B,ha=A):(B^=aa,A^=K));tempresult+=String.fromCharCode(B>>>24,B>>>16&255,B>>>8&255,B&255,A>>>24,A>>>16&255,A>>>8&255,A&255);Z+=8;512==Z&&(result+=tempresult,tempresult="",Z=0)}result+=tempresult;return result=result.replace(/\0*$/g,
+131592,8,134348808,131584],j=[8396801,8321,8321,128,8396928,8388737,8388609,8193,0,8396800,8396800,8396929,129,0,8388736,8388609,1,8192,8388608,8396801,128,8388608,8193,8320,8388737,1,8320,8388736,8192,8396928,8396929,129,8388736,8388609,8396800,8396929,129,0,0,8396800,8320,8388736,8388737,1,8396801,8321,8321,128,8396929,129,1,8192,8388609,8193,8396928,8388737,8193,8320,8388608,8396801,128,8388608,8192,8396928],m=[256,34078976,34078720,1107296512,524288,256,1073741824,34078720,1074266368,524288,33554688,
+1074266368,1107296512,1107820544,524544,1073741824,33554432,1074266112,1074266112,0,1073742080,1107820800,1107820800,33554688,1107820544,1073742080,0,1107296256,34078976,33554432,1107296256,524544,524288,1107296512,256,33554432,1073741824,34078720,1107296512,1074266368,33554688,1073741824,1107820544,34078976,1074266368,256,33554432,1107820544,1107820800,524544,1107296256,1107820800,34078720,0,1074266112,1107296256,524544,33554688,1073742080,524288,0,1074266112,34078976,1073742080],u=[536870928,541065216,
+16384,541081616,541065216,16,541081616,4194304,536887296,4210704,4194304,536870928,4194320,536887296,536870912,16400,0,4194320,536887312,16384,4210688,536887312,16,541065232,541065232,0,4210704,541081600,16400,4210688,541081600,536870912,536887296,16,541065232,4210688,541081616,4194304,16400,536870928,4194304,536887296,536870912,16400,536870928,541081616,4210688,541065216,4210704,541081600,0,541065232,16,16384,541065216,4210704,16384,4194320,536887312,0,541081600,536870912,4194320,536887312],D=[2097152,
+69206018,67110914,0,2048,67110914,2099202,69208064,69208066,2097152,0,67108866,2,67108864,69206018,2050,67110912,2099202,2097154,67110912,67108866,69206016,69208064,2097154,69206016,2048,2050,69208066,2099200,2,67108864,2099200,67108864,2099200,2097152,67110914,67110914,69206018,69206018,2,2097154,67108864,67110912,2097152,69208064,2050,2099202,69208064,2050,67108866,69208066,69206016,2099200,0,2,69208066,0,2099202,69206016,2048,67108866,67110912,2048,2097154],l=[268439616,4096,262144,268701760,268435456,
+268439616,64,268435456,262208,268697600,268701760,266240,268701696,266304,4096,64,268697600,268435520,268439552,4160,266240,262208,268697664,268701696,4160,0,0,268697664,268435520,268439552,266304,262144,266304,262144,268701696,4096,64,268697664,4096,266304,268439552,64,268435520,268697600,268697664,268435456,262144,268439616,0,268701760,262208,268435520,268697600,268439552,268439616,0,268701760,266240,266240,4160,4160,262208,268435456,268701696],p=0,W,L,z,o,A,ka,na,fa,la,O,M,Z,qa=b.length,ea=0,ca=
+32==a.length?3:9;ka=3==ca?c?[0,32,2]:[30,-2,-2]:c?[0,32,2,62,30,-2,64,96,2]:[94,62,-2,32,64,2,30,-2,-2];2==f?b+="        ":1==f?(f=8-qa%8,b+=String.fromCharCode(f,f,f,f,f,f,f,f),8==f&&(qa+=8)):f||(b+="\x00\x00\x00\x00\x00\x00\x00\x00");tempresult=result="";1==d&&(na=e.charCodeAt(p++)<<24|e.charCodeAt(p++)<<16|e.charCodeAt(p++)<<8|e.charCodeAt(p++),la=e.charCodeAt(p++)<<24|e.charCodeAt(p++)<<16|e.charCodeAt(p++)<<8|e.charCodeAt(p++),p=0);for(;p<qa;){o=b.charCodeAt(p++)<<24|b.charCodeAt(p++)<<16|b.charCodeAt(p++)<<
+8|b.charCodeAt(p++);A=b.charCodeAt(p++)<<24|b.charCodeAt(p++)<<16|b.charCodeAt(p++)<<8|b.charCodeAt(p++);1==d&&(c?(o^=na,A^=la):(fa=na,O=la,na=o,la=A));f=(o>>>4^A)&252645135;A^=f;o^=f<<4;f=(o>>>16^A)&65535;A^=f;o^=f<<16;f=(A>>>2^o)&858993459;o^=f;A^=f<<2;f=(A>>>8^o)&16711935;o^=f;A^=f<<8;f=(o>>>1^A)&1431655765;A^=f;o^=f<<1;o=o<<1|o>>>31;A=A<<1|A>>>31;for(W=0;W<ca;W+=3){M=ka[W+1];Z=ka[W+2];for(e=ka[W];e!=M;e+=Z)L=A^a[e],z=(A>>>4|A<<28)^a[e+1],f=o,o=A,A=f^(h[L>>>24&63]|j[L>>>16&63]|u[L>>>8&63]|l[L&
+63]|g[z>>>24&63]|k[z>>>16&63]|m[z>>>8&63]|D[z&63]);f=o;o=A;A=f}o=o>>>1|o<<31;A=A>>>1|A<<31;f=(o>>>1^A)&1431655765;A^=f;o^=f<<1;f=(A>>>8^o)&16711935;o^=f;A^=f<<8;f=(A>>>2^o)&858993459;o^=f;A^=f<<2;f=(o>>>16^A)&65535;A^=f;o^=f<<16;f=(o>>>4^A)&252645135;A^=f;o^=f<<4;1==d&&(c?(na=o,la=A):(o^=fa,A^=O));tempresult+=String.fromCharCode(o>>>24,o>>>16&255,o>>>8&255,o&255,A>>>24,A>>>16&255,A>>>8&255,A&255);ea+=8;512==ea&&(result+=tempresult,tempresult="",ea=0)}result+=tempresult;return result=result.replace(/\0*$/g,
 "")}
 function des_createKeys(a){pc2bytes0=[0,4,536870912,536870916,65536,65540,536936448,536936452,512,516,536871424,536871428,66048,66052,536936960,536936964];pc2bytes1=[0,1,1048576,1048577,67108864,67108865,68157440,68157441,256,257,1048832,1048833,67109120,67109121,68157696,68157697];pc2bytes2=[0,8,2048,2056,16777216,16777224,16779264,16779272,0,8,2048,2056,16777216,16777224,16779264,16779272];pc2bytes3=[0,2097152,134217728,136314880,8192,2105344,134225920,136323072,131072,2228224,134348800,136445952,139264,
 2236416,134356992,136454144];pc2bytes4=[0,262144,16,262160,0,262144,16,262160,4096,266240,4112,266256,4096,266240,4112,266256];pc2bytes5=[0,1024,32,1056,0,1024,32,1056,33554432,33555456,33554464,33555488,33554432,33555456,33554464,33555488];pc2bytes6=[0,268435456,524288,268959744,2,268435458,524290,268959746,0,268435456,524288,268959744,2,268435458,524290,268959746];pc2bytes7=[0,65536,2048,67584,536870912,536936448,536872960,536938496,131072,196608,133120,198656,537001984,537067520,537004032,537069568];
 pc2bytes8=[0,262144,0,262144,2,262146,2,262146,33554432,33816576,33554432,33816576,33554434,33816578,33554434,33816578];pc2bytes9=[0,268435456,8,268435464,0,268435456,8,268435464,1024,268436480,1032,268436488,1024,268436480,1032,268436488];pc2bytes10=[0,32,0,32,1048576,1048608,1048576,1048608,8192,8224,8192,8224,1056768,1056800,1056768,1056800];pc2bytes11=[0,16777216,512,16777728,2097152,18874368,2097664,18874880,67108864,83886080,67109376,83886592,69206016,85983232,69206528,85983744];pc2bytes12=
-[0,4096,134217728,134221824,524288,528384,134742016,134746112,16,4112,134217744,134221840,524304,528400,134742032,134746128];pc2bytes13=[0,4,256,260,0,4,256,260,1,5,257,261,1,5,257,261];for(var b=8<a.length?3:1,c=Array(32*b),d=[0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0],e,f,h=0,g=0,k,j=0;j<b;j++){left=a.charCodeAt(h++)<<24|a.charCodeAt(h++)<<16|a.charCodeAt(h++)<<8|a.charCodeAt(h++);right=a.charCodeAt(h++)<<24|a.charCodeAt(h++)<<16|a.charCodeAt(h++)<<8|a.charCodeAt(h++);k=(left>>>4^right)&252645135;right^=
+[0,4096,134217728,134221824,524288,528384,134742016,134746112,16,4112,134217744,134221840,524304,528400,134742032,134746128];pc2bytes13=[0,4,256,260,0,4,256,260,1,5,257,261,1,5,257,261];for(var b=8<a.length?3:1,c=Array(32*b),d=[0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0],e,f,g=0,h=0,k,j=0;j<b;j++){left=a.charCodeAt(g++)<<24|a.charCodeAt(g++)<<16|a.charCodeAt(g++)<<8|a.charCodeAt(g++);right=a.charCodeAt(g++)<<24|a.charCodeAt(g++)<<16|a.charCodeAt(g++)<<8|a.charCodeAt(g++);k=(left>>>4^right)&252645135;right^=
 k;left^=k<<4;k=(right>>>-16^left)&65535;left^=k;right^=k<<-16;k=(left>>>2^right)&858993459;right^=k;left^=k<<2;k=(right>>>-16^left)&65535;left^=k;right^=k<<-16;k=(left>>>1^right)&1431655765;right^=k;left^=k<<1;k=(right>>>8^left)&16711935;left^=k;right^=k<<8;k=(left>>>1^right)&1431655765;right^=k;left^=k<<1;k=left<<8|right>>>20&240;left=right<<24|right<<8&16711680|right>>>8&65280|right>>>24&240;right=k;for(i=0;i<d.length;i++)d[i]?(left=left<<2|left>>>26,right=right<<2|right>>>26):(left=left<<1|left>>>
-27,right=right<<1|right>>>27),left&=-15,right&=-15,e=pc2bytes0[left>>>28]|pc2bytes1[left>>>24&15]|pc2bytes2[left>>>20&15]|pc2bytes3[left>>>16&15]|pc2bytes4[left>>>12&15]|pc2bytes5[left>>>8&15]|pc2bytes6[left>>>4&15],f=pc2bytes7[right>>>28]|pc2bytes8[right>>>24&15]|pc2bytes9[right>>>20&15]|pc2bytes10[right>>>16&15]|pc2bytes11[right>>>12&15]|pc2bytes12[right>>>8&15]|pc2bytes13[right>>>4&15],k=(f>>>16^e)&65535,c[g++]=e^k,c[g++]=f^k<<16}return c}
+27,right=right<<1|right>>>27),left&=-15,right&=-15,e=pc2bytes0[left>>>28]|pc2bytes1[left>>>24&15]|pc2bytes2[left>>>20&15]|pc2bytes3[left>>>16&15]|pc2bytes4[left>>>12&15]|pc2bytes5[left>>>8&15]|pc2bytes6[left>>>4&15],f=pc2bytes7[right>>>28]|pc2bytes8[right>>>24&15]|pc2bytes9[right>>>20&15]|pc2bytes10[right>>>16&15]|pc2bytes11[right>>>12&15]|pc2bytes12[right>>>8&15]|pc2bytes13[right>>>4&15],k=(f>>>16^e)&65535,c[h++]=e^k,c[h++]=f^k<<16}return c}
 function cast5_encrypt(a,b){var c=new openpgp_symenc_cast5;c.setKey(util.str2bin(b));return c.encrypt(a)}
-function openpgp_symenc_cast5(){function a(b,a,c){b=a+b;c=b<<c|b>>>32-c;return(f[0][c>>>24]^f[1][c>>>16&255])-f[2][c>>>8&255]+f[3][c&255]}function b(b,a,c){b^=a;c=b<<c|b>>>32-c;return f[0][c>>>24]-f[1][c>>>16&255]+f[2][c>>>8&255]^f[3][c&255]}function c(b,a,c){b=a-b;c=b<<c|b>>>32-c;return(f[0][c>>>24]+f[1][c>>>16&255]^f[2][c>>>8&255])-f[3][c&255]}this.BlockSize=8;this.KeySize=16;this.setKey=function(b){this.masking=Array(16);this.rotate=Array(16);this.reset();if(b.length==this.KeySize)this.keySchedule(b);
-else return util.print_error("cast5.js: CAST-128: keys must be 16 bytes"),!1;return!0};this.reset=function(){for(var b=0;16>b;b++)this.masking[b]=0,this.rotate[b]=0};this.getBlockSize=function(){return BlockSize};this.encrypt=function(d){var e=Array(d.length);for(i=0;i<d.length;i+=8){var f=d[i]<<24|d[i+1]<<16|d[i+2]<<8|d[i+3],j=d[i+4]<<24|d[i+5]<<16|d[i+6]<<8|d[i+7],l;l=j;j=f^a(j,this.masking[0],this.rotate[0]);f=l;l=j;j=f^b(j,this.masking[1],this.rotate[1]);f=l;l=j;j=f^c(j,this.masking[2],this.rotate[2]);
-f=l;l=j;j=f^a(j,this.masking[3],this.rotate[3]);f=l;l=j;j=f^b(j,this.masking[4],this.rotate[4]);f=l;l=j;j=f^c(j,this.masking[5],this.rotate[5]);f=l;l=j;j=f^a(j,this.masking[6],this.rotate[6]);f=l;l=j;j=f^b(j,this.masking[7],this.rotate[7]);f=l;l=j;j=f^c(j,this.masking[8],this.rotate[8]);f=l;l=j;j=f^a(j,this.masking[9],this.rotate[9]);f=l;l=j;j=f^b(j,this.masking[10],this.rotate[10]);f=l;l=j;j=f^c(j,this.masking[11],this.rotate[11]);f=l;l=j;j=f^a(j,this.masking[12],this.rotate[12]);f=l;l=j;j=f^b(j,
-this.masking[13],this.rotate[13]);f=l;l=j;j=f^c(j,this.masking[14],this.rotate[14]);f=l;l=j;j=f^a(j,this.masking[15],this.rotate[15]);f=l;e[i]=j>>>24&255;e[i+1]=j>>>16&255;e[i+2]=j>>>8&255;e[i+3]=j&255;e[i+4]=f>>>24&255;e[i+5]=f>>>16&255;e[i+6]=f>>>8&255;e[i+7]=f&255}return e};this.decrypt=function(d){var e=Array(d.length);for(i=0;i<d.length;i+=8){var f=d[i]<<24|d[i+1]<<16|d[i+2]<<8|d[i+3],j=d[i+4]<<24|d[i+5]<<16|d[i+6]<<8|d[i+7],l;l=j;j=f^a(j,this.masking[15],this.rotate[15]);f=l;l=j;j=f^c(j,this.masking[14],
-this.rotate[14]);f=l;l=j;j=f^b(j,this.masking[13],this.rotate[13]);f=l;l=j;j=f^a(j,this.masking[12],this.rotate[12]);f=l;l=j;j=f^c(j,this.masking[11],this.rotate[11]);f=l;l=j;j=f^b(j,this.masking[10],this.rotate[10]);f=l;l=j;j=f^a(j,this.masking[9],this.rotate[9]);f=l;l=j;j=f^c(j,this.masking[8],this.rotate[8]);f=l;l=j;j=f^b(j,this.masking[7],this.rotate[7]);f=l;l=j;j=f^a(j,this.masking[6],this.rotate[6]);f=l;l=j;j=f^c(j,this.masking[5],this.rotate[5]);f=l;l=j;j=f^b(j,this.masking[4],this.rotate[4]);
-f=l;l=j;j=f^a(j,this.masking[3],this.rotate[3]);f=l;l=j;j=f^c(j,this.masking[2],this.rotate[2]);f=l;l=j;j=f^b(j,this.masking[1],this.rotate[1]);f=l;l=j;j=f^a(j,this.masking[0],this.rotate[0]);f=l;e[i]=j>>>24&255;e[i+1]=j>>>16&255;e[i+2]=j>>>8&255;e[i+3]=j&255;e[i+4]=f>>>24&255;e[i+5]=f>>16&255;e[i+6]=f>>8&255;e[i+7]=f&255}return e};var d=Array(4);d[0]=Array(4);d[0][0]=[4,0,13,15,12,14,8];d[0][1]=[5,2,16,18,17,19,10];d[0][2]=[6,3,23,22,21,20,9];d[0][3]=[7,1,26,25,27,24,11];d[1]=Array(4);d[1][0]=[0,
+function openpgp_symenc_cast5(){function a(a,b,c){a=b+a;c=a<<c|a>>>32-c;return(f[0][c>>>24]^f[1][c>>>16&255])-f[2][c>>>8&255]+f[3][c&255]}function b(a,b,c){a^=b;c=a<<c|a>>>32-c;return f[0][c>>>24]-f[1][c>>>16&255]+f[2][c>>>8&255]^f[3][c&255]}function c(a,b,c){a=b-a;c=a<<c|a>>>32-c;return(f[0][c>>>24]+f[1][c>>>16&255]^f[2][c>>>8&255])-f[3][c&255]}this.BlockSize=8;this.KeySize=16;this.setKey=function(a){this.masking=Array(16);this.rotate=Array(16);this.reset();if(a.length==this.KeySize)this.keySchedule(a);
+else return util.print_error("cast5.js: CAST-128: keys must be 16 bytes"),!1;return!0};this.reset=function(){for(var a=0;16>a;a++)this.masking[a]=0,this.rotate[a]=0};this.getBlockSize=function(){return BlockSize};this.encrypt=function(d){var e=Array(d.length);for(i=0;i<d.length;i+=8){var f=d[i]<<24|d[i+1]<<16|d[i+2]<<8|d[i+3],j=d[i+4]<<24|d[i+5]<<16|d[i+6]<<8|d[i+7],m;m=j;j=f^a(j,this.masking[0],this.rotate[0]);f=m;m=j;j=f^b(j,this.masking[1],this.rotate[1]);f=m;m=j;j=f^c(j,this.masking[2],this.rotate[2]);
+f=m;m=j;j=f^a(j,this.masking[3],this.rotate[3]);f=m;m=j;j=f^b(j,this.masking[4],this.rotate[4]);f=m;m=j;j=f^c(j,this.masking[5],this.rotate[5]);f=m;m=j;j=f^a(j,this.masking[6],this.rotate[6]);f=m;m=j;j=f^b(j,this.masking[7],this.rotate[7]);f=m;m=j;j=f^c(j,this.masking[8],this.rotate[8]);f=m;m=j;j=f^a(j,this.masking[9],this.rotate[9]);f=m;m=j;j=f^b(j,this.masking[10],this.rotate[10]);f=m;m=j;j=f^c(j,this.masking[11],this.rotate[11]);f=m;m=j;j=f^a(j,this.masking[12],this.rotate[12]);f=m;m=j;j=f^b(j,
+this.masking[13],this.rotate[13]);f=m;m=j;j=f^c(j,this.masking[14],this.rotate[14]);f=m;m=j;j=f^a(j,this.masking[15],this.rotate[15]);f=m;e[i]=j>>>24&255;e[i+1]=j>>>16&255;e[i+2]=j>>>8&255;e[i+3]=j&255;e[i+4]=f>>>24&255;e[i+5]=f>>>16&255;e[i+6]=f>>>8&255;e[i+7]=f&255}return e};this.decrypt=function(d){var e=Array(d.length);for(i=0;i<d.length;i+=8){var f=d[i]<<24|d[i+1]<<16|d[i+2]<<8|d[i+3],j=d[i+4]<<24|d[i+5]<<16|d[i+6]<<8|d[i+7],m;m=j;j=f^a(j,this.masking[15],this.rotate[15]);f=m;m=j;j=f^c(j,this.masking[14],
+this.rotate[14]);f=m;m=j;j=f^b(j,this.masking[13],this.rotate[13]);f=m;m=j;j=f^a(j,this.masking[12],this.rotate[12]);f=m;m=j;j=f^c(j,this.masking[11],this.rotate[11]);f=m;m=j;j=f^b(j,this.masking[10],this.rotate[10]);f=m;m=j;j=f^a(j,this.masking[9],this.rotate[9]);f=m;m=j;j=f^c(j,this.masking[8],this.rotate[8]);f=m;m=j;j=f^b(j,this.masking[7],this.rotate[7]);f=m;m=j;j=f^a(j,this.masking[6],this.rotate[6]);f=m;m=j;j=f^c(j,this.masking[5],this.rotate[5]);f=m;m=j;j=f^b(j,this.masking[4],this.rotate[4]);
+f=m;m=j;j=f^a(j,this.masking[3],this.rotate[3]);f=m;m=j;j=f^c(j,this.masking[2],this.rotate[2]);f=m;m=j;j=f^b(j,this.masking[1],this.rotate[1]);f=m;m=j;j=f^a(j,this.masking[0],this.rotate[0]);f=m;e[i]=j>>>24&255;e[i+1]=j>>>16&255;e[i+2]=j>>>8&255;e[i+3]=j&255;e[i+4]=f>>>24&255;e[i+5]=f>>16&255;e[i+6]=f>>8&255;e[i+7]=f&255}return e};var d=Array(4);d[0]=Array(4);d[0][0]=[4,0,13,15,12,14,8];d[0][1]=[5,2,16,18,17,19,10];d[0][2]=[6,3,23,22,21,20,9];d[0][3]=[7,1,26,25,27,24,11];d[1]=Array(4);d[1][0]=[0,
 6,21,23,20,22,16];d[1][1]=[1,4,0,2,1,3,18];d[1][2]=[2,5,7,6,5,4,17];d[1][3]=[3,7,10,9,11,8,19];d[2]=Array(4);d[2][0]=[4,0,13,15,12,14,8];d[2][1]=[5,2,16,18,17,19,10];d[2][2]=[6,3,23,22,21,20,9];d[2][3]=[7,1,26,25,27,24,11];d[3]=Array(4);d[3][0]=[0,6,21,23,20,22,16];d[3][1]=[1,4,0,2,1,3,18];d[3][2]=[2,5,7,6,5,4,17];d[3][3]=[3,7,10,9,11,8,19];var e=Array(4);e[0]=Array(4);e[0][0]=[24,25,23,22,18];e[0][1]=[26,27,21,20,22];e[0][2]=[28,29,19,18,25];e[0][3]=[30,31,17,16,28];e[1]=Array(4);e[1][0]=[3,2,12,
-13,8];e[1][1]=[1,0,14,15,13];e[1][2]=[7,6,8,9,3];e[1][3]=[5,4,10,11,7];e[2]=Array(4);e[2][0]=[19,18,28,29,25];e[2][1]=[17,16,30,31,28];e[2][2]=[23,22,24,25,18];e[2][3]=[21,20,26,27,22];e[3]=Array(4);e[3][0]=[8,9,7,6,3];e[3][1]=[10,11,5,4,7];e[3][2]=[12,13,3,2,8];e[3][3]=[14,15,1,0,13];this.keySchedule=function(b){for(var a=Array(8),c=Array(32),j=0;4>j;j++){var l=4*j;a[j]=b[l]<<24|b[l+1]<<16|b[l+2]<<8|b[l+3]}for(var b=[6,7,4,5],q=j=0;2>q;q++)for(var u=0;4>u;u++){for(l=0;4>l;l++){var m=d[u][l],o=a[m[1]],
-o=o^f[4][a[m[2]>>>2]>>>24-8*(m[2]&3)&255],o=o^f[5][a[m[3]>>>2]>>>24-8*(m[3]&3)&255],o=o^f[6][a[m[4]>>>2]>>>24-8*(m[4]&3)&255],o=o^f[7][a[m[5]>>>2]>>>24-8*(m[5]&3)&255],o=o^f[b[l]][a[m[6]>>>2]>>>24-8*(m[6]&3)&255];a[m[0]]=o}for(l=0;4>l;l++)m=e[u][l],o=f[4][a[m[0]>>>2]>>>24-8*(m[0]&3)&255],o^=f[5][a[m[1]>>>2]>>>24-8*(m[1]&3)&255],o^=f[6][a[m[2]>>>2]>>>24-8*(m[2]&3)&255],o^=f[7][a[m[3]>>>2]>>>24-8*(m[3]&3)&255],o^=f[4+l][a[m[4]>>>2]>>>24-8*(m[4]&3)&255],c[j]=o,j++}for(j=0;16>j;j++)this.masking[j]=c[j],
+13,8];e[1][1]=[1,0,14,15,13];e[1][2]=[7,6,8,9,3];e[1][3]=[5,4,10,11,7];e[2]=Array(4);e[2][0]=[19,18,28,29,25];e[2][1]=[17,16,30,31,28];e[2][2]=[23,22,24,25,18];e[2][3]=[21,20,26,27,22];e[3]=Array(4);e[3][0]=[8,9,7,6,3];e[3][1]=[10,11,5,4,7];e[3][2]=[12,13,3,2,8];e[3][3]=[14,15,1,0,13];this.keySchedule=function(a){for(var b=Array(8),c=Array(32),j=0;4>j;j++){var m=4*j;b[j]=a[m]<<24|a[m+1]<<16|a[m+2]<<8|a[m+3]}for(var a=[6,7,4,5],u=j=0;2>u;u++)for(var D=0;4>D;D++){for(m=0;4>m;m++){var l=d[D][m],p=b[l[1]],
+p=p^f[4][b[l[2]>>>2]>>>24-8*(l[2]&3)&255],p=p^f[5][b[l[3]>>>2]>>>24-8*(l[3]&3)&255],p=p^f[6][b[l[4]>>>2]>>>24-8*(l[4]&3)&255],p=p^f[7][b[l[5]>>>2]>>>24-8*(l[5]&3)&255],p=p^f[a[m]][b[l[6]>>>2]>>>24-8*(l[6]&3)&255];b[l[0]]=p}for(m=0;4>m;m++)l=e[D][m],p=f[4][b[l[0]>>>2]>>>24-8*(l[0]&3)&255],p^=f[5][b[l[1]>>>2]>>>24-8*(l[1]&3)&255],p^=f[6][b[l[2]>>>2]>>>24-8*(l[2]&3)&255],p^=f[7][b[l[3]>>>2]>>>24-8*(l[3]&3)&255],p^=f[4+m][b[l[4]>>>2]>>>24-8*(l[4]&3)&255],c[j]=p,j++}for(j=0;16>j;j++)this.masking[j]=c[j],
 this.rotate[j]=c[16+j]&31};var f=Array(8);f[0]=[821772500,2678128395,1810681135,1059425402,505495343,2617265619,1610868032,3483355465,3218386727,2294005173,3791863952,2563806837,1852023008,365126098,3269944861,584384398,677919599,3229601881,4280515016,2002735330,1136869587,3744433750,2289869850,2731719981,2714362070,879511577,1639411079,575934255,717107937,2857637483,576097850,2731753936,1725645E3,2810460463,5111599,767152862,2543075244,1251459544,1383482551,3052681127,3089939183,3612463449,1878520045,
 1510570527,2189125840,2431448366,582008916,3163445557,1265446783,1354458274,3529918736,3202711853,3073581712,3912963487,3029263377,1275016285,4249207360,2905708351,3304509486,1442611557,3585198765,2712415662,2731849581,3248163920,2283946226,208555832,2766454743,1331405426,1447828783,3315356441,3108627284,2957404670,2981538698,3339933917,1669711173,286233437,1465092821,1782121619,3862771680,710211251,980974943,1651941557,430374111,2051154026,704238805,4128970897,3144820574,2857402727,948965521,3333752299,
 2227686284,718756367,2269778983,2731643755,718440111,2857816721,3616097120,1113355533,2478022182,410092745,1811985197,1944238868,2696854588,1415722873,1682284203,1060277122,1998114690,1503841958,82706478,2315155686,1068173648,845149890,2167947013,1768146376,1993038550,3566826697,3390574031,940016341,3355073782,2328040721,904371731,1205506512,4094660742,2816623006,825647681,85914773,2857843460,1249926541,1417871568,3287612,3211054559,3126306446,1975924523,1353700161,2814456437,2438597621,1800716203,
@@ -245,7 +357,43 @@ f[2]=[2381300288,637164959,3952098751,3893414151,1197506559,916448331,2350892612
 163866573,3246985393,3776823163,114105080,1903216136,761148244,3571337562,1690750982,3166750252,1037045171,1888456500,2010454850,642736655,616092351,365016990,1185228132,4174898510,1043824992,2023083429,2241598885,3863320456,3279669087,3674716684,108438443,2132974366,830746235,606445527,4173263986,2204105912,1844756978,2532684181,4245352700,2969441100,3796921661,1335562986,4061524517,2720232303,2679424040,634407289,885462008,3294724487,3933892248,2094100220,339117932,4048830727,3202280980,1458155303,
 2689246273,1022871705,2464987878,3714515309,353796843,2822958815,4256850100,4052777845,551748367,618185374,3778635579,4020649912,1904685140,3069366075,2670879810,3407193292,2954511620,4058283405,2219449317,3135758300,1120655984,3447565834,1474845562,3577699062,550456716,3466908712,2043752612,881257467,869518812,2005220179,938474677,3305539448,3850417126,1315485940,3318264702,226533026,965733244,321539988,1136104718,804158748,573969341,3708209826,937399083,3290727049,2901666755,1461057207,4013193437,
 4066861423,3242773476,2421326174,1581322155,3028952165,786071460,3900391652,3918438532,1485433313,4023619836,3708277595,3678951060,953673138,1467089153,1930354364,1533292819,2492563023,1346121658,1685000834,1965281866,3765933717,4190206607,2052792609,3515332758,690371149,3125873887,2180283551,2903598061,3933952357,436236910,289419410,14314871,1242357089,2904507907,1616633776,2666382180,585885352,3471299210,2699507360,1432659641,277164553,3354103607,770115018,2303809295,3741942315,3177781868,2853364978,
-2269453327,3774259834,987383833,1290892879,225909803,1741533526,890078084,1496906255,1111072499,916028167,243534141,1252605537,2204162171,531204876,290011180,3916834213,102027703,237315147,209093447,1486785922,220223953,2758195998,4175039106,82940208,3127791296,2569425252,518464269,1353887104,3941492737,2377294467,3935040926]}
+2269453327,3774259834,987383833,1290892879,225909803,1741533526,890078084,1496906255,1111072499,916028167,243534141,1252605537,2204162171,531204876,290011180,3916834213,102027703,237315147,209093447,1486785922,220223953,2758195998,4175039106,82940208,3127791296,2569425252,518464269,1353887104,3941492737,2377294467,3935040926]}function TFencrypt(a,b){var c=[].concat(a),d=createTwofish();d.open(util.str2bin(b),0);c=d.encrypt(c,0);d.close();return c}var MAXINT=4294967295;
+function rotb(a,b){return(a<<b|a>>>8-b)&255}function rotw(a,b){return(a<<b|a>>>32-b)&MAXINT}function getW(a,b){return a[b]|a[b+1]<<8|a[b+2]<<16|a[b+3]<<24}function setW(a,b,c){a.splice(b,4,c&255,c>>>8&255,c>>>16&255,c>>>24&255)}function setWInv(a,b,c){a.splice(b,4,c>>>24&255,c>>>16&255,c>>>8&255,c&255)}function getB(a,b){return a>>>8*b&255}function getNrBits(a){for(var b=0;0<a;)b++,a>>>=1;return b}function getMask(a){return(1<<a)-1}function randByte(){return Math.floor(256*Math.random())}
+function createTwofish(){function a(a){return g[0][getB(a,0)]^g[1][getB(a,1)]^g[2][getB(a,2)]^g[3][getB(a,3)]}function b(a){return g[0][getB(a,3)]^g[1][getB(a,0)]^g[2][getB(a,1)]^g[3][getB(a,2)]}var c=null,d=null,e=-1,f=[],g=[[],[],[],[]];return{name:"twofish",blocksize:16,open:function(a){function b(a,c){var d,e,f;for(d=0;8>d;d++)e=c>>>24,c=c<<8&MAXINT|a>>>24,a=a<<8&MAXINT,f=e<<1,e&128&&(f^=333),c^=e^f<<16,f^=e>>>1,e&1&&(f^=166),c^=f<<24|f<<8;return c}function d(a,b){var c,e,f;c=b>>4;e=b&15;f=A[a][c^
+e];c=ka[a][la[e]^O[c]];return fa[a][la[c]^O[f]]<<4|na[a][f^c]}function e(a,b){var c=getB(a,0),d=getB(a,1),f=getB(a,2),g=getB(a,3);switch(L){case 4:c=M[1][c]^getB(b[3],0),d=M[0][d]^getB(b[3],1),f=M[0][f]^getB(b[3],2),g=M[1][g]^getB(b[3],3);case 3:c=M[1][c]^getB(b[2],0),d=M[1][d]^getB(b[2],1),f=M[0][f]^getB(b[2],2),g=M[0][g]^getB(b[2],3);case 2:c=M[0][M[0][c]^getB(b[1],0)]^getB(b[0],0),d=M[0][M[1][d]^getB(b[1],1)]^getB(b[0],1),f=M[1][M[0][f]^getB(b[1],2)]^getB(b[0],2),g=M[1][M[1][g]^getB(b[1],3)]^getB(b[0],
+3)}return Z[0][c]^Z[1][d]^Z[2][f]^Z[3][g]}c=a;var u,D,l,p;l=[];p=[];var W=[],L,z=[],o,A=[[8,1,7,13,6,15,3,2,0,11,5,9,14,12,10,4],[2,8,11,13,15,7,6,14,3,1,9,4,0,10,12,5]],ka=[[14,12,11,8,1,2,3,5,15,4,10,6,7,0,9,13],[1,14,2,11,4,12,3,7,6,13,10,5,15,9,0,8]],na=[[11,10,5,14,6,13,9,0,12,8,15,3,2,4,7,1],[4,12,7,5,1,6,9,10,0,14,13,8,2,11,3,15]],fa=[[13,7,15,4,1,2,6,14,9,11,3,0,8,5,12,10],[11,9,5,1,12,3,13,14,6,4,7,15,2,0,8,10]],la=[0,8,1,9,2,10,3,11,4,12,5,13,6,14,7,15],O=[0,9,2,11,4,13,6,15,8,1,10,3,12,
+5,14,7],M=[[],[]],Z=[[],[],[],[]];c=c.slice(0,32);for(a=c.length;16!=a&&24!=a&&32!=a;)c[a++]=0;for(a=0;a<c.length;a+=4)W[a>>2]=getW(c,a);for(a=0;256>a;a++)M[0][a]=d(0,a),M[1][a]=d(1,a);for(a=0;256>a;a++)u=M[1][a],D=u^u>>2^[0,90,180,238][u&3],o=u^u>>1^u>>2^[0,238,180,90][u&3],Z[0][a]=u+(D<<8)+(o<<16)+(o<<24),Z[2][a]=D+(o<<8)+(u<<16)+(o<<24),u=M[0][a],D=u^u>>2^[0,90,180,238][u&3],o=u^u>>1^u>>2^[0,238,180,90][u&3],Z[1][a]=o+(o<<8)+(D<<16)+(u<<24),Z[3][a]=D+(u<<8)+(o<<16)+(D<<24);L=W.length/2;for(a=0;a<
+L;a++)u=W[a+a],l[a]=u,D=W[a+a+1],p[a]=D,z[L-a-1]=b(u,D);for(a=0;40>a;a+=2)u=16843009*a,D=u+16843009,u=e(u,l),D=rotw(e(D,p),8),f[a]=u+D&MAXINT,f[a+1]=rotw(u+2*D,9);for(a=0;256>a;a++)switch(u=D=l=p=a,L){case 4:u=M[1][u]^getB(z[3],0),D=M[0][D]^getB(z[3],1),l=M[0][l]^getB(z[3],2),p=M[1][p]^getB(z[3],3);case 3:u=M[1][u]^getB(z[2],0),D=M[1][D]^getB(z[2],1),l=M[0][l]^getB(z[2],2),p=M[0][p]^getB(z[2],3);case 2:g[0][a]=Z[0][M[0][M[0][u]^getB(z[1],0)]^getB(z[0],0)],g[1][a]=Z[1][M[0][M[1][D]^getB(z[1],1)]^getB(z[0],
+1)],g[2][a]=Z[2][M[1][M[0][l]^getB(z[1],2)]^getB(z[0],2)],g[3][a]=Z[3][M[1][M[1][p]^getB(z[1],3)]^getB(z[0],3)]}},close:function(){f=[];g=[[],[],[],[]]},encrypt:function(c,g){d=c;e=g;for(var j=[getW(d,e)^f[0],getW(d,e+4)^f[1],getW(d,e+8)^f[2],getW(d,e+12)^f[3]],m=0;8>m;m++){var u=m,D=j,l=a(D[0]),p=b(D[1]);D[2]=rotw(D[2]^l+p+f[4*u+8]&MAXINT,31);D[3]=rotw(D[3],1)^l+2*p+f[4*u+9]&MAXINT;l=a(D[2]);p=b(D[3]);D[0]=rotw(D[0]^l+p+f[4*u+10]&MAXINT,31);D[1]=rotw(D[1],1)^l+2*p+f[4*u+11]&MAXINT}setW(d,e,j[2]^
+f[4]);setW(d,e+4,j[3]^f[5]);setW(d,e+8,j[0]^f[6]);setW(d,e+12,j[1]^f[7]);e+=16;return d},decrypt:function(c,g){d=c;e=g;for(var j=[getW(d,e)^f[4],getW(d,e+4)^f[5],getW(d,e+8)^f[6],getW(d,e+12)^f[7]],m=7;0<=m;m--){var u=m,D=j,l=a(D[0]),p=b(D[1]);D[2]=rotw(D[2],1)^l+p+f[4*u+10]&MAXINT;D[3]=rotw(D[3]^l+2*p+f[4*u+11]&MAXINT,31);l=a(D[2]);p=b(D[3]);D[0]=rotw(D[0],1)^l+p+f[4*u+8]&MAXINT;D[1]=rotw(D[1]^l+2*p+f[4*u+9]&MAXINT,31)}setW(d,e,j[2]^f[0]);setW(d,e+4,j[3]^f[1]);setW(d,e+8,j[0]^f[2]);setW(d,e+12,j[1]^
+f[3]);e+=16},finalize:function(){return d}}}function Blowfish(){}Blowfish.prototype.BLOCKSIZE=8;
+Blowfish.prototype.SBOXES=[[3509652390,2564797868,805139163,3491422135,3101798381,1780907670,3128725573,4046225305,614570311,3012652279,134345442,2240740374,1667834072,1901547113,2757295779,4103290238,227898511,1921955416,1904987480,2182433518,2069144605,3260701109,2620446009,720527379,3318853667,677414384,3393288472,3101374703,2390351024,1614419982,1822297739,2954791486,3608508353,3174124327,2024746970,1432378464,3864339955,2857741204,1464375394,1676153920,1439316330,715854006,3033291828,289532110,
+2706671279,2087905683,3018724369,1668267050,732546397,1947742710,3462151702,2609353502,2950085171,1814351708,2050118529,680887927,999245976,1800124847,3300911131,1713906067,1641548236,4213287313,1216130144,1575780402,4018429277,3917837745,3693486850,3949271944,596196993,3549867205,258830323,2213823033,772490370,2760122372,1774776394,2652871518,566650946,4142492826,1728879713,2882767088,1783734482,3629395816,2517608232,2874225571,1861159788,326777828,3124490320,2130389656,2716951837,967770486,1724537150,
+2185432712,2364442137,1164943284,2105845187,998989502,3765401048,2244026483,1075463327,1455516326,1322494562,910128902,469688178,1117454909,936433444,3490320968,3675253459,1240580251,122909385,2157517691,634681816,4142456567,3825094682,3061402683,2540495037,79693498,3249098678,1084186820,1583128258,426386531,1761308591,1047286709,322548459,995290223,1845252383,2603652396,3431023940,2942221577,3202600964,3727903485,1712269319,422464435,3234572375,1170764815,3523960633,3117677531,1434042557,442511882,
+3600875718,1076654713,1738483198,4213154764,2393238008,3677496056,1014306527,4251020053,793779912,2902807211,842905082,4246964064,1395751752,1040244610,2656851899,3396308128,445077038,3742853595,3577915638,679411651,2892444358,2354009459,1767581616,3150600392,3791627101,3102740896,284835224,4246832056,1258075500,768725851,2589189241,3069724005,3532540348,1274779536,3789419226,2764799539,1660621633,3471099624,4011903706,913787905,3497959166,737222580,2514213453,2928710040,3937242737,1804850592,3499020752,
+2949064160,2386320175,2390070455,2415321851,4061277028,2290661394,2416832540,1336762016,1754252060,3520065937,3014181293,791618072,3188594551,3933548030,2332172193,3852520463,3043980520,413987798,3465142937,3030929376,4245938359,2093235073,3534596313,375366246,2157278981,2479649556,555357303,3870105701,2008414854,3344188149,4221384143,3956125452,2067696032,3594591187,2921233993,2428461,544322398,577241275,1471733935,610547355,4027169054,1432588573,1507829418,2025931657,3646575487,545086370,48609733,
+2200306550,1653985193,298326376,1316178497,3007786442,2064951626,458293330,2589141269,3591329599,3164325604,727753846,2179363840,146436021,1461446943,4069977195,705550613,3059967265,3887724982,4281599278,3313849956,1404054877,2845806497,146425753,1854211946],[1266315497,3048417604,3681880366,3289982499,290971E4,1235738493,2632868024,2414719590,3970600049,1771706367,1449415276,3266420449,422970021,1963543593,2690192192,3826793022,1062508698,1531092325,1804592342,2583117782,2714934279,4024971509,1294809318,
+4028980673,1289560198,2221992742,1669523910,35572830,157838143,1052438473,1016535060,1802137761,1753167236,1386275462,3080475397,2857371447,1040679964,2145300060,2390574316,1461121720,2956646967,4031777805,4028374788,33600511,2920084762,1018524850,629373528,3691585981,3515945977,2091462646,2486323059,586499841,988145025,935516892,3367335476,2599673255,2839830854,265290510,3972581182,2759138881,3795373465,1005194799,847297441,406762289,1314163512,1332590856,1866599683,4127851711,750260880,613907577,
+1450815602,3165620655,3734664991,3650291728,3012275730,3704569646,1427272223,778793252,1343938022,2676280711,2052605720,1946737175,3164576444,3914038668,3967478842,3682934266,1661551462,3294938066,4011595847,840292616,3712170807,616741398,312560963,711312465,1351876610,322626781,1910503582,271666773,2175563734,1594956187,70604529,3617834859,1007753275,1495573769,4069517037,2549218298,2663038764,504708206,2263041392,3941167025,2249088522,1514023603,1998579484,1312622330,694541497,2582060303,2151582166,
+1382467621,776784248,2618340202,3323268794,2497899128,2784771155,503983604,4076293799,907881277,423175695,432175456,1378068232,4145222326,3954048622,3938656102,3820766613,2793130115,2977904593,26017576,3274890735,3194772133,1700274565,1756076034,4006520079,3677328699,720338349,1533947780,354530856,688349552,3973924725,1637815568,332179504,3949051286,53804574,2852348879,3044236432,1282449977,3583942155,3416972820,4006381244,1617046695,2628476075,3002303598,1686838959,431878346,2686675385,1700445008,
+1080580658,1009431731,832498133,3223435511,2605976345,2271191193,2516031870,1648197032,4164389018,2548247927,300782431,375919233,238389289,3353747414,2531188641,2019080857,1475708069,455242339,2609103871,448939670,3451063019,1395535956,2413381860,1841049896,1491858159,885456874,4264095073,4001119347,1565136089,3898914787,1108368660,540939232,1173283510,2745871338,3681308437,4207628240,3343053890,4016749493,1699691293,1103962373,3625875870,2256883143,3830138730,1031889488,3479347698,1535977030,4236805024,
+3251091107,2132092099,1774941330,1199868427,1452454533,157007616,2904115357,342012276,595725824,1480756522,206960106,497939518,591360097,863170706,2375253569,3596610801,1814182875,2094937945,3421402208,1082520231,3463918190,2785509508,435703966,3908032597,1641649973,2842273706,3305899714,1510255612,2148256476,2655287854,3276092548,4258621189,236887753,3681803219,274041037,1734335097,3815195456,3317970021,1899903192,1026095262,4050517792,356393447,2410691914,3873677099,3682840055],[3913112168,2491498743,
+4132185628,2489919796,1091903735,1979897079,3170134830,3567386728,3557303409,857797738,1136121015,1342202287,507115054,2535736646,337727348,3213592640,1301675037,2528481711,1895095763,1721773893,3216771564,62756741,2142006736,835421444,2531993523,1442658625,3659876326,2882144922,676362277,1392781812,170690266,3921047035,1759253602,3611846912,1745797284,664899054,1329594018,3901205900,3045908486,2062866102,2865634940,3543621612,3464012697,1080764994,553557557,3656615353,3996768171,991055499,499776247,
+1265440854,648242737,3940784050,980351604,3713745714,1749149687,3396870395,4211799374,3640570775,1161844396,3125318951,1431517754,545492359,4268468663,3499529547,1437099964,2702547544,3433638243,2581715763,2787789398,1060185593,1593081372,2418618748,4260947970,69676912,2159744348,86519011,2512459080,3838209314,1220612927,3339683548,133810670,1090789135,1078426020,1569222167,845107691,3583754449,4072456591,1091646820,628848692,1613405280,3757631651,526609435,236106946,48312990,2942717905,3402727701,
+1797494240,859738849,992217954,4005476642,2243076622,3870952857,3732016268,765654824,3490871365,2511836413,1685915746,3888969200,1414112111,2273134842,3281911079,4080962846,172450625,2569994100,980381355,4109958455,2819808352,2716589560,2568741196,3681446669,3329971472,1835478071,660984891,3704678404,4045999559,3422617507,3040415634,1762651403,1719377915,3470491036,2693910283,3642056355,3138596744,1364962596,2073328063,1983633131,926494387,3423689081,2150032023,4096667949,1749200295,3328846651,309677260,
+2016342300,1779581495,3079819751,111262694,1274766160,443224088,298511866,1025883608,3806446537,1145181785,168956806,3641502830,3584813610,1689216846,3666258015,3200248200,1692713982,2646376535,4042768518,1618508792,1610833997,3523052358,4130873264,2001055236,3610705100,2202168115,4028541809,2961195399,1006657119,2006996926,3186142756,1430667929,3210227297,1314452623,4074634658,4101304120,2273951170,1399257539,3367210612,3027628629,1190975929,2062231137,2333990788,2221543033,2438960610,1181637006,
+548689776,2362791313,3372408396,3104550113,3145860560,296247880,1970579870,3078560182,3769228297,1714227617,3291629107,3898220290,166772364,1251581989,493813264,448347421,195405023,2709975567,677966185,3703036547,1463355134,2715995803,1338867538,1343315457,2802222074,2684532164,233230375,2599980071,2000651841,3277868038,1638401717,4028070440,3237316320,6314154,819756386,300326615,590932579,1405279636,3267499572,3150704214,2428286686,3959192993,3461946742,1862657033,1266418056,963775037,2089974820,
+2263052895,1917689273,448879540,3550394620,3981727096,150775221,3627908307,1303187396,508620638,2975983352,2726630617,1817252668,1876281319,1457606340,908771278,3720792119,3617206836,2455994898,1729034894,1080033504],[976866871,3556439503,2881648439,1522871579,1555064734,1336096578,3548522304,2579274686,3574697629,3205460757,3593280638,3338716283,3079412587,564236357,2993598910,1781952180,1464380207,3163844217,3332601554,1699332808,1393555694,1183702653,3581086237,1288719814,691649499,2847557200,
+2895455976,3193889540,2717570544,1781354906,1676643554,2592534050,3230253752,1126444790,2770207658,2633158820,2210423226,2615765581,2414155088,3127139286,673620729,2805611233,1269405062,4015350505,3341807571,4149409754,1057255273,2012875353,2162469141,2276492801,2601117357,993977747,3918593370,2654263191,753973209,36408145,2530585658,25011837,3520020182,2088578344,530523599,2918365339,1524020338,1518925132,3760827505,3759777254,1202760957,3985898139,3906192525,674977740,4174734889,2031300136,2019492241,
+3983892565,4153806404,3822280332,352677332,2297720250,60907813,90501309,3286998549,1016092578,2535922412,2839152426,457141659,509813237,4120667899,652014361,1966332200,2975202805,55981186,2327461051,676427537,3255491064,2882294119,3433927263,1307055953,942726286,933058658,2468411793,3933900994,4215176142,1361170020,2001714738,2830558078,3274259782,1222529897,1679025792,2729314320,3714953764,1770335741,151462246,3013232138,1682292957,1483529935,471910574,1539241949,458788160,3436315007,1807016891,
+3718408830,978976581,1043663428,3165965781,1927990952,4200891579,2372276910,3208408903,3533431907,1412390302,2931980059,4132332400,1947078029,3881505623,4168226417,2941484381,1077988104,1320477388,886195818,18198404,3786409E3,2509781533,112762804,3463356488,1866414978,891333506,18488651,661792760,1628790961,3885187036,3141171499,876946877,2693282273,1372485963,791857591,2686433993,3759982718,3167212022,3472953795,2716379847,445679433,3561995674,3504004811,3574258232,54117162,3331405415,2381918588,
+3769707343,4154350007,1140177722,4074052095,668550556,3214352940,367459370,261225585,2610173221,4209349473,3468074219,3265815641,314222801,3066103646,3808782860,282218597,3406013506,3773591054,379116347,1285071038,846784868,2669647154,3771962079,3550491691,2305946142,453669953,1268987020,3317592352,3279303384,3744833421,2610507566,3859509063,266596637,3847019092,517658769,3462560207,3443424879,370717030,4247526661,2224018117,4143653529,4112773975,2788324899,2477274417,1456262402,2901442914,1517677493,
+1846949527,2295493580,3734397586,2176403920,1280348187,1908823572,3871786941,846861322,1172426758,3287448474,3383383037,1655181056,3139813346,901632758,1897031941,2986607138,3066810236,3447102507,1393639104,373351379,950779232,625454576,3124240540,4148612726,2007998917,544563296,2244738638,2330496472,2058025392,1291430526,424198748,50039436,29584100,3605783033,2429876329,2791104160,1057563949,3255363231,3075367218,3463963227,1469046755,985887462]];
+Blowfish.prototype.PARRAY=[608135816,2242054355,320440878,57701188,2752067618,698298832,137296536,3964562569,1160258022,953160567,3193202383,887688300,3232508343,3380367581,1065670069,3041331479,2450970073,2306472731];Blowfish.prototype.NN=16;Blowfish.prototype._clean=function(a){0>a&&(a=(a&2147483647)+2147483648);return a};Blowfish.prototype._F=function(a){var b,c,d;d=a&255;a>>>=8;c=a&255;a>>>=8;b=a&255;a=this.sboxes[0][a>>>8&255]+this.sboxes[1][b];a^=this.sboxes[2][c];return a+=this.sboxes[3][d]};
+Blowfish.prototype._encrypt_block=function(a){var b=a[0],c=a[1],d;for(d=0;d<this.NN;++d)var b=b^this.parray[d],c=this._F(b)^c,e=b,b=c,c=e;b^=this.parray[this.NN+0];c^=this.parray[this.NN+1];a[0]=this._clean(c);a[1]=this._clean(b)};Blowfish.prototype.encrypt_block=function(a){var b,c=[0,0],d=this.BLOCKSIZE/2;for(b=0;b<this.BLOCKSIZE/2;++b)c[0]=c[0]<<8|a[b+0]&255,c[1]=c[1]<<8|a[b+d]&255;this._encrypt_block(c);a=[];for(b=0;b<this.BLOCKSIZE/2;++b)a[b+0]=c[0]>>>24-8*b&255,a[b+d]=c[1]>>>24-8*b&255;return a};
+Blowfish.prototype._decrypt_block=function(a){var b=a[0],c=a[1],d;for(d=this.NN+1;1<d;--d)var b=b^this.parray[d],c=this._F(b)^c,e=b,b=c,c=e;b^=this.parray[1];c^=this.parray[0];a[0]=this._clean(c);a[1]=this._clean(b)};
+Blowfish.prototype.init=function(a){var b,c=0;this.parray=[];for(b=0;b<this.NN+2;++b){var d=0,e;for(e=0;4>e;++e)d=d<<8|a[c]&255,++c>=a.length&&(c=0);this.parray[b]=this.PARRAY[b]^d}this.sboxes=[];for(b=0;4>b;++b){this.sboxes[b]=[];for(c=0;256>c;++c)this.sboxes[b][c]=this.SBOXES[b][c]}a=[0,0];for(b=0;b<this.NN+2;b+=2)this._encrypt_block(a),this.parray[b+0]=a[0],this.parray[b+1]=a[1];for(b=0;4>b;++b)for(c=0;256>c;c+=2)this._encrypt_block(a),this.sboxes[b][c+0]=a[0],this.sboxes[b][c+1]=a[1]};
+function BFencrypt(a,b){var c=new Blowfish;c.init(util.str2bin(b));return c.encrypt_block(a)}
 var Rcon=[1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47,94,188,99,198,151,53,106,212,179,125,250,239,197,145],S=[99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,208,239,170,251,67,77,51,133,69,249,2,127,80,
 60,159,168,81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,205,12,19,236,95,151,68,23,196,167,126,61,100,93,25,115,96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,224,50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,231,200,55,109,141,213,78,169,108,86,244,234,101,122,174,8,186,120,37,46,28,166,180,198,232,221,116,31,75,189,139,138,112,62,181,102,72,3,246,14,97,53,87,185,134,193,29,158,225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,140,161,137,13,191,230,66,104,65,
 153,45,15,176,84,187,22],T1=[2774754246,2222750968,2574743534,2373680118,234025727,3177933782,2976870366,1422247313,1345335392,50397442,2842126286,2099981142,436141799,1658312629,3870010189,2591454956,1170918031,2642575903,1086966153,2273148410,368769775,3948501426,3376891790,200339707,3970805057,1742001331,4255294047,3937382213,3214711843,4154762323,2524082916,1539358875,3266819957,486407649,2928907069,1780885068,1513502316,1094664062,49805301,1338821763,1546925160,4104496465,887481809,150073849,
@@ -271,118 +419,72 @@ var Rcon=[1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47,94,188,99,198,151,53,
 967348625,832869781,3543655652,4069226873,3576883175,2336475336,1851340599,3669454189,25988493,2976175573,2631028302,1239460265,3635702892,2902087254,4077384948,3475368682,3400492389,4102978170,1206496942,270010376,1876277946,4035475576,1248797989,1550986798,941890588,1475454630,1942467764,2538718918,3408128232,2709315037,3902567540,1042358047,2531085131,1641856445,226921355,260409994,3767562352,2084716094,1908716981,3433719398,2430093384,100991747,4144101110,470945294,3265487201,1784624437,2935576407,
 1775286713,395413126,2572730817,975641885,666476190,3644383713,3943954680,733190296,573772049,3535497577,2842745305,126455438,866620564,766942107,1008868894,361924487,3374377449,2269761230,2868860245,1350051880,2776293343,59739276,1509466529,159418761,437718285,1708834751,3610371814,2227585602,3501746280,2193834305,699439513,1517759789,504434447,2076946608,2835108948,1842789307,742004246];function B0(a){return a&255}function B1(a){return a>>8&255}function B2(a){return a>>16&255}
 function B3(a){return a>>24&255}function F1(a,b,c,d){return B1(T1[a&255])|B1(T1[b>>8&255])<<8|B1(T1[c>>16&255])<<16|B1(T1[d>>>24])<<24}function packBytes(a){var b,c,d=a.length,e=Array(d/4);if(a&&!(d%4)){for(b=0,c=0;c<d;c+=4)e[b++]=a[c]|a[c+1]<<8|a[c+2]<<16|a[c+3]<<24;return e}}function unpackBytes(a){var b,c=0,d=a.length,e=Array(4*d);for(b=0;b<d;b++)e[c++]=B0(a[b]),e[c++]=B1(a[b]),e[c++]=B2(a[b]),e[c++]=B3(a[b]);return e}var maxkc=8,maxrk=14;
-function keyExpansion(a){var b,c,d,e,f=Array(maxrk+1),h=a.length,g=Array(maxkc),k=Array(maxkc),j=0;if(16==h)e=10,b=4;else if(24==h)e=12,b=6;else if(32==h)e=14,b=8;else{util.print_error("aes.js: Invalid key-length for AES key:"+h);return}for(c=0;c<maxrk+1;c++)f[c]=Array(4);for(c=0,d=0;d<h;d++,c+=4)g[d]=a.charCodeAt(c)|a.charCodeAt(c+1)<<8|a.charCodeAt(c+2)<<16|a.charCodeAt(c+3)<<24;for(d=b-1;0<=d;d--)k[d]=g[d];for(d=c=a=0;d<b&&a<e+1;){for(;d<b&&4>c;d++,c++)f[a][c]=k[d];4==c&&(a++,c=0)}for(;a<e+1;){d=
+function keyExpansion(a){var b,c,d,e,f=Array(maxrk+1),g=a.length,h=Array(maxkc),k=Array(maxkc),j=0;if(16==g)e=10,b=4;else if(24==g)e=12,b=6;else if(32==g)e=14,b=8;else{util.print_error("aes.js: Invalid key-length for AES key:"+g);return}for(c=0;c<maxrk+1;c++)f[c]=Array(4);for(c=0,d=0;d<g;d++,c+=4)h[d]=a.charCodeAt(c)|a.charCodeAt(c+1)<<8|a.charCodeAt(c+2)<<16|a.charCodeAt(c+3)<<24;for(d=b-1;0<=d;d--)k[d]=h[d];for(d=c=a=0;d<b&&a<e+1;){for(;d<b&&4>c;d++,c++)f[a][c]=k[d];4==c&&(a++,c=0)}for(;a<e+1;){d=
 k[b-1];k[0]^=S[B1(d)]|S[B2(d)]<<8|S[B3(d)]<<16|S[B0(d)]<<24;k[0]^=Rcon[j++];if(8!=b)d=1;else{for(d=1;d<b/2;d++)k[d]^=k[d-1];d=k[b/2-1];k[b/2]^=S[B0(d)]|S[B1(d)]<<8|S[B2(d)]<<16|S[B3(d)]<<24;d=b/2+1}for(;d<b;d++)k[d]^=k[d-1];for(d=0;d<b&&a<e+1;){for(;d<b&&4>c;d++,c++)f[a][c]=k[d];4==c&&(a++,c=0)}}this.rounds=e;this.rk=f;return this}
-function AESencrypt(a,b){var c,d,e,f,h,g=packBytes(a),k=b.rounds,j=g[0],l=g[1],q=g[2];h=g[3];for(c=0;c<k-1;c++)d=j^b.rk[c][0],e=l^b.rk[c][1],f=q^b.rk[c][2],h^=b.rk[c][3],j=T1[d&255]^T2[e>>8&255]^T3[f>>16&255]^T4[h>>>24],l=T1[e&255]^T2[f>>8&255]^T3[h>>16&255]^T4[d>>>24],q=T1[f&255]^T2[h>>8&255]^T3[d>>16&255]^T4[e>>>24],h=T1[h&255]^T2[d>>8&255]^T3[e>>16&255]^T4[f>>>24];c=k-1;d=j^b.rk[c][0];e=l^b.rk[c][1];f=q^b.rk[c][2];h^=b.rk[c][3];g[0]=F1(d,e,f,h)^b.rk[k][0];g[1]=F1(e,f,h,d)^b.rk[k][1];g[2]=F1(f,
-h,d,e)^b.rk[k][2];g[3]=F1(h,d,e,f)^b.rk[k][3];return unpackBytes(g)}function TFencrypt(a,b){var c=[].concat(a),d=createTwofish();d.open(util.str2bin(b),0);c=d.encrypt(c,0);d.close();return c}var MAXINT=4294967295;function rotb(a,b){return(a<<b|a>>>8-b)&255}function rotw(a,b){return(a<<b|a>>>32-b)&MAXINT}function getW(a,b){return a[b]|a[b+1]<<8|a[b+2]<<16|a[b+3]<<24}function setW(a,b,c){a.splice(b,4,c&255,c>>>8&255,c>>>16&255,c>>>24&255)}
-function setWInv(a,b,c){a.splice(b,4,c>>>24&255,c>>>16&255,c>>>8&255,c&255)}function getB(a,b){return a>>>8*b&255}function getNrBits(a){for(var b=0;0<a;)b++,a>>>=1;return b}function getMask(a){return(1<<a)-1}function randByte(){return Math.floor(256*Math.random())}
-function createTwofish(){function a(b){return h[0][getB(b,0)]^h[1][getB(b,1)]^h[2][getB(b,2)]^h[3][getB(b,3)]}function b(b){return h[0][getB(b,3)]^h[1][getB(b,0)]^h[2][getB(b,1)]^h[3][getB(b,2)]}var c=null,d=null,e=-1,f=[],h=[[],[],[],[]];return{name:"twofish",blocksize:16,open:function(b){function a(b,c){var d,e,f;for(d=0;8>d;d++)e=c>>>24,c=c<<8&MAXINT|b>>>24,b=b<<8&MAXINT,f=e<<1,e&128&&(f^=333),c^=e^f<<16,f^=e>>>1,e&1&&(f^=166),c^=f<<24|f<<8;return c}function d(b,a){var c,e,f;c=a>>4;e=a&15;f=A[b][c^
-e];c=ga[b][ha[e]^K[c]];return aa[b][ha[c]^K[f]]<<4|ia[b][f^c]}function e(b,a){var c=getB(b,0),d=getB(b,1),f=getB(b,2),h=getB(b,3);switch(O){case 4:c=E[1][c]^getB(a[3],0),d=E[0][d]^getB(a[3],1),f=E[0][f]^getB(a[3],2),h=E[1][h]^getB(a[3],3);case 3:c=E[1][c]^getB(a[2],0),d=E[1][d]^getB(a[2],1),f=E[0][f]^getB(a[2],2),h=E[0][h]^getB(a[2],3);case 2:c=E[0][E[0][c]^getB(a[1],0)]^getB(a[0],0),d=E[0][E[1][d]^getB(a[1],1)]^getB(a[0],1),f=E[1][E[0][f]^getB(a[1],2)]^getB(a[0],2),h=E[1][E[1][h]^getB(a[1],3)]^getB(a[0],
-3)}return V[0][c]^V[1][d]^V[2][f]^V[3][h]}c=b;var q,u,m,o;m=[];o=[];var M=[],O,D=[],B,A=[[8,1,7,13,6,15,3,2,0,11,5,9,14,12,10,4],[2,8,11,13,15,7,6,14,3,1,9,4,0,10,12,5]],ga=[[14,12,11,8,1,2,3,5,15,4,10,6,7,0,9,13],[1,14,2,11,4,12,3,7,6,13,10,5,15,9,0,8]],ia=[[11,10,5,14,6,13,9,0,12,8,15,3,2,4,7,1],[4,12,7,5,1,6,9,10,0,14,13,8,2,11,3,15]],aa=[[13,7,15,4,1,2,6,14,9,11,3,0,8,5,12,10],[11,9,5,1,12,3,13,14,6,4,7,15,2,0,8,10]],ha=[0,8,1,9,2,10,3,11,4,12,5,13,6,14,7,15],K=[0,9,2,11,4,13,6,15,8,1,10,3,12,
-5,14,7],E=[[],[]],V=[[],[],[],[]];c=c.slice(0,32);for(b=c.length;16!=b&&24!=b&&32!=b;)c[b++]=0;for(b=0;b<c.length;b+=4)M[b>>2]=getW(c,b);for(b=0;256>b;b++)E[0][b]=d(0,b),E[1][b]=d(1,b);for(b=0;256>b;b++)q=E[1][b],u=q^q>>2^[0,90,180,238][q&3],B=q^q>>1^q>>2^[0,238,180,90][q&3],V[0][b]=q+(u<<8)+(B<<16)+(B<<24),V[2][b]=u+(B<<8)+(q<<16)+(B<<24),q=E[0][b],u=q^q>>2^[0,90,180,238][q&3],B=q^q>>1^q>>2^[0,238,180,90][q&3],V[1][b]=B+(B<<8)+(u<<16)+(q<<24),V[3][b]=u+(q<<8)+(B<<16)+(u<<24);O=M.length/2;for(b=0;b<
-O;b++)q=M[b+b],m[b]=q,u=M[b+b+1],o[b]=u,D[O-b-1]=a(q,u);for(b=0;40>b;b+=2)q=16843009*b,u=q+16843009,q=e(q,m),u=rotw(e(u,o),8),f[b]=q+u&MAXINT,f[b+1]=rotw(q+2*u,9);for(b=0;256>b;b++)switch(q=u=m=o=b,O){case 4:q=E[1][q]^getB(D[3],0),u=E[0][u]^getB(D[3],1),m=E[0][m]^getB(D[3],2),o=E[1][o]^getB(D[3],3);case 3:q=E[1][q]^getB(D[2],0),u=E[1][u]^getB(D[2],1),m=E[0][m]^getB(D[2],2),o=E[0][o]^getB(D[2],3);case 2:h[0][b]=V[0][E[0][E[0][q]^getB(D[1],0)]^getB(D[0],0)],h[1][b]=V[1][E[0][E[1][u]^getB(D[1],1)]^getB(D[0],
-1)],h[2][b]=V[2][E[1][E[0][m]^getB(D[1],2)]^getB(D[0],2)],h[3][b]=V[3][E[1][E[1][o]^getB(D[1],3)]^getB(D[0],3)]}},close:function(){f=[];h=[[],[],[],[]]},encrypt:function(c,h){d=c;e=h;for(var j=[getW(d,e)^f[0],getW(d,e+4)^f[1],getW(d,e+8)^f[2],getW(d,e+12)^f[3]],l=0;8>l;l++){var q=l,u=j,m=a(u[0]),o=b(u[1]);u[2]=rotw(u[2]^m+o+f[4*q+8]&MAXINT,31);u[3]=rotw(u[3],1)^m+2*o+f[4*q+9]&MAXINT;m=a(u[2]);o=b(u[3]);u[0]=rotw(u[0]^m+o+f[4*q+10]&MAXINT,31);u[1]=rotw(u[1],1)^m+2*o+f[4*q+11]&MAXINT}setW(d,e,j[2]^
-f[4]);setW(d,e+4,j[3]^f[5]);setW(d,e+8,j[0]^f[6]);setW(d,e+12,j[1]^f[7]);e+=16;return d},decrypt:function(c,h){d=c;e=h;for(var j=[getW(d,e)^f[4],getW(d,e+4)^f[5],getW(d,e+8)^f[6],getW(d,e+12)^f[7]],l=7;0<=l;l--){var q=l,u=j,m=a(u[0]),o=b(u[1]);u[2]=rotw(u[2],1)^m+o+f[4*q+10]&MAXINT;u[3]=rotw(u[3]^m+2*o+f[4*q+11]&MAXINT,31);m=a(u[2]);o=b(u[3]);u[0]=rotw(u[0],1)^m+o+f[4*q+8]&MAXINT;u[1]=rotw(u[1]^m+2*o+f[4*q+9]&MAXINT,31)}setW(d,e,j[2]^f[0]);setW(d,e+4,j[3]^f[1]);setW(d,e+8,j[0]^f[2]);setW(d,e+12,j[1]^
-f[3]);e+=16},finalize:function(){return d}}}function SecureRandom(){this.nextBytes=function(a){for(var b=0;b<a.length;b++)a[b]=openpgp_crypto_getSecureRandomOctet()}}
-function RSA(){function a(){this.n=null;this.e=0;this.u=this.dmq1=this.dmp1=this.q=this.p=this.d=this.ee=null}this.encrypt=function(b,a,d){return b.modPowInt(a,d)};this.decrypt=function(b,a,d,e,f){var h=b.mod(d).modPow(a.mod(d.subtract(BigInteger.ONE)),d),b=b.mod(e).modPow(a.mod(e.subtract(BigInteger.ONE)),e);util.print_debug("rsa.js decrypt\nxpn:"+util.hexstrdump(h.toMPI())+"\nxqn:"+util.hexstrdump(b.toMPI()));a=b.subtract(h);0==a[0]?(a=h.subtract(b),a=a.multiply(f).mod(e),a=e.subtract(a)):a=a.multiply(f).mod(e);
-return a.multiply(d).add(h)};this.verify=function(b,a,d){return b.modPowInt(a,d)};this.sign=function(b,a,d){return b.modPow(a,d)};this.generate=function(b,c){var d=new a,e=new SecureRandom,f=b>>1;d.e=parseInt(c,16);for(d.ee=new BigInteger(c,16);;){for(;!(d.p=new BigInteger(b-f,1,e),0==d.p.subtract(BigInteger.ONE).gcd(d.ee).compareTo(BigInteger.ONE)&&d.p.isProbablePrime(10)););for(;!(d.q=new BigInteger(f,1,e),0==d.q.subtract(BigInteger.ONE).gcd(d.ee).compareTo(BigInteger.ONE)&&d.q.isProbablePrime(10)););
-if(0>=d.p.compareTo(d.q)){var h=d.p;d.p=d.q;d.q=h}var h=d.p.subtract(BigInteger.ONE),g=d.q.subtract(BigInteger.ONE),k=h.multiply(g);if(0==k.gcd(d.ee).compareTo(BigInteger.ONE)){d.n=d.p.multiply(d.q);d.d=d.ee.modInverse(k);d.dmp1=d.d.mod(h);d.dmq1=d.d.mod(g);d.u=d.p.modInverse(d.q);break}}return d};this.keyObject=a}
-function DSA(){this.select_hash_algorithm=function(a){var b=openpgp.config.config.prefer_hash_algorithm;switch(Math.round(a.bitLength()/8)){case 20:return 2!=b&&11<b&&10!=b&&8>b?2:b;case 28:return 11<b&&8>b?11:b;case 32:return 10<b&&8>b?8:b;default:return util.print_debug("DSA select hash algorithm: returning null for an unknown length of q"),null}};this.sign=function(a,b,c,d,e,f){a=util.getLeftNBits(openpgp_crypto_hashData(a,b),e.bitLength());a=new BigInteger(util.hexstrdump(a),16);b=openpgp_crypto_getRandomBigIntegerInRange(BigInteger.ONE.add(BigInteger.ONE),
-e.subtract(BigInteger.ONE));c=c.modPow(b,d).mod(e);e=b.modInverse(e).multiply(a.add(f.multiply(c))).mod(e);f=[];f[0]=c.toMPI();f[1]=e.toMPI();return f};this.verify=function(a,b,c,d,e,f,h,g){a=util.getLeftNBits(openpgp_crypto_hashData(a,d),f.bitLength());a=new BigInteger(util.hexstrdump(a),16);if(0<BigInteger.ZERO.compareTo(b)||0<b.compareTo(f)||0<BigInteger.ZERO.compareTo(c)||0<c.compareTo(f))return util.print_error("invalid DSA Signature"),null;c=c.modInverse(f);a=a.multiply(c).mod(f);b=b.multiply(c).mod(f);
-return h.modPow(a,e).multiply(g.modPow(b,e)).mod(e).mod(f)}}var dbits,canary=244837814094590,j_lm=15715070==(canary&16777215);function BigInteger(a,b,c){null!=a&&("number"==typeof a?this.fromNumber(a,b,c):null==b&&"string"!=typeof a?this.fromString(a,256):this.fromString(a,b))}function nbi(){return new BigInteger(null)}function am1(a,b,c,d,e,f){for(;0<=--f;){var h=b*this[a++]+c[d]+e,e=Math.floor(h/67108864);c[d++]=h&67108863}return e}
-function am2(a,b,c,d,e,f){for(var h=b&32767,b=b>>15;0<=--f;){var g=this[a]&32767,k=this[a++]>>15,j=b*g+k*h,g=h*g+((j&32767)<<15)+c[d]+(e&1073741823),e=(g>>>30)+(j>>>15)+b*k+(e>>>30);c[d++]=g&1073741823}return e}function am3(a,b,c,d,e,f){for(var h=b&16383,b=b>>14;0<=--f;){var g=this[a]&16383,k=this[a++]>>14,j=b*g+k*h,g=h*g+((j&16383)<<14)+c[d]+e,e=(g>>28)+(j>>14)+b*k;c[d++]=g&268435455}return e}
-j_lm&&"Microsoft Internet Explorer"==navigator.appName?(BigInteger.prototype.am=am2,dbits=30):j_lm&&"Netscape"!=navigator.appName?(BigInteger.prototype.am=am1,dbits=26):(BigInteger.prototype.am=am3,dbits=28);BigInteger.prototype.DB=dbits;BigInteger.prototype.DM=(1<<dbits)-1;BigInteger.prototype.DV=1<<dbits;var BI_FP=52;BigInteger.prototype.FV=Math.pow(2,BI_FP);BigInteger.prototype.F1=BI_FP-dbits;BigInteger.prototype.F2=2*dbits-BI_FP;var BI_RM="0123456789abcdefghijklmnopqrstuvwxyz",BI_RC=[],rr,vv;
-rr=48;for(vv=0;9>=vv;++vv)BI_RC[rr++]=vv;rr=97;for(vv=10;36>vv;++vv)BI_RC[rr++]=vv;rr=65;for(vv=10;36>vv;++vv)BI_RC[rr++]=vv;function int2char(a){return BI_RM.charAt(a)}function intAt(a,b){var c=BI_RC[a.charCodeAt(b)];return null==c?-1:c}function bnpCopyTo(a){for(var b=this.t-1;0<=b;--b)a[b]=this[b];a.t=this.t;a.s=this.s}function bnpFromInt(a){this.t=1;this.s=0>a?-1:0;0<a?this[0]=a:-1>a?this[0]=a+DV:this.t=0}function nbv(a){var b=nbi();b.fromInt(a);return b}
-function bnpFromString(a,b){var c;if(16==b)c=4;else if(8==b)c=3;else if(256==b)c=8;else if(2==b)c=1;else if(32==b)c=5;else if(4==b)c=2;else{this.fromRadix(a,b);return}this.s=this.t=0;for(var d=a.length,e=!1,f=0;0<=--d;){var h=8==c?a[d]&255:intAt(a,d);0>h?"-"==a.charAt(d)&&(e=!0):(e=!1,0==f?this[this.t++]=h:f+c>this.DB?(this[this.t-1]|=(h&(1<<this.DB-f)-1)<<f,this[this.t++]=h>>this.DB-f):this[this.t-1]|=h<<f,f+=c,f>=this.DB&&(f-=this.DB))}if(8==c&&0!=(a[0]&128))this.s=-1,0<f&&(this[this.t-1]|=(1<<
-this.DB-f)-1<<f);this.clamp();e&&BigInteger.ZERO.subTo(this,this)}function bnpClamp(){for(var a=this.s&this.DM;0<this.t&&this[this.t-1]==a;)--this.t}
-function bnToString(a){if(0>this.s)return"-"+this.negate().toString(a);if(16==a)a=4;else if(8==a)a=3;else if(2==a)a=1;else if(32==a)a=5;else if(4==a)a=2;else return this.toRadix(a);var b=(1<<a)-1,c,d=!1,e="",f=this.t,h=this.DB-f*this.DB%a;if(0<f--){if(h<this.DB&&0<(c=this[f]>>h))d=!0,e=int2char(c);for(;0<=f;)h<a?(c=(this[f]&(1<<h)-1)<<a-h,c|=this[--f]>>(h+=this.DB-a)):(c=this[f]>>(h-=a)&b,0>=h&&(h+=this.DB,--f)),0<c&&(d=!0),d&&(e+=int2char(c))}return d?e:"0"}
-function bnNegate(){var a=nbi();BigInteger.ZERO.subTo(this,a);return a}function bnAbs(){return 0>this.s?this.negate():this}function bnCompareTo(a){var b=this.s-a.s;if(0!=b)return b;var c=this.t,b=c-a.t;if(0!=b)return b;for(;0<=--c;)if(0!=(b=this[c]-a[c]))return b;return 0}function nbits(a){var b=1,c;if(0!=(c=a>>>16))a=c,b+=16;if(0!=(c=a>>8))a=c,b+=8;if(0!=(c=a>>4))a=c,b+=4;if(0!=(c=a>>2))a=c,b+=2;0!=a>>1&&(b+=1);return b}
-function bnBitLength(){return 0>=this.t?0:this.DB*(this.t-1)+nbits(this[this.t-1]^this.s&this.DM)}function bnpDLShiftTo(a,b){var c;for(c=this.t-1;0<=c;--c)b[c+a]=this[c];for(c=a-1;0<=c;--c)b[c]=0;b.t=this.t+a;b.s=this.s}function bnpDRShiftTo(a,b){for(var c=a;c<this.t;++c)b[c-a]=this[c];b.t=Math.max(this.t-a,0);b.s=this.s}
-function bnpLShiftTo(a,b){var c=a%this.DB,d=this.DB-c,e=(1<<d)-1,f=Math.floor(a/this.DB),h=this.s<<c&this.DM,g;for(g=this.t-1;0<=g;--g)b[g+f+1]=this[g]>>d|h,h=(this[g]&e)<<c;for(g=f-1;0<=g;--g)b[g]=0;b[f]=h;b.t=this.t+f+1;b.s=this.s;b.clamp()}
-function bnpRShiftTo(a,b){b.s=this.s;var c=Math.floor(a/this.DB);if(c>=this.t)b.t=0;else{var d=a%this.DB,e=this.DB-d,f=(1<<d)-1;b[0]=this[c]>>d;for(var h=c+1;h<this.t;++h)b[h-c-1]|=(this[h]&f)<<e,b[h-c]=this[h]>>d;0<d&&(b[this.t-c-1]|=(this.s&f)<<e);b.t=this.t-c;b.clamp()}}
-function bnpSubTo(a,b){for(var c=0,d=0,e=Math.min(a.t,this.t);c<e;)d+=this[c]-a[c],b[c++]=d&this.DM,d>>=this.DB;if(a.t<this.t){for(d-=a.s;c<this.t;)d+=this[c],b[c++]=d&this.DM,d>>=this.DB;d+=this.s}else{for(d+=this.s;c<a.t;)d-=a[c],b[c++]=d&this.DM,d>>=this.DB;d-=a.s}b.s=0>d?-1:0;-1>d?b[c++]=this.DV+d:0<d&&(b[c++]=d);b.t=c;b.clamp()}
-function bnpMultiplyTo(a,b){var c=this.abs(),d=a.abs(),e=c.t;for(b.t=e+d.t;0<=--e;)b[e]=0;for(e=0;e<d.t;++e)b[e+c.t]=c.am(0,d[e],b,e,0,c.t);b.s=0;b.clamp();this.s!=a.s&&BigInteger.ZERO.subTo(b,b)}function bnpSquareTo(a){for(var b=this.abs(),c=a.t=2*b.t;0<=--c;)a[c]=0;for(c=0;c<b.t-1;++c){var d=b.am(c,b[c],a,2*c,0,1);if((a[c+b.t]+=b.am(c+1,2*b[c],a,2*c+1,d,b.t-c-1))>=b.DV)a[c+b.t]-=b.DV,a[c+b.t+1]=1}0<a.t&&(a[a.t-1]+=b.am(c,b[c],a,2*c,0,1));a.s=0;a.clamp()}
-function bnpDivRemTo(a,b,c){var d=a.abs();if(!(0>=d.t)){var e=this.abs();if(e.t<d.t)null!=b&&b.fromInt(0),null!=c&&this.copyTo(c);else{null==c&&(c=nbi());var f=nbi(),h=this.s,a=a.s,g=this.DB-nbits(d[d.t-1]);0<g?(d.lShiftTo(g,f),e.lShiftTo(g,c)):(d.copyTo(f),e.copyTo(c));d=f.t;e=f[d-1];if(0!=e){var k=e*(1<<this.F1)+(1<d?f[d-2]>>this.F2:0),j=this.FV/k,k=(1<<this.F1)/k,l=1<<this.F2,q=c.t,u=q-d,m=null==b?nbi():b;f.dlShiftTo(u,m);0<=c.compareTo(m)&&(c[c.t++]=1,c.subTo(m,c));BigInteger.ONE.dlShiftTo(d,
-m);for(m.subTo(f,f);f.t<d;)f[f.t++]=0;for(;0<=--u;){var o=c[--q]==e?this.DM:Math.floor(c[q]*j+(c[q-1]+l)*k);if((c[q]+=f.am(0,o,c,u,0,d))<o){f.dlShiftTo(u,m);for(c.subTo(m,c);c[q]<--o;)c.subTo(m,c)}}null!=b&&(c.drShiftTo(d,b),h!=a&&BigInteger.ZERO.subTo(b,b));c.t=d;c.clamp();0<g&&c.rShiftTo(g,c);0>h&&BigInteger.ZERO.subTo(c,c)}}}}function bnMod(a){var b=nbi();this.abs().divRemTo(a,null,b);0>this.s&&0<b.compareTo(BigInteger.ZERO)&&a.subTo(b,b);return b}function Classic(a){this.m=a}
-function cConvert(a){return 0>a.s||0<=a.compareTo(this.m)?a.mod(this.m):a}function cRevert(a){return a}function cReduce(a){a.divRemTo(this.m,null,a)}function cMulTo(a,b,c){a.multiplyTo(b,c);this.reduce(c)}function cSqrTo(a,b){a.squareTo(b);this.reduce(b)}Classic.prototype.convert=cConvert;Classic.prototype.revert=cRevert;Classic.prototype.reduce=cReduce;Classic.prototype.mulTo=cMulTo;Classic.prototype.sqrTo=cSqrTo;
-function bnpInvDigit(){if(1>this.t)return 0;var a=this[0];if(0==(a&1))return 0;var b=a&3,b=b*(2-(a&15)*b)&15,b=b*(2-(a&255)*b)&255,b=b*(2-((a&65535)*b&65535))&65535,b=b*(2-a*b%this.DV)%this.DV;return 0<b?this.DV-b:-b}function Montgomery(a){this.m=a;this.mp=a.invDigit();this.mpl=this.mp&32767;this.mph=this.mp>>15;this.um=(1<<a.DB-15)-1;this.mt2=2*a.t}
-function montConvert(a){var b=nbi();a.abs().dlShiftTo(this.m.t,b);b.divRemTo(this.m,null,b);0>a.s&&0<b.compareTo(BigInteger.ZERO)&&this.m.subTo(b,b);return b}function montRevert(a){var b=nbi();a.copyTo(b);this.reduce(b);return b}
-function montReduce(a){for(;a.t<=this.mt2;)a[a.t++]=0;for(var b=0;b<this.m.t;++b){var c=a[b]&32767,d=c*this.mpl+((c*this.mph+(a[b]>>15)*this.mpl&this.um)<<15)&a.DM,c=b+this.m.t;for(a[c]+=this.m.am(0,d,a,b,0,this.m.t);a[c]>=a.DV;)a[c]-=a.DV,a[++c]++}a.clamp();a.drShiftTo(this.m.t,a);0<=a.compareTo(this.m)&&a.subTo(this.m,a)}function montSqrTo(a,b){a.squareTo(b);this.reduce(b)}function montMulTo(a,b,c){a.multiplyTo(b,c);this.reduce(c)}Montgomery.prototype.convert=montConvert;
-Montgomery.prototype.revert=montRevert;Montgomery.prototype.reduce=montReduce;Montgomery.prototype.mulTo=montMulTo;Montgomery.prototype.sqrTo=montSqrTo;function bnpIsEven(){return 0==(0<this.t?this[0]&1:this.s)}function bnpExp(a,b){if(4294967295<a||1>a)return BigInteger.ONE;var c=nbi(),d=nbi(),e=b.convert(this),f=nbits(a)-1;for(e.copyTo(c);0<=--f;)if(b.sqrTo(c,d),0<(a&1<<f))b.mulTo(d,e,c);else var h=c,c=d,d=h;return b.revert(c)}
-function bnModPowInt(a,b){var c;c=256>a||b.isEven()?new Classic(b):new Montgomery(b);return this.exp(a,c)}BigInteger.prototype.copyTo=bnpCopyTo;BigInteger.prototype.fromInt=bnpFromInt;BigInteger.prototype.fromString=bnpFromString;BigInteger.prototype.clamp=bnpClamp;BigInteger.prototype.dlShiftTo=bnpDLShiftTo;BigInteger.prototype.drShiftTo=bnpDRShiftTo;BigInteger.prototype.lShiftTo=bnpLShiftTo;BigInteger.prototype.rShiftTo=bnpRShiftTo;BigInteger.prototype.subTo=bnpSubTo;
-BigInteger.prototype.multiplyTo=bnpMultiplyTo;BigInteger.prototype.squareTo=bnpSquareTo;BigInteger.prototype.divRemTo=bnpDivRemTo;BigInteger.prototype.invDigit=bnpInvDigit;BigInteger.prototype.isEven=bnpIsEven;BigInteger.prototype.exp=bnpExp;BigInteger.prototype.toString=bnToString;BigInteger.prototype.negate=bnNegate;BigInteger.prototype.abs=bnAbs;BigInteger.prototype.compareTo=bnCompareTo;BigInteger.prototype.bitLength=bnBitLength;BigInteger.prototype.mod=bnMod;BigInteger.prototype.modPowInt=bnModPowInt;
-BigInteger.ZERO=nbv(0);BigInteger.ONE=nbv(1);
-function Elgamal(){this.encrypt=function(a,b,c,d){var e=BigInteger.ONE.add(BigInteger.ONE),f=c.subtract(e),e=openpgp_crypto_getRandomBigIntegerInRange(e,f),e=e.mod(f).add(BigInteger.ONE),f=[];f[0]=b.modPow(e,c);f[1]=d.modPow(e,c).multiply(a).mod(c).toMPI();f[0]=f[0].toMPI();return f};this.decrypt=function(a,b,c,d){util.print_debug("Elgamal Decrypt:\nc1:"+util.hexstrdump(a.toMPI())+"\nc2:"+util.hexstrdump(b.toMPI())+"\np:"+util.hexstrdump(c.toMPI())+"\nx:"+util.hexstrdump(d.toMPI()));return a.modPow(d,
-c).modInverse(c).multiply(b).mod(c)}}function bnClone(){var a=nbi();this.copyTo(a);return a}function bnIntValue(){if(0>this.s){if(1==this.t)return this[0]-this.DV;if(0==this.t)return-1}else{if(1==this.t)return this[0];if(0==this.t)return 0}return(this[1]&(1<<32-this.DB)-1)<<this.DB|this[0]}function bnByteValue(){return 0==this.t?this.s:this[0]<<24>>24}function bnShortValue(){return 0==this.t?this.s:this[0]<<16>>16}function bnpChunkSize(a){return Math.floor(Math.LN2*this.DB/Math.log(a))}
-function bnSigNum(){return 0>this.s?-1:0>=this.t||1==this.t&&0>=this[0]?0:1}function bnpToRadix(a){null==a&&(a=10);if(0==this.signum()||2>a||36<a)return"0";var b=this.chunkSize(a),b=Math.pow(a,b),c=nbv(b),d=nbi(),e=nbi(),f="";for(this.divRemTo(c,d,e);0<d.signum();)f=(b+e.intValue()).toString(a).substr(1)+f,d.divRemTo(c,d,e);return e.intValue().toString(a)+f}
-function bnpFromRadix(a,b){this.fromInt(0);null==b&&(b=10);for(var c=this.chunkSize(b),d=Math.pow(b,c),e=!1,f=0,h=0,g=0;g<a.length;++g){var k=intAt(a,g);0>k?"-"==a.charAt(g)&&0==this.signum()&&(e=!0):(h=b*h+k,++f>=c&&(this.dMultiply(d),this.dAddOffset(h,0),h=f=0))}0<f&&(this.dMultiply(Math.pow(b,f)),this.dAddOffset(h,0));e&&BigInteger.ZERO.subTo(this,this)}
-function bnpFromNumber(a,b,c){if("number"==typeof b)if(2>a)this.fromInt(1);else{this.fromNumber(a,c);this.testBit(a-1)||this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);for(this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(b);)this.dAddOffset(2,0),this.bitLength()>a&&this.subTo(BigInteger.ONE.shiftLeft(a-1),this)}else{var c=[],d=a&7;c.length=(a>>3)+1;b.nextBytes(c);c[0]=0<d?c[0]&(1<<d)-1:0;this.fromString(c,256)}}
-function bnToByteArray(){var a=this.t,b=[];b[0]=this.s;var c=this.DB-a*this.DB%8,d,e=0;if(0<a--){if(c<this.DB&&(d=this[a]>>c)!=(this.s&this.DM)>>c)b[e++]=d|this.s<<this.DB-c;for(;0<=a;)if(8>c?(d=(this[a]&(1<<c)-1)<<8-c,d|=this[--a]>>(c+=this.DB-8)):(d=this[a]>>(c-=8)&255,0>=c&&(c+=this.DB,--a)),0<e||d!=this.s)b[e++]=d}return b}function bnEquals(a){return 0==this.compareTo(a)}function bnMin(a){return 0>this.compareTo(a)?this:a}function bnMax(a){return 0<this.compareTo(a)?this:a}
-function bnpBitwiseTo(a,b,c){var d,e,f=Math.min(a.t,this.t);for(d=0;d<f;++d)c[d]=b(this[d],a[d]);if(a.t<this.t){e=a.s&this.DM;for(d=f;d<this.t;++d)c[d]=b(this[d],e);c.t=this.t}else{e=this.s&this.DM;for(d=f;d<a.t;++d)c[d]=b(e,a[d]);c.t=a.t}c.s=b(this.s,a.s);c.clamp()}function op_and(a,b){return a&b}function bnAnd(a){var b=nbi();this.bitwiseTo(a,op_and,b);return b}function op_or(a,b){return a|b}function bnOr(a){var b=nbi();this.bitwiseTo(a,op_or,b);return b}function op_xor(a,b){return a^b}
-function bnXor(a){var b=nbi();this.bitwiseTo(a,op_xor,b);return b}function op_andnot(a,b){return a&~b}function bnAndNot(a){var b=nbi();this.bitwiseTo(a,op_andnot,b);return b}function bnNot(){for(var a=nbi(),b=0;b<this.t;++b)a[b]=this.DM&~this[b];a.t=this.t;a.s=~this.s;return a}function bnShiftLeft(a){var b=nbi();0>a?this.rShiftTo(-a,b):this.lShiftTo(a,b);return b}function bnShiftRight(a){var b=nbi();0>a?this.lShiftTo(-a,b):this.rShiftTo(a,b);return b}
-function lbit(a){if(0==a)return-1;var b=0;0==(a&65535)&&(a>>=16,b+=16);0==(a&255)&&(a>>=8,b+=8);0==(a&15)&&(a>>=4,b+=4);0==(a&3)&&(a>>=2,b+=2);0==(a&1)&&++b;return b}function bnGetLowestSetBit(){for(var a=0;a<this.t;++a)if(0!=this[a])return a*this.DB+lbit(this[a]);return 0>this.s?this.t*this.DB:-1}function cbit(a){for(var b=0;0!=a;)a&=a-1,++b;return b}function bnBitCount(){for(var a=0,b=this.s&this.DM,c=0;c<this.t;++c)a+=cbit(this[c]^b);return a}
-function bnTestBit(a){var b=Math.floor(a/this.DB);return b>=this.t?0!=this.s:0!=(this[b]&1<<a%this.DB)}function bnpChangeBit(a,b){var c=BigInteger.ONE.shiftLeft(a);this.bitwiseTo(c,b,c);return c}function bnSetBit(a){return this.changeBit(a,op_or)}function bnClearBit(a){return this.changeBit(a,op_andnot)}function bnFlipBit(a){return this.changeBit(a,op_xor)}
-function bnpAddTo(a,b){for(var c=0,d=0,e=Math.min(a.t,this.t);c<e;)d+=this[c]+a[c],b[c++]=d&this.DM,d>>=this.DB;if(a.t<this.t){for(d+=a.s;c<this.t;)d+=this[c],b[c++]=d&this.DM,d>>=this.DB;d+=this.s}else{for(d+=this.s;c<a.t;)d+=a[c],b[c++]=d&this.DM,d>>=this.DB;d+=a.s}b.s=0>d?-1:0;0<d?b[c++]=d:-1>d&&(b[c++]=this.DV+d);b.t=c;b.clamp()}function bnAdd(a){var b=nbi();this.addTo(a,b);return b}function bnSubtract(a){var b=nbi();this.subTo(a,b);return b}
-function bnMultiply(a){var b=nbi();this.multiplyTo(a,b);return b}function bnSquare(){var a=nbi();this.squareTo(a);return a}function bnDivide(a){var b=nbi();this.divRemTo(a,b,null);return b}function bnRemainder(a){var b=nbi();this.divRemTo(a,null,b);return b}function bnDivideAndRemainder(a){var b=nbi(),c=nbi();this.divRemTo(a,b,c);return[b,c]}function bnpDMultiply(a){this[this.t]=this.am(0,a-1,this,0,0,this.t);++this.t;this.clamp()}
-function bnpDAddOffset(a,b){if(0!=a){for(;this.t<=b;)this[this.t++]=0;for(this[b]+=a;this[b]>=this.DV;)this[b]-=this.DV,++b>=this.t&&(this[this.t++]=0),++this[b]}}function NullExp(){}function nNop(a){return a}function nMulTo(a,b,c){a.multiplyTo(b,c)}function nSqrTo(a,b){a.squareTo(b)}NullExp.prototype.convert=nNop;NullExp.prototype.revert=nNop;NullExp.prototype.mulTo=nMulTo;NullExp.prototype.sqrTo=nSqrTo;function bnPow(a){return this.exp(a,new NullExp)}
-function bnpMultiplyLowerTo(a,b,c){var d=Math.min(this.t+a.t,b);c.s=0;for(c.t=d;0<d;)c[--d]=0;var e;for(e=c.t-this.t;d<e;++d)c[d+this.t]=this.am(0,a[d],c,d,0,this.t);for(e=Math.min(a.t,b);d<e;++d)this.am(0,a[d],c,d,0,b-d);c.clamp()}function bnpMultiplyUpperTo(a,b,c){--b;var d=c.t=this.t+a.t-b;for(c.s=0;0<=--d;)c[d]=0;for(d=Math.max(b-this.t,0);d<a.t;++d)c[this.t+d-b]=this.am(b-d,a[d],c,0,0,this.t+d-b);c.clamp();c.drShiftTo(1,c)}
-function Barrett(a){this.r2=nbi();this.q3=nbi();BigInteger.ONE.dlShiftTo(2*a.t,this.r2);this.mu=this.r2.divide(a);this.m=a}function barrettConvert(a){if(0>a.s||a.t>2*this.m.t)return a.mod(this.m);if(0>a.compareTo(this.m))return a;var b=nbi();a.copyTo(b);this.reduce(b);return b}function barrettRevert(a){return a}
-function barrettReduce(a){a.drShiftTo(this.m.t-1,this.r2);if(a.t>this.m.t+1)a.t=this.m.t+1,a.clamp();this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);for(this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);0>a.compareTo(this.r2);)a.dAddOffset(1,this.m.t+1);for(a.subTo(this.r2,a);0<=a.compareTo(this.m);)a.subTo(this.m,a)}function barrettSqrTo(a,b){a.squareTo(b);this.reduce(b)}function barrettMulTo(a,b,c){a.multiplyTo(b,c);this.reduce(c)}Barrett.prototype.convert=barrettConvert;
-Barrett.prototype.revert=barrettRevert;Barrett.prototype.reduce=barrettReduce;Barrett.prototype.mulTo=barrettMulTo;Barrett.prototype.sqrTo=barrettSqrTo;
-function bnModPow(a,b){var c=a.bitLength(),d,e=nbv(1),f;if(0>=c)return e;d=18>c?1:48>c?3:144>c?4:768>c?5:6;f=8>c?new Classic(b):b.isEven()?new Barrett(b):new Montgomery(b);var h=[],g=3,k=d-1,j=(1<<d)-1;h[1]=f.convert(this);if(1<d){c=nbi();for(f.sqrTo(h[1],c);g<=j;)h[g]=nbi(),f.mulTo(c,h[g-2],h[g]),g+=2}for(var l=a.t-1,q,u=!0,m=nbi(),c=nbits(a[l])-1;0<=l;){c>=k?q=a[l]>>c-k&j:(q=(a[l]&(1<<c+1)-1)<<k-c,0<l&&(q|=a[l-1]>>this.DB+c-k));for(g=d;0==(q&1);)q>>=1,--g;if(0>(c-=g))c+=this.DB,--l;if(u)h[q].copyTo(e),
-u=!1;else{for(;1<g;)f.sqrTo(e,m),f.sqrTo(m,e),g-=2;0<g?f.sqrTo(e,m):(g=e,e=m,m=g);f.mulTo(m,h[q],e)}for(;0<=l&&0==(a[l]&1<<c);)f.sqrTo(e,m),g=e,e=m,m=g,0>--c&&(c=this.DB-1,--l)}return f.revert(e)}
-function bnGCD(a){var b=0>this.s?this.negate():this.clone(),a=0>a.s?a.negate():a.clone();if(0>b.compareTo(a))var c=b,b=a,a=c;var c=b.getLowestSetBit(),d=a.getLowestSetBit();if(0>d)return b;c<d&&(d=c);0<d&&(b.rShiftTo(d,b),a.rShiftTo(d,a));for(;0<b.signum();)0<(c=b.getLowestSetBit())&&b.rShiftTo(c,b),0<(c=a.getLowestSetBit())&&a.rShiftTo(c,a),0<=b.compareTo(a)?(b.subTo(a,b),b.rShiftTo(1,b)):(a.subTo(b,a),a.rShiftTo(1,a));0<d&&a.lShiftTo(d,a);return a}
-function bnpModInt(a){if(0>=a)return 0;var b=this.DV%a,c=0>this.s?a-1:0;if(0<this.t)if(0==b)c=this[0]%a;else for(var d=this.t-1;0<=d;--d)c=(b*c+this[d])%a;return c}
-function bnModInverse(a){var b=a.isEven();if(this.isEven()&&b||0==a.signum())return BigInteger.ZERO;for(var c=a.clone(),d=this.clone(),e=nbv(1),f=nbv(0),h=nbv(0),g=nbv(1);0!=c.signum();){for(;c.isEven();){c.rShiftTo(1,c);if(b){if(!e.isEven()||!f.isEven())e.addTo(this,e),f.subTo(a,f);e.rShiftTo(1,e)}else f.isEven()||f.subTo(a,f);f.rShiftTo(1,f)}for(;d.isEven();){d.rShiftTo(1,d);if(b){if(!h.isEven()||!g.isEven())h.addTo(this,h),g.subTo(a,g);h.rShiftTo(1,h)}else g.isEven()||g.subTo(a,g);g.rShiftTo(1,
-g)}0<=c.compareTo(d)?(c.subTo(d,c),b&&e.subTo(h,e),f.subTo(g,f)):(d.subTo(c,d),b&&h.subTo(e,h),g.subTo(f,g))}if(0!=d.compareTo(BigInteger.ONE))return BigInteger.ZERO;if(0<=g.compareTo(a))return g.subtract(a);if(0>g.signum())g.addTo(a,g);else return g;return 0>g.signum()?g.add(a):g}
-var lowprimes=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,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],lplim=67108864/lowprimes[lowprimes.length-1];
-function bnIsProbablePrime(a){var b,c=this.abs();if(1==c.t&&c[0]<=lowprimes[lowprimes.length-1]){for(b=0;b<lowprimes.length;++b)if(c[0]==lowprimes[b])return!0;return!1}if(c.isEven())return!1;for(b=1;b<lowprimes.length;){for(var d=lowprimes[b],e=b+1;e<lowprimes.length&&d<lplim;)d*=lowprimes[e++];for(d=c.modInt(d);b<e;)if(0==d%lowprimes[b++])return!1}return c.millerRabin(a)}
-function nbits(a){var b=1,c;if(0!=(c=a>>>16))a=c,b+=16;if(0!=(c=a>>8))a=c,b+=8;if(0!=(c=a>>4))a=c,b+=4;if(0!=(c=a>>2))a=c,b+=2;0!=a>>1&&(b+=1);return b}function bnToMPI(){var a=this.toByteArray(),b=8*(a.length-1)+nbits(a[0]),c;c=""+String.fromCharCode((b&65280)>>8);c+=String.fromCharCode(b&255);return c+=util.bin2str(a)}
-function bnpMillerRabin(a){var b=this.subtract(BigInteger.ONE),c=b.getLowestSetBit();if(0>=c)return!1;var d=b.shiftRight(c),a=a+1>>1;if(a>lowprimes.length)a=lowprimes.length;for(var e=nbi(),f=0;f<a;++f){e.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);var h=e.modPow(d,this);if(0!=h.compareTo(BigInteger.ONE)&&0!=h.compareTo(b)){for(var g=1;g++<c&&0!=h.compareTo(b);)if(h=h.modPowInt(2,this),0==h.compareTo(BigInteger.ONE))return!1;if(0!=h.compareTo(b))return!1}}return!0}
-BigInteger.prototype.chunkSize=bnpChunkSize;BigInteger.prototype.toRadix=bnpToRadix;BigInteger.prototype.fromRadix=bnpFromRadix;BigInteger.prototype.fromNumber=bnpFromNumber;BigInteger.prototype.bitwiseTo=bnpBitwiseTo;BigInteger.prototype.changeBit=bnpChangeBit;BigInteger.prototype.addTo=bnpAddTo;BigInteger.prototype.dMultiply=bnpDMultiply;BigInteger.prototype.dAddOffset=bnpDAddOffset;BigInteger.prototype.multiplyLowerTo=bnpMultiplyLowerTo;BigInteger.prototype.multiplyUpperTo=bnpMultiplyUpperTo;
-BigInteger.prototype.modInt=bnpModInt;BigInteger.prototype.millerRabin=bnpMillerRabin;BigInteger.prototype.clone=bnClone;BigInteger.prototype.intValue=bnIntValue;BigInteger.prototype.byteValue=bnByteValue;BigInteger.prototype.shortValue=bnShortValue;BigInteger.prototype.signum=bnSigNum;BigInteger.prototype.toByteArray=bnToByteArray;BigInteger.prototype.equals=bnEquals;BigInteger.prototype.min=bnMin;BigInteger.prototype.max=bnMax;BigInteger.prototype.and=bnAnd;BigInteger.prototype.or=bnOr;
-BigInteger.prototype.xor=bnXor;BigInteger.prototype.andNot=bnAndNot;BigInteger.prototype.not=bnNot;BigInteger.prototype.shiftLeft=bnShiftLeft;BigInteger.prototype.shiftRight=bnShiftRight;BigInteger.prototype.getLowestSetBit=bnGetLowestSetBit;BigInteger.prototype.bitCount=bnBitCount;BigInteger.prototype.testBit=bnTestBit;BigInteger.prototype.setBit=bnSetBit;BigInteger.prototype.clearBit=bnClearBit;BigInteger.prototype.flipBit=bnFlipBit;BigInteger.prototype.add=bnAdd;BigInteger.prototype.subtract=bnSubtract;
-BigInteger.prototype.multiply=bnMultiply;BigInteger.prototype.divide=bnDivide;BigInteger.prototype.remainder=bnRemainder;BigInteger.prototype.divideAndRemainder=bnDivideAndRemainder;BigInteger.prototype.modPow=bnModPow;BigInteger.prototype.modInverse=bnModInverse;BigInteger.prototype.pow=bnPow;BigInteger.prototype.gcd=bnGCD;BigInteger.prototype.isProbablePrime=bnIsProbablePrime;BigInteger.prototype.toMPI=bnToMPI;BigInteger.prototype.square=bnSquare;
-function openpgp_crypto_symmetricEncrypt(a,b,c,d,e){switch(b){case 0:return d;case 2:return openpgp_cfb_encrypt(a,desede,d,8,c,e).substring(0,d.length+10);case 3:return openpgp_cfb_encrypt(a,cast5_encrypt,d,8,c,e).substring(0,d.length+10);case 4:return openpgp_cfb_encrypt(a,BFencrypt,d,8,c,e).substring(0,d.length+10);case 7:case 8:case 9:return openpgp_cfb_encrypt(a,AESencrypt,d,16,keyExpansion(c),e).substring(0,d.length+18);case 10:return openpgp_cfb_encrypt(a,TFencrypt,d,16,c,e).substring(0,d.length+
-18);case 1:return util.print_error("IDEA Algorithm not implemented"),null;default:return null}}
-function openpgp_crypto_symmetricDecrypt(a,b,c,d){util.print_debug_hexstr_dump("openpgp_crypto_symmetricDecrypt:\nalgo:"+a+"\nencrypteddata:",c);var e=0;d||(e=2);switch(a){case 0:return c;case 2:return openpgp_cfb_decrypt(desede,8,b,c,d).substring(e,c.length+e-10);case 3:return openpgp_cfb_decrypt(cast5_encrypt,8,b,c,d).substring(e,c.length+e-10);case 4:return openpgp_cfb_decrypt(BFencrypt,8,b,c,d).substring(e,c.length+e-10);case 7:case 8:case 9:return openpgp_cfb_decrypt(AESencrypt,16,keyExpansion(b),
-c,d).substring(e,c.length+e-18);case 10:return openpgp_cfb_decrypt(TFencrypt,16,b,c,d).substring(e,c.length+e-18);case 1:util.print_error(""+(1==a?"IDEA Algorithm not implemented":"Twofish Algorithm not implemented"))}return null}
-function openpgp_cfb_encrypt(a,b,c,d,e,f){var h=Array(d),g=Array(d),a=a+a.charAt(d-2)+a.charAt(d-1);util.print_debug("prefixrandom:"+util.hexstrdump(a));for(var k="",j=0;j<d;j++)h[j]=0;g=b(h,e);for(j=0;j<d;j++)k+=String.fromCharCode(g[j]^a.charCodeAt(j));for(j=0;j<d;j++)h[j]=k.charCodeAt(j);g=b(h,e);k+=String.fromCharCode(g[0]^a.charCodeAt(d));k+=String.fromCharCode(g[1]^a.charCodeAt(d+1));if(f)for(j=0;j<d;j++)h[j]=k.charCodeAt(j+2);else for(j=0;j<d;j++)h[j]=k.charCodeAt(j);g=b(h,e);if(f){for(j=0;j<
-d;j++)k+=String.fromCharCode(g[j]^c.charCodeAt(j));for(n=d+2;n<c.length;n+=d){for(j=0;j<d;j++)h[j]=k.charCodeAt(n+j);g=b(h,e);for(j=0;j<d;j++)k+=String.fromCharCode(g[j]^c.charCodeAt(n-2+j))}}else{c="  "+c;for(j=2;j<d;j++)k+=String.fromCharCode(g[j]^c.charCodeAt(j));a=k.substring(0,2*d).split("");k=k.substring(d);for(n=d;n<c.length;n+=d){for(j=0;j<d;j++)h[j]=k.charCodeAt(j);k="";g=b(h,e);for(j=0;j<d;j++)a.push(String.fromCharCode(g[j]^c.charCodeAt(n+j))),k+=String.fromCharCode(g[j]^c.charCodeAt(n+
-j))}k=a.join("")}return k}function openpgp_cfb_mdc(a,b,c,d){var e=Array(b),f=Array(b),h;for(h=0;h<b;h++)e[h]=0;e=a(e,c);for(h=0;h<b;h++)f[h]=d.charCodeAt(h),e[h]^=f[h];f=a(f,c);return util.bin2str(e)+String.fromCharCode(f[0]^d.charCodeAt(b))+String.fromCharCode(f[1]^d.charCodeAt(b+1))}
-function openpgp_cfb_decrypt(a,b,c,d,e){util.print_debug("resync:"+e);var f=Array(b),h=Array(b),g,k="",j=[];for(g=0;g<b;g++)f[g]=0;f=a(f,c);for(g=0;g<b;g++)h[g]=d.charCodeAt(g),f[g]^=h[g];h=a(h,c);util.print_debug("openpgp_cfb_decrypt:\niblock:"+util.hexidump(f)+"\nablock:"+util.hexidump(h)+"\n");util.print_debug((h[0]^d.charCodeAt(b)).toString(16)+(h[1]^d.charCodeAt(b+1)).toString(16));if(f[b-2]!=(h[0]^d.charCodeAt(b))||f[b-1]!=(h[1]^d.charCodeAt(b+1)))return util.print_eror("error duding decryption. Symmectric encrypted data not valid."),
-j.join("");if(e){for(g=0;g<b;g++)f[g]=d.charCodeAt(g+2);k=b+2}else{for(g=0;g<b;g++)f[g]=d.charCodeAt(g);k=b}for(;k<d.length;k+=b){h=a(f,c);for(g=0;g<b&&g+k<d.length;g++)f[g]=d.charCodeAt(k+g),j.push(String.fromCharCode(h[g]^f[g]))}return j.join("")}
-function normal_cfb_encrypt(a,b,c,d,e){for(var f="",f="",h=0,g=[],k=[],f=e.substring(0,b);d.length>b*h;){for(var e=a(f,c),f=d.substring(h*b,h*b+b),j=0;j<f.length;j++)k.push(String.fromCharCode(f.charCodeAt(j)^e[j]));f=k.join("");k=[];g.push(f);h++}return g.join("")}
-function normal_cfb_decrypt(a,b,c,d,e){var f="",h=0,g=[];if(null==e)for(e=0;e<b;e++)f+=String.fromCharCode(0);else f=e.substring(0,b);for(;d.length>b*h;){for(var k=a(f,c),f=d.substring(h*b+0,h*b+b+0),e=0;e<f.length;e++)g.push(String.fromCharCode(f.charCodeAt(e)^k[e]));h++}return g.join("")}
-function openpgp_crypto_asymetricEncrypt(a,b,c){switch(a){case 1:case 2:case 3:var a=new RSA,d=b[0].toBigInteger(),b=b[1].toBigInteger(),c=c.toBigInteger();return a.encrypt(c,b,d).toMPI();case 16:var a=new Elgamal,d=b[0].toBigInteger(),e=b[1].toBigInteger(),b=b[2].toBigInteger(),c=c.toBigInteger();return a.encrypt(c,e,d,b);default:return null}}
-function openpgp_crypto_asymetricDecrypt(a,b,c,d){switch(a){case 1:case 2:case 3:var a=new RSA,e=c[0].toBigInteger(),b=c[1].toBigInteger(),f=c[2].toBigInteger(),c=c[3].toBigInteger(),d=d[0].toBigInteger();return a.decrypt(d,e,b,f,c);case 16:return a=new Elgamal,c=c[0].toBigInteger(),e=d[0].toBigInteger(),d=d[1].toBigInteger(),b=b[0].toBigInteger(),a.decrypt(e,d,b,c);default:return null}}
-function openpgp_crypto_getPrefixRandom(a){switch(a){case 2:case 3:case 4:return openpgp_crypto_getRandomBytes(8);case 7:case 8:case 9:case 10:return openpgp_crypto_getRandomBytes(16);default:return null}}
-function openpgp_crypto_MDCSystemBytes(a,b,c){util.print_debug_hexstr_dump("openpgp_crypto_symmetricDecrypt:\nencrypteddata:",c);switch(a){case 0:return c;case 2:return openpgp_cfb_mdc(desede,8,b,c,openpgp_cfb);case 3:return openpgp_cfb_mdc(cast5_encrypt,8,b,c);case 4:return openpgp_cfb_mdc(BFencrypt,8,b,c);case 7:case 8:case 9:return openpgp_cfb_mdc(AESencrypt,16,keyExpansion(b),c);case 10:return openpgp_cfb_mdc(TFencrypt,16,b,c);case 1:util.print_error(""+(1==a?"IDEA Algorithm not implemented":
-"Twofish Algorithm not implemented"))}return null}function openpgp_crypto_generateSessionKey(a){switch(a){case 2:case 8:return openpgp_crypto_getRandomBytes(24);case 3:case 4:case 7:return util.print_debug("length = 16:\n"+util.hexstrdump(openpgp_crypto_getRandomBytes(16))),openpgp_crypto_getRandomBytes(16);case 9:case 10:return openpgp_crypto_getRandomBytes(32)}return null}
-function openpgp_crypto_verifySignature(a,b,c,d,e){var f=openpgp_crypto_hashData(b,e);switch(a){case 1:case 2:case 3:e=new RSA;a=d[0].toBigInteger();d=d[1].toBigInteger();c=c[0].toBigInteger();d=e.verify(c,d,a);b=openpgp_encoding_emsa_pkcs1_decode(b,d.toMPI().substring(2));return-1==b?(util.print_error("PKCS1 padding in message or key incorrect. Aborting..."),!1):b==f;case 16:return util.print_error("signing with Elgamal is not defined in the OpenPGP standard."),null;case 17:var a=new DSA,f=c[0].toBigInteger(),
-c=c[1].toBigInteger(),h=d[0].toBigInteger(),g=d[1].toBigInteger(),k=d[2].toBigInteger(),d=d[3].toBigInteger(),d=a.verify(b,f,c,e,h,g,k,d);return 0==d.compareTo(f);default:return null}}
-function openpgp_crypto_signData(a,b,c,d,e){switch(b){case 1:case 2:case 3:var b=new RSA,d=d[0].toBigInteger(),f=c[0].toBigInteger(),a=openpgp_encoding_emsa_pkcs1_encode(a,e,c[0].mpiByteLength);util.print_debug("signing using RSA");return b.sign(a,d,f).toMPI();case 17:b=new DSA;util.print_debug("DSA Sign: q size in Bytes:"+c[1].getByteLength());var f=c[0].toBigInteger(),h=c[1].toBigInteger(),g=c[2].toBigInteger();c[3].toBigInteger();c=d[0].toBigInteger();a=b.sign(a,e,g,f,h,c);util.print_debug("signing using DSA\n result:"+
-util.hexstrdump(a[0])+"|"+util.hexstrdump(a[1]));return a[0]+a[1];case 16:return util.print_debug("signing with Elgamal is not defined in the OpenPGP standard."),null;default:return null}}function openpgp_crypto_hashData(a,b){var c=null;switch(a){case 1:c=MD5(b);break;case 2:c=str_sha1(b);break;case 3:c=RMDstring(b);break;case 8:c=str_sha256(b);break;case 9:c=str_sha384(b);break;case 10:c=str_sha512(b);break;case 11:c=str_sha224(b)}return c}
-function openpgp_crypto_getHashByteLength(a){switch(a){case 1:return 16;case 2:case 3:return 20;case 8:return 32;case 9:return 48;case 10:return 64;case 11:return 28}return null}function openpgp_crypto_getRandomBytes(a){for(var b="",c=0;c<a;c++)b+=String.fromCharCode(openpgp_crypto_getSecureRandomOctet());return b}function openpgp_crypto_getPseudoRandom(a,b){return Math.round(Math.random()*(b-a))+a}
-function openpgp_crypto_getSecureRandom(a,b){var c=new Uint32Array(1);window.crypto.getRandomValues(c);for(var d=(b-a).toString(2).length;(c[0]&Math.pow(2,d)-1)>b-a;)window.crypto.getRandomValues(c);return a+Math.abs(c[0]&Math.pow(2,d)-1)}function openpgp_crypto_getSecureRandomOctet(){var a=new Uint32Array(1);window.crypto.getRandomValues(a);return a[0]&255}
-function openpgp_crypto_getRandomBigInteger(a){if(0>a)return null;var b=openpgp_crypto_getRandomBytes(Math.floor((a+7)/8));0<a%8&&(b=String.fromCharCode(Math.pow(2,a%8)-1&b.charCodeAt(0))+b.substring(1));return(new openpgp_type_mpi).create(b).toBigInteger()}function openpgp_crypto_getRandomBigIntegerInRange(a,b){if(!(0>=b.compareTo(a))){for(var c=b.subtract(a),d=openpgp_crypto_getRandomBigInteger(c.bitLength());d>c;)d=openpgp_crypto_getRandomBigInteger(c.bitLength());return a.add(d)}}
-function openpgp_crypto_testRSA(a){debugger;var b=new RSA,c=new openpgp_type_mpi;c.create(openpgp_encoding_eme_pkcs1_encode("ABABABAB",128));c=b.encrypt(c.toBigInteger(),a.ee,a.n);b.decrypt(c,a.d,a.p,a.q,a.u)}
-function openpgp_crypto_generateKeyPair(a,b,c,d,e){var f,h,g=new Date,g=g.getTime()/1E3,g=String.fromCharCode(Math.floor(g/16777216%256))+String.fromCharCode(Math.floor(g/65536%256))+String.fromCharCode(Math.floor(g/256%256))+String.fromCharCode(Math.floor(g%256));switch(a){case 1:b=(new RSA).generate(b,"10001");f=(new openpgp_packet_keymaterial).write_private_key(a,b,c,d,e,g);h=(new openpgp_packet_keymaterial).write_public_key(a,b,g);break;default:util.print_error("Unknown keytype "+a)}return{privateKey:f,
-publicKey:h}}
-function _openpgp(){this.tostring="";this.generate_key_pair=function(a,b,c,d){var e=(new openpgp_packet_userid).write_packet(c),b=openpgp_crypto_generateKeyPair(a,b,d,openpgp.config.config.prefer_hash_algorithm,3),a=b.privateKey,f=(new openpgp_packet_keymaterial).read_priv_key(a.string,3,a.string.length);f.decryptSecretMPIs(d)||util.print_error("Issue creating key. Unable to read resulting private key");d=new openpgp_msg_privatekey;d.privateKeyPacket=f;d.getPreferredSignatureHashAlgorithm=function(){return openpgp.config.config.prefer_hash_algorithm};
-f=d.privateKeyPacket.publicKey.data;f=String.fromCharCode(153)+String.fromCharCode(f.length>>8&255)+String.fromCharCode(f.length&255)+f+String.fromCharCode(180)+String.fromCharCode(c.length>>24)+String.fromCharCode(c.length>>16&255)+String.fromCharCode(c.length>>8&255)+String.fromCharCode(c.length&255)+c;c=new openpgp_packet_signature;c=c.write_message_signature(16,f,d);b=openpgp_encoding_armor(4,b.publicKey.string+e+c.openpgp);e=openpgp_encoding_armor(5,a.string+e+c.openpgp);return{privateKey:d,
-privateKeyArmored:e,publicKeyArmored:b}};this.write_signed_message=function(a,b){var c=(new openpgp_packet_signature).write_message_signature(1,b.replace(/\r\n/g,"\n").replace(/\n/,"\r\n"),a),c={text:b.replace(/\r\n/g,"\n").replace(/\n/,"\r\n"),openpgp:c.openpgp,hash:c.hash};return openpgp_encoding_armor(2,c,null,null)};this.write_signed_and_encrypted_message=function(a,b,c){var d="",e=(new openpgp_packet_literaldata).write_packet(c.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"));util.print_debug_hexstr_dump("literal_packet: |"+
-e+"|\n",e);for(var f=0;f<b.length;f++){var h="",h=(new openpgp_packet_onepasssignature).write_packet(1,openpgp.config.config.prefer_hash_algorithm,a,!1);util.print_debug_hexstr_dump("onepasssigstr: |"+h+"|\n",h);var g=(new openpgp_packet_signature).write_message_signature(1,c.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"),a);util.print_debug_hexstr_dump("datasignature: |"+g.openpgp+"|\n",g.openpgp);d=0==f?h+e+g.openpgp:h+d+g.openpgp}util.print_debug_hexstr_dump("signed packet: |"+d+"|\n",d);a=openpgp_crypto_generateSessionKey(openpgp.config.config.encryption_cipher);
-c="";for(f=0;f<b.length;f++){e=b[f].getEncryptionKey();if(null==e)return util.print_error("no encryption key found! Key is for signing only."),null;c+=(new openpgp_packet_encryptedsessionkey).write_pub_key_packet(e.getKeyId(),e.MPIs,e.publicKeyAlgorithm,openpgp.config.config.encryption_cipher,a)}c=openpgp.config.config.integrity_protect?c+(new openpgp_packet_encryptedintegrityprotecteddata).write_packet(openpgp.config.config.encryption_cipher,a,d):c+(new openpgp_packet_encrypteddata).write_packet(openpgp.config.config.encryption_cipher,
-a,d);return openpgp_encoding_armor(3,c,null,null)};this.write_encrypted_message=function(a,b){var c="",c=(new openpgp_packet_literaldata).write_packet(b.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"));util.print_debug_hexstr_dump("literal_packet: |"+c+"|\n",c);for(var d=openpgp_crypto_generateSessionKey(openpgp.config.config.encryption_cipher),e="",f=0;f<a.length;f++){var h=a[f].getEncryptionKey();if(null==h)return util.print_error("no encryption key found! Key is for signing only."),null;e+=(new openpgp_packet_encryptedsessionkey).write_pub_key_packet(h.getKeyId(),
-h.MPIs,h.publicKeyAlgorithm,openpgp.config.config.encryption_cipher,d)}e=openpgp.config.config.integrity_protect?e+(new openpgp_packet_encryptedintegrityprotecteddata).write_packet(openpgp.config.config.encryption_cipher,d,c):e+(new openpgp_packet_encrypteddata).write_packet(openpgp.config.config.encryption_cipher,d,c);return openpgp_encoding_armor(3,e,null,null)};this.read_message=function(a){var b;try{b=openpgp_encoding_deArmor(a.replace(/\r/g,""))}catch(c){return util.print_error("no message found!"),
-null}for(var a=b.openpgp,d=[],e=0,f=0,h=a.length;f<a.length;){var g=openpgp_packet.read_packet(a,f,h);if(1==g.tagType||2==g.tagType&&16>g.signatureType||3==g.tagType||8==g.tagType||9==g.tagType||10==g.tagType||11==g.tagType||18==g.tagType||19==g.tagType)if(d[d.length]=new openpgp_msg_message,d[e].messagePacket=g,d[e].type=b.type,9==g.tagType||1==g.tagType||3==g.tagType||18==g.tagType)if(9==g.tagType){util.print_error("unexpected openpgp packet");break}else if(1==g.tagType){util.print_debug("session key found:\n "+
-g.toString());var k=!0;d[e].sessionKeys=[];for(var j=0;k;)d[e].sessionKeys[j]=g,f+=g.packetLength+g.headerLength,h-=g.packetLength+g.headerLength,g=openpgp_packet.read_packet(a,f,h),1!=g.tagType&&3!=g.tagType&&(k=!1),j++;18==g.tagType||9==g.tagType?(util.print_debug("encrypted data found:\n "+g.toString()),d[e].encryptedData=g,f+=g.packetLength+g.headerLength,h-=g.packetLength+g.headerLength,e++):util.print_debug("something is wrong: "+g.tagType)}else{if(18==g.tagType){util.print_debug("symmetric encrypted data");
-break}}else if(2==g.tagType&&3>g.signatureType){d[e].text=b.text;d[e].signature=g;break}else if(8==g.tagType){util.print_error("A directly compressed message is currently not supported");break}else if(10==g.tagType)d.length=0,f+=g.packetLength+g.headerLength,h-=g.packetLength+g.headerLength;else{if(11==g.tagType){util.print_error("A direct literal message is currently not supported.");break}}else return util.print_error("no message found!"),null}return d};this.read_publicKey=function(a){for(var b=
-0,c=[],d=0,a=openpgp_encoding_deArmor(a.replace(/\r/g,"")).openpgp,e=a.length;b!=a.length;){var f=openpgp_packet.read_packet(a,b,e);if(153==a[b].charCodeAt()||6==f.tagType)c[d]=new openpgp_msg_publickey,c[d].header=a.substring(b,b+3),153==a[b].charCodeAt()?(b++,e=a[b++].charCodeAt()<<8|a[b++].charCodeAt(),c[d].publicKeyPacket=new openpgp_packet_keymaterial,c[d].publicKeyPacket.header=c[d].header,c[d].publicKeyPacket.read_tag6(a,b,e),b+=c[d].publicKeyPacket.packetLength,b+=c[d].read_nodes(c[d].publicKeyPacket,
-a,b,a.length-b)):(c[d]=new openpgp_msg_publickey,c[d].publicKeyPacket=f,b+=f.headerLength+f.packetLength,b+=c[d].read_nodes(f,a,b,a.length-b));else return util.print_error("no public key found!"),null;c[d].data=a.substring(0,b);d++}return c};this.read_privateKey=function(a){for(var b=[],c=0,d=0,a=openpgp_encoding_deArmor(a.replace(/\r/g,"")).openpgp,e=a.length;d!=a.length;){var f=openpgp_packet.read_packet(a,d,e);if(5==f.tagType)b[b.length]=new openpgp_msg_privatekey,d+=f.headerLength+f.packetLength,
-d+=b[c].read_nodes(f,a,d,e);else return util.print_error("no block packet found!"),null;b[c].data=a.substring(0,d);c++}return b};this.init=function(){this.config=new openpgp_config;this.config.read();this.keyring=new openpgp_keyring;this.keyring.init()}}var openpgp=new _openpgp;
+function AESencrypt(a,b){var c,d,e,f,g,h=packBytes(a),k=b.rounds,j=h[0],m=h[1],u=h[2];g=h[3];for(c=0;c<k-1;c++)d=j^b.rk[c][0],e=m^b.rk[c][1],f=u^b.rk[c][2],g^=b.rk[c][3],j=T1[d&255]^T2[e>>8&255]^T3[f>>16&255]^T4[g>>>24],m=T1[e&255]^T2[f>>8&255]^T3[g>>16&255]^T4[d>>>24],u=T1[f&255]^T2[g>>8&255]^T3[d>>16&255]^T4[e>>>24],g=T1[g&255]^T2[d>>8&255]^T3[e>>16&255]^T4[f>>>24];c=k-1;d=j^b.rk[c][0];e=m^b.rk[c][1];f=u^b.rk[c][2];g^=b.rk[c][3];h[0]=F1(d,e,f,g)^b.rk[k][0];h[1]=F1(e,f,g,d)^b.rk[k][1];h[2]=F1(f,
+g,d,e)^b.rk[k][2];h[3]=F1(g,d,e,f)^b.rk[k][3];return unpackBytes(h)}
+function openpgp_cfb_encrypt(a,b,c,d,e,f){var g=Array(d),h=Array(d),a=a+a.charAt(d-2)+a.charAt(d-1);util.print_debug("prefixrandom:"+util.hexstrdump(a));for(var k="",j=0;j<d;j++)g[j]=0;h=b(g,e);for(j=0;j<d;j++)k+=String.fromCharCode(h[j]^a.charCodeAt(j));for(j=0;j<d;j++)g[j]=k.charCodeAt(j);h=b(g,e);k+=String.fromCharCode(h[0]^a.charCodeAt(d));k+=String.fromCharCode(h[1]^a.charCodeAt(d+1));if(f)for(j=0;j<d;j++)g[j]=k.charCodeAt(j+2);else for(j=0;j<d;j++)g[j]=k.charCodeAt(j);h=b(g,e);if(f){for(j=0;j<
+d;j++)k+=String.fromCharCode(h[j]^c.charCodeAt(j));for(n=d+2;n<c.length;n+=d){for(j=0;j<d;j++)g[j]=k.charCodeAt(n+j);h=b(g,e);for(j=0;j<d;j++)k+=String.fromCharCode(h[j]^c.charCodeAt(n-2+j))}}else{c="  "+c;for(j=2;j<d;j++)k+=String.fromCharCode(h[j]^c.charCodeAt(j));a=k.substring(0,2*d).split("");k=k.substring(d);for(n=d;n<c.length;n+=d){for(j=0;j<d;j++)g[j]=k.charCodeAt(j);k="";h=b(g,e);for(j=0;j<d;j++)a.push(String.fromCharCode(h[j]^c.charCodeAt(n+j))),k+=String.fromCharCode(h[j]^c.charCodeAt(n+
+j))}k=a.join("")}return k}function openpgp_cfb_mdc(a,b,c,d){var e=Array(b),f=Array(b),g;for(g=0;g<b;g++)e[g]=0;e=a(e,c);for(g=0;g<b;g++)f[g]=d.charCodeAt(g),e[g]^=f[g];f=a(f,c);return util.bin2str(e)+String.fromCharCode(f[0]^d.charCodeAt(b))+String.fromCharCode(f[1]^d.charCodeAt(b+1))}
+function openpgp_cfb_decrypt(a,b,c,d,e){util.print_debug("resync:"+e);var f=Array(b),g=Array(b),h,k="",j=[];for(h=0;h<b;h++)f[h]=0;f=a(f,c);for(h=0;h<b;h++)g[h]=d.charCodeAt(h),f[h]^=g[h];g=a(g,c);util.print_debug("openpgp_cfb_decrypt:\niblock:"+util.hexidump(f)+"\nablock:"+util.hexidump(g)+"\n");util.print_debug((g[0]^d.charCodeAt(b)).toString(16)+(g[1]^d.charCodeAt(b+1)).toString(16));if(f[b-2]!=(g[0]^d.charCodeAt(b))||f[b-1]!=(g[1]^d.charCodeAt(b+1)))return util.print_eror("error duding decryption. Symmectric encrypted data not valid."),
+j.join("");if(e){for(h=0;h<b;h++)f[h]=d.charCodeAt(h+2);k=b+2}else{for(h=0;h<b;h++)f[h]=d.charCodeAt(h);k=b}for(;k<d.length;k+=b){g=a(f,c);for(h=0;h<b&&h+k<d.length;h++)f[h]=d.charCodeAt(k+h),j.push(String.fromCharCode(g[h]^f[h]))}return j.join("")}
+function normal_cfb_encrypt(a,b,c,d,e){for(var f="",f="",g=0,h=[],k=[],f=e.substring(0,b);d.length>b*g;){for(var e=a(f,c),f=d.substring(g*b,g*b+b),j=0;j<f.length;j++)k.push(String.fromCharCode(f.charCodeAt(j)^e[j]));f=k.join("");k=[];h.push(f);g++}return h.join("")}
+function normal_cfb_decrypt(a,b,c,d,e){var f="",g=0,h=[];if(null==e)for(e=0;e<b;e++)f+=String.fromCharCode(0);else f=e.substring(0,b);for(;d.length>b*g;){for(var k=a(f,c),f=d.substring(g*b+0,g*b+b+0),e=0;e<f.length;e++)h.push(String.fromCharCode(f.charCodeAt(e)^k[e]));g++}return h.join("")}
+var jsSHA=function(){var a=function(a,b){this.highOrder=a;this.lowOrder=b},b=function(a){var b=[],c=8*a.length,d;for(d=0;d<c;d+=8)b[d>>5]|=(a.charCodeAt(d/8)&255)<<24-d%32;return b},c=function(a){var b=[],c=a.length,d,e;for(d=0;d<c;d+=2){e=parseInt(a.substr(d,2),16);if(isNaN(e))return"INVALID HEX STRING";b[d>>3]|=e<<24-4*(d%8)}return b},d=function(a){var b="",c=4*a.length,d,e;for(d=0;d<c;d+=1)e=a[d>>2]>>8*(3-d%4),b+="0123456789abcdef".charAt(e>>4&15)+"0123456789abcdef".charAt(e&15);return b},e=function(a){var b=
+"",c=4*a.length,d,e,f;for(d=0;d<c;d+=3){f=(a[d>>2]>>8*(3-d%4)&255)<<16|(a[d+1>>2]>>8*(3-(d+1)%4)&255)<<8|a[d+2>>2]>>8*(3-(d+2)%4)&255;for(e=0;4>e;e+=1)b=8*d+6*e<=32*a.length?b+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(f>>6*(3-e)&63):b+""}return b},f=function(a){for(var b="",c=0;c<32*a.length;c+=8)b+=String.fromCharCode(a[c>>5]>>>24-c%32&255);return b},g=function(a,b){return a<<b|a>>>32-b},h=function(a,b){return a>>>b|a<<32-b},k=function(b,c){return 32>=c?new a(b.highOrder>>>
+c|b.lowOrder<<32-c,b.lowOrder>>>c|b.highOrder<<32-c):new a(b.lowOrder>>>c|b.highOrder<<32-c,b.highOrder>>>c|b.lowOrder<<32-c)},j=function(b,c){return 32>=c?new a(b.highOrder>>>c,b.lowOrder>>>c|b.highOrder<<32-c):new a(0,b.highOrder<<32-c)},m=function(a,b,c){return a&b^~a&c},u=function(b,c,d){return new a(b.highOrder&c.highOrder^~b.highOrder&d.highOrder,b.lowOrder&c.lowOrder^~b.lowOrder&d.lowOrder)},D=function(a,b,c){return a&b^a&c^b&c},l=function(b,c,d){return new a(b.highOrder&c.highOrder^b.highOrder&
+d.highOrder^c.highOrder&d.highOrder,b.lowOrder&c.lowOrder^b.lowOrder&d.lowOrder^c.lowOrder&d.lowOrder)},p=function(a){return h(a,2)^h(a,13)^h(a,22)},W=function(b){var c=k(b,28),d=k(b,34),b=k(b,39);return new a(c.highOrder^d.highOrder^b.highOrder,c.lowOrder^d.lowOrder^b.lowOrder)},L=function(a){return h(a,6)^h(a,11)^h(a,25)},z=function(b){var c=k(b,14),d=k(b,18),b=k(b,41);return new a(c.highOrder^d.highOrder^b.highOrder,c.lowOrder^d.lowOrder^b.lowOrder)},o=function(a){return h(a,7)^h(a,18)^a>>>3},
+A=function(b){var c=k(b,1),d=k(b,8),b=j(b,7);return new a(c.highOrder^d.highOrder^b.highOrder,c.lowOrder^d.lowOrder^b.lowOrder)},ka=function(a){return h(a,17)^h(a,19)^a>>>10},na=function(b){var c=k(b,19),d=k(b,61),b=j(b,6);return new a(c.highOrder^d.highOrder^b.highOrder,c.lowOrder^d.lowOrder^b.lowOrder)},fa=function(a,b){var c=(a&65535)+(b&65535);return((a>>>16)+(b>>>16)+(c>>>16)&65535)<<16|c&65535},la=function(a,b,c,d){var e=(a&65535)+(b&65535)+(c&65535)+(d&65535);return((a>>>16)+(b>>>16)+(c>>>
+16)+(d>>>16)+(e>>>16)&65535)<<16|e&65535},O=function(a,b,c,d,e){var f=(a&65535)+(b&65535)+(c&65535)+(d&65535)+(e&65535);return((a>>>16)+(b>>>16)+(c>>>16)+(d>>>16)+(e>>>16)+(f>>>16)&65535)<<16|f&65535},M=function(b,c){var d,e,f;d=(b.lowOrder&65535)+(c.lowOrder&65535);e=(b.lowOrder>>>16)+(c.lowOrder>>>16)+(d>>>16);f=(e&65535)<<16|d&65535;d=(b.highOrder&65535)+(c.highOrder&65535)+(e>>>16);e=(b.highOrder>>>16)+(c.highOrder>>>16)+(d>>>16);return new a((e&65535)<<16|d&65535,f)},Z=function(b,c,d,e){var f,
+g,h;f=(b.lowOrder&65535)+(c.lowOrder&65535)+(d.lowOrder&65535)+(e.lowOrder&65535);g=(b.lowOrder>>>16)+(c.lowOrder>>>16)+(d.lowOrder>>>16)+(e.lowOrder>>>16)+(f>>>16);h=(g&65535)<<16|f&65535;f=(b.highOrder&65535)+(c.highOrder&65535)+(d.highOrder&65535)+(e.highOrder&65535)+(g>>>16);g=(b.highOrder>>>16)+(c.highOrder>>>16)+(d.highOrder>>>16)+(e.highOrder>>>16)+(f>>>16);return new a((g&65535)<<16|f&65535,h)},qa=function(b,c,d,e,f){var g,h,j;g=(b.lowOrder&65535)+(c.lowOrder&65535)+(d.lowOrder&65535)+(e.lowOrder&
+65535)+(f.lowOrder&65535);h=(b.lowOrder>>>16)+(c.lowOrder>>>16)+(d.lowOrder>>>16)+(e.lowOrder>>>16)+(f.lowOrder>>>16)+(g>>>16);j=(h&65535)<<16|g&65535;g=(b.highOrder&65535)+(c.highOrder&65535)+(d.highOrder&65535)+(e.highOrder&65535)+(f.highOrder&65535)+(h>>>16);h=(b.highOrder>>>16)+(c.highOrder>>>16)+(d.highOrder>>>16)+(e.highOrder>>>16)+(f.highOrder>>>16)+(g>>>16);return new a((h&65535)<<16|g&65535,j)},ea=function(a,b){var c=[],d,e,f,h,j,k,m,l,p,o=[1732584193,4023233417,2562383102,271733878,3285377520],
+u=[1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,
+2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782];a[b>>5]|=128<<24-b%32;a[(b+65>>9<<4)+15]=b;p=a.length;for(m=0;m<p;m+=16){d=o[0];e=o[1];f=o[2];h=o[3];j=o[4];for(l=0;80>l;l+=1)c[l]=
+16>l?a[l+m]:g(c[l-3]^c[l-8]^c[l-14]^c[l-16],1),k=20>l?O(g(d,5),e&f^~e&h,j,u[l],c[l]):40>l?O(g(d,5),e^f^h,j,u[l],c[l]):60>l?O(g(d,5),D(e,f,h),j,u[l],c[l]):O(g(d,5),e^f^h,j,u[l],c[l]),j=h,h=f,f=g(e,30),e=d,d=k;o[0]=fa(d,o[0]);o[1]=fa(e,o[1]);o[2]=fa(f,o[2]);o[3]=fa(h,o[3]);o[4]=fa(j,o[4])}return o},ca=function(b,c,d){var e,f,g,h,j,k,ga,ca,ea,B,da,ma,ia,Ba,va,ja,wa,xa,ya,za,ta,ra,Aa,pa,t,ua,ba=[],Ea;if("SHA-224"===d||"SHA-256"===d)da=64,e=(c+65>>9<<4)+15,Ba=16,va=1,t=Number,ja=fa,wa=la,xa=O,ya=o,za=
+ka,ta=p,ra=L,pa=D,Aa=m,ua=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,
+3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],B="SHA-224"===d?[3238371032,914150663,812702999,4144912697,4290775857,1750603025,1694076839,3204075428]:[1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225];else if("SHA-384"===d||"SHA-512"===d)da=80,e=(c+128>>10<<5)+31,Ba=32,va=2,t=a,ja=M,wa=Z,xa=qa,
+ya=A,za=na,ta=W,ra=z,pa=l,Aa=u,ua=[new t(1116352408,3609767458),new t(1899447441,602891725),new t(3049323471,3964484399),new t(3921009573,2173295548),new t(961987163,4081628472),new t(1508970993,3053834265),new t(2453635748,2937671579),new t(2870763221,3664609560),new t(3624381080,2734883394),new t(310598401,1164996542),new t(607225278,1323610764),new t(1426881987,3590304994),new t(1925078388,4068182383),new t(2162078206,991336113),new t(2614888103,633803317),new t(3248222580,3479774868),new t(3835390401,
+2666613458),new t(4022224774,944711139),new t(264347078,2341262773),new t(604807628,2007800933),new t(770255983,1495990901),new t(1249150122,1856431235),new t(1555081692,3175218132),new t(1996064986,2198950837),new t(2554220882,3999719339),new t(2821834349,766784016),new t(2952996808,2566594879),new t(3210313671,3203337956),new t(3336571891,1034457026),new t(3584528711,2466948901),new t(113926993,3758326383),new t(338241895,168717936),new t(666307205,1188179964),new t(773529912,1546045734),new t(1294757372,
+1522805485),new t(1396182291,2643833823),new t(1695183700,2343527390),new t(1986661051,1014477480),new t(2177026350,1206759142),new t(2456956037,344077627),new t(2730485921,1290863460),new t(2820302411,3158454273),new t(3259730800,3505952657),new t(3345764771,106217008),new t(3516065817,3606008344),new t(3600352804,1432725776),new t(4094571909,1467031594),new t(275423344,851169720),new t(430227734,3100823752),new t(506948616,1363258195),new t(659060556,3750685593),new t(883997877,3785050280),new t(958139571,
+3318307427),new t(1322822218,3812723403),new t(1537002063,2003034995),new t(1747873779,3602036899),new t(1955562222,1575990012),new t(2024104815,1125592928),new t(2227730452,2716904306),new t(2361852424,442776044),new t(2428436474,593698344),new t(2756734187,3733110249),new t(3204031479,2999351573),new t(3329325298,3815920427),new t(3391569614,3928383900),new t(3515267271,566280711),new t(3940187606,3454069534),new t(4118630271,4000239992),new t(116418474,1914138554),new t(174292421,2731055270),new t(289380356,
+3203993006),new t(460393269,320620315),new t(685471733,587496836),new t(852142971,1086792851),new t(1017036298,365543100),new t(1126000580,2618297676),new t(1288033470,3409855158),new t(1501505948,4234509866),new t(1607167915,987167468),new t(1816402316,1246189591)],B="SHA-384"===d?[new t(3418070365,3238371032),new t(1654270250,914150663),new t(2438529370,812702999),new t(355462360,4144912697),new t(1731405415,4290775857),new t(41048885895,1750603025),new t(3675008525,1694076839),new t(1203062813,
+3204075428)]:[new t(1779033703,4089235720),new t(3144134277,2227873595),new t(1013904242,4271175723),new t(2773480762,1595750129),new t(1359893119,2917565137),new t(2600822924,725511199),new t(528734635,4215389547),new t(1541459225,327033209)];b[c>>5]|=128<<24-c%32;b[e]=c;Ea=b.length;for(ma=0;ma<Ea;ma+=Ba){c=B[0];e=B[1];f=B[2];g=B[3];h=B[4];j=B[5];k=B[6];ga=B[7];for(ia=0;ia<da;ia+=1)ba[ia]=16>ia?new t(b[ia*va+ma],b[ia*va+ma+1]):wa(za(ba[ia-2]),ba[ia-7],ya(ba[ia-15]),ba[ia-16]),ca=xa(ga,ra(h),Aa(h,
+j,k),ua[ia],ba[ia]),ea=ja(ta(c),pa(c,e,f)),ga=k,k=j,j=h,h=ja(g,ca),g=f,f=e,e=c,c=ja(ca,ea);B[0]=ja(c,B[0]);B[1]=ja(e,B[1]);B[2]=ja(f,B[2]);B[3]=ja(g,B[3]);B[4]=ja(h,B[4]);B[5]=ja(j,B[5]);B[6]=ja(k,B[6]);B[7]=ja(ga,B[7])}switch(d){case "SHA-224":return[B[0],B[1],B[2],B[3],B[4],B[5],B[6]];case "SHA-256":return B;case "SHA-384":return[B[0].highOrder,B[0].lowOrder,B[1].highOrder,B[1].lowOrder,B[2].highOrder,B[2].lowOrder,B[3].highOrder,B[3].lowOrder,B[4].highOrder,B[4].lowOrder,B[5].highOrder,B[5].lowOrder];
+case "SHA-512":return[B[0].highOrder,B[0].lowOrder,B[1].highOrder,B[1].lowOrder,B[2].highOrder,B[2].lowOrder,B[3].highOrder,B[3].lowOrder,B[4].highOrder,B[4].lowOrder,B[5].highOrder,B[5].lowOrder,B[6].highOrder,B[6].lowOrder,B[7].highOrder,B[7].lowOrder];default:return[]}},da=function(a,d){this.strToHash=this.strBinLen=this.sha512=this.sha384=this.sha256=this.sha224=this.sha1=null;if("HEX"===d){if(0!==a.length%2)return"TEXT MUST BE IN BYTE INCREMENTS";this.strBinLen=4*a.length;this.strToHash=c(a)}else if("ASCII"===
+d||"undefined"===typeof d)this.strBinLen=8*a.length,this.strToHash=b(a);else return"UNKNOWN TEXT INPUT TYPE"};da.prototype={getHash:function(a,b){var c=null,g=this.strToHash.slice();switch(b){case "HEX":c=d;break;case "B64":c=e;break;case "ASCII":c=f;break;default:return"FORMAT NOT RECOGNIZED"}switch(a){case "SHA-1":if(null===this.sha1)this.sha1=ea(g,this.strBinLen);return c(this.sha1);case "SHA-224":if(null===this.sha224)this.sha224=ca(g,this.strBinLen,a);return c(this.sha224);case "SHA-256":if(null===
+this.sha256)this.sha256=ca(g,this.strBinLen,a);return c(this.sha256);case "SHA-384":if(null===this.sha384)this.sha384=ca(g,this.strBinLen,a);return c(this.sha384);case "SHA-512":if(null===this.sha512)this.sha512=ca(g,this.strBinLen,a);return c(this.sha512);default:return"HASH NOT RECOGNIZED"}},getHMAC:function(a,g,h,j){var k,l,m,o,p;l=[];var u=[];switch(j){case "HEX":j=d;break;case "B64":j=e;break;case "ASCII":j=f;break;default:return"FORMAT NOT RECOGNIZED"}switch(h){case "SHA-1":k=64;p=160;break;
+case "SHA-224":k=64;p=224;break;case "SHA-256":k=64;p=256;break;case "SHA-384":k=128;p=384;break;case "SHA-512":k=128;p=512;break;default:return"HASH NOT RECOGNIZED"}if("HEX"===g){if(0!==a.length%2)return"KEY MUST BE IN BYTE INCREMENTS";g=c(a);o=4*a.length}else if("ASCII"===g)g=b(a),o=8*a.length;else return"UNKNOWN KEY INPUT TYPE";a=8*k;m=k/4-1;k<o/8?(g="SHA-1"===h?ea(g,o):ca(g,o,h),g[m]&=4294967040):k>o/8&&(g[m]&=4294967040);for(k=0;k<=m;k+=1)l[k]=g[k]^909522486,u[k]=g[k]^1549556828;"SHA-1"===h?
+(l=ea(l.concat(this.strToHash),a+this.strBinLen),l=ea(u.concat(l),a+p)):(l=ca(l.concat(this.strToHash),a+this.strBinLen,h),l=ca(u.concat(l),a+p,h));return j(l)}};return da}();function str_sha1(a){return(new jsSHA(a,"ASCII")).getHash("SHA-1","ASCII")}function str_sha224(a){return(new jsSHA(a,"ASCII")).getHash("SHA-224","ASCII")}function str_sha256(a){return(new jsSHA(a,"ASCII")).getHash("SHA-256","ASCII")}function str_sha384(a){return(new jsSHA(a,"ASCII")).getHash("SHA-384","ASCII")}
+function str_sha512(a){return(new jsSHA(a,"ASCII")).getHash("SHA-512","ASCII")}var RMDsize=160,X=[];function ROL(a,b){return new Number(a<<b|a>>>32-b)}function F(a,b,c){return new Number(a^b^c)}function G(a,b,c){return new Number(a&b|~a&c)}function H(a,b,c){return new Number((a|~b)^c)}function I(a,b,c){return new Number(a&c|b&~c)}function J(a,b,c){return new Number(a^(b|~c))}
+function mixOneRound(a,b,c,d,e,f,g,h){switch(h){case 0:a+=F(b,c,d)+f+0;break;case 1:a+=G(b,c,d)+f+1518500249;break;case 2:a+=H(b,c,d)+f+1859775393;break;case 3:a+=I(b,c,d)+f+2400959708;break;case 4:a+=J(b,c,d)+f+2840853838;break;case 5:a+=J(b,c,d)+f+1352829926;break;case 6:a+=I(b,c,d)+f+1548603684;break;case 7:a+=H(b,c,d)+f+1836072691;break;case 8:a+=G(b,c,d)+f+2053994217;break;case 9:a+=F(b,c,d)+f+0;break;default:document.write("Bogus round number")}a=ROL(a,g)+e;c=ROL(c,10);h=[];h[0]=a&4294967295;
+h[1]=b&4294967295;h[2]=c&4294967295;h[3]=d&4294967295;h[4]=e&4294967295;h[5]=f;h[6]=g;return h}function MDinit(a){a[0]=1732584193;a[1]=4023233417;a[2]=2562383102;a[3]=271733878;a[4]=3285377520}
+var ROLs=[[11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8],[7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12],[11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5],[11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12],[9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6],[8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6],[9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11],[9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5],[15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8],[8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11]],indexes=[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[7,4,13,1,10,6,15,3,12,
+0,9,5,2,14,11,8],[3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12],[1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2],[4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13],[5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12],[6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2],[15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13],[8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14],[12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11]];
+function compress(a,b){blockA=[];blockB=[];for(var c,d=0;5>d;d++)blockA[d]=new Number(a[d]),blockB[d]=new Number(a[d]);for(var e=0,f=0;5>f;f++)for(d=0;16>d;d++)c=mixOneRound(blockA[(e+0)%5],blockA[(e+1)%5],blockA[(e+2)%5],blockA[(e+3)%5],blockA[(e+4)%5],b[indexes[f][d]],ROLs[f][d],f),blockA[(e+0)%5]=c[0],blockA[(e+1)%5]=c[1],blockA[(e+2)%5]=c[2],blockA[(e+3)%5]=c[3],blockA[(e+4)%5]=c[4],e+=4;e=0;for(f=5;10>f;f++)for(d=0;16>d;d++)c=mixOneRound(blockB[(e+0)%5],blockB[(e+1)%5],blockB[(e+2)%5],blockB[(e+
+3)%5],blockB[(e+4)%5],b[indexes[f][d]],ROLs[f][d],f),blockB[(e+0)%5]=c[0],blockB[(e+1)%5]=c[1],blockB[(e+2)%5]=c[2],blockB[(e+3)%5]=c[3],blockB[(e+4)%5]=c[4],e+=4;blockB[3]+=blockA[2]+a[1];a[1]=a[2]+blockA[3]+blockB[4];a[2]=a[3]+blockA[4]+blockB[0];a[3]=a[4]+blockA[0]+blockB[1];a[4]=a[0]+blockA[1]+blockB[2];a[0]=blockB[3]}function zeroX(a){for(var b=0;16>b;b++)a[b]=0}
+function MDfinish(a,b,c,d){var e=Array(16);zeroX(e);for(var f=0,g=0;g<(c&63);g++)e[g>>>2]^=(b.charCodeAt(f++)&255)<<8*(g&3);e[c>>>2&15]^=1<<8*(c&3)+7;55<(c&63)&&(compress(a,e),e=Array(16),zeroX(e));e[14]=c<<3;e[15]=c>>>29|d<<3;compress(a,e)}function BYTES_TO_DWORD(a){var b=(a.charCodeAt(3)&255)<<24,b=b|(a.charCodeAt(2)&255)<<16,b=b|(a.charCodeAt(1)&255)<<8;return b|=a.charCodeAt(0)&255}
+function RMD(a){var b=Array(RMDsize/32),c=Array(RMDsize/8),d,e;MDinit(b);d=a.length;var f=Array(16);zeroX(f);var g=0;for(e=d;63<e;e-=64){for(var h=0;16>h;h++)f[h]=BYTES_TO_DWORD(a.substr(g,4)),g+=4;compress(b,f)}MDfinish(b,a.substr(g),d,0);for(h=0;h<RMDsize/8;h+=4)c[h]=b[h>>>2]&255,c[h+1]=b[h>>>2]>>>8&255,c[h+2]=b[h>>>2]>>>16&255,c[h+3]=b[h>>>2]>>>24&255;return c}function RMDstring(a){for(var a=RMD(a),b="",c=0;c<RMDsize/8;c++)b+=String.fromCharCode(a[c]);return b}
+function MD5(a){a=md5(a);return util.hex2bin(a)}
+function md5cycle(a,b){var c=a[0],d=a[1],e=a[2],f=a[3],c=ff(c,d,e,f,b[0],7,-680876936),f=ff(f,c,d,e,b[1],12,-389564586),e=ff(e,f,c,d,b[2],17,606105819),d=ff(d,e,f,c,b[3],22,-1044525330),c=ff(c,d,e,f,b[4],7,-176418897),f=ff(f,c,d,e,b[5],12,1200080426),e=ff(e,f,c,d,b[6],17,-1473231341),d=ff(d,e,f,c,b[7],22,-45705983),c=ff(c,d,e,f,b[8],7,1770035416),f=ff(f,c,d,e,b[9],12,-1958414417),e=ff(e,f,c,d,b[10],17,-42063),d=ff(d,e,f,c,b[11],22,-1990404162),c=ff(c,d,e,f,b[12],7,1804603682),f=ff(f,c,d,e,b[13],12,
+-40341101),e=ff(e,f,c,d,b[14],17,-1502002290),d=ff(d,e,f,c,b[15],22,1236535329),c=gg(c,d,e,f,b[1],5,-165796510),f=gg(f,c,d,e,b[6],9,-1069501632),e=gg(e,f,c,d,b[11],14,643717713),d=gg(d,e,f,c,b[0],20,-373897302),c=gg(c,d,e,f,b[5],5,-701558691),f=gg(f,c,d,e,b[10],9,38016083),e=gg(e,f,c,d,b[15],14,-660478335),d=gg(d,e,f,c,b[4],20,-405537848),c=gg(c,d,e,f,b[9],5,568446438),f=gg(f,c,d,e,b[14],9,-1019803690),e=gg(e,f,c,d,b[3],14,-187363961),d=gg(d,e,f,c,b[8],20,1163531501),c=gg(c,d,e,f,b[13],5,-1444681467),
+f=gg(f,c,d,e,b[2],9,-51403784),e=gg(e,f,c,d,b[7],14,1735328473),d=gg(d,e,f,c,b[12],20,-1926607734),c=hh(c,d,e,f,b[5],4,-378558),f=hh(f,c,d,e,b[8],11,-2022574463),e=hh(e,f,c,d,b[11],16,1839030562),d=hh(d,e,f,c,b[14],23,-35309556),c=hh(c,d,e,f,b[1],4,-1530992060),f=hh(f,c,d,e,b[4],11,1272893353),e=hh(e,f,c,d,b[7],16,-155497632),d=hh(d,e,f,c,b[10],23,-1094730640),c=hh(c,d,e,f,b[13],4,681279174),f=hh(f,c,d,e,b[0],11,-358537222),e=hh(e,f,c,d,b[3],16,-722521979),d=hh(d,e,f,c,b[6],23,76029189),c=hh(c,d,
+e,f,b[9],4,-640364487),f=hh(f,c,d,e,b[12],11,-421815835),e=hh(e,f,c,d,b[15],16,530742520),d=hh(d,e,f,c,b[2],23,-995338651),c=ii(c,d,e,f,b[0],6,-198630844),f=ii(f,c,d,e,b[7],10,1126891415),e=ii(e,f,c,d,b[14],15,-1416354905),d=ii(d,e,f,c,b[5],21,-57434055),c=ii(c,d,e,f,b[12],6,1700485571),f=ii(f,c,d,e,b[3],10,-1894986606),e=ii(e,f,c,d,b[10],15,-1051523),d=ii(d,e,f,c,b[1],21,-2054922799),c=ii(c,d,e,f,b[8],6,1873313359),f=ii(f,c,d,e,b[15],10,-30611744),e=ii(e,f,c,d,b[6],15,-1560198380),d=ii(d,e,f,c,b[13],
+21,1309151649),c=ii(c,d,e,f,b[4],6,-145523070),f=ii(f,c,d,e,b[11],10,-1120210379),e=ii(e,f,c,d,b[2],15,718787259),d=ii(d,e,f,c,b[9],21,-343485551);a[0]=add32(c,a[0]);a[1]=add32(d,a[1]);a[2]=add32(e,a[2]);a[3]=add32(f,a[3])}function cmn(a,b,c,d,e,f){b=add32(add32(b,a),add32(d,f));return add32(b<<e|b>>>32-e,c)}function ff(a,b,c,d,e,f,g){return cmn(b&c|~b&d,a,b,e,f,g)}function gg(a,b,c,d,e,f,g){return cmn(b&d|c&~d,a,b,e,f,g)}function hh(a,b,c,d,e,f,g){return cmn(b^c^d,a,b,e,f,g)}
+function ii(a,b,c,d,e,f,g){return cmn(c^(b|~d),a,b,e,f,g)}function md51(a){txt="";var b=a.length,c=[1732584193,-271733879,-1732584194,271733878],d;for(d=64;d<=a.length;d+=64)md5cycle(c,md5blk(a.substring(d-64,d)));var a=a.substring(d-64),e=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(d=0;d<a.length;d++)e[d>>2]|=a.charCodeAt(d)<<(d%4<<3);e[d>>2]|=128<<(d%4<<3);if(55<d){md5cycle(c,e);for(d=0;16>d;d++)e[d]=0}e[14]=8*b;md5cycle(c,e);return c}
+function md5blk(a){var b=[],c;for(c=0;64>c;c+=4)b[c>>2]=a.charCodeAt(c)+(a.charCodeAt(c+1)<<8)+(a.charCodeAt(c+2)<<16)+(a.charCodeAt(c+3)<<24);return b}var hex_chr="0123456789abcdef".split("");function rhex(a){for(var b="",c=0;4>c;c++)b+=hex_chr[a>>8*c+4&15]+hex_chr[a>>8*c&15];return b}function hex(a){for(var b=0;b<a.length;b++)a[b]=rhex(a[b]);return a.join("")}function md5(a){return hex(md51(a))}function add32(a,b){return a+b&4294967295}
+"5d41402abc4b2a76b9719d911017c592"!=md5("hello")&&(add32=function(a,b){var c=(a&65535)+(b&65535);return(a>>16)+(b>>16)+(c>>16)<<16|c&65535});
+function openpgp_keyring(){this.init=function(){var a=JSON.parse(window.localStorage.getItem("privatekeys")),b=JSON.parse(window.localStorage.getItem("publickeys"));if(null==a||0==a.length)a=[];if(null==b||0==b.length)b=[];this.publicKeys=[];this.privateKeys=[];for(var c=0,d=0;d<a.length;d++){var e=openpgp.read_privateKey(a[d]);this.privateKeys[c]={armored:a[d],obj:e[0],keyId:e[0].getKeyId()};c++}for(d=c=0;d<b.length;d++)e=openpgp.read_publicKey(b[d]),null!=e[0]&&(this.publicKeys[c]={armored:b[d],
+obj:e[0],keyId:e[0].getKeyId()},c++)};this.hasPrivateKey=function(){return 0<this.privateKeys.length};this.store=function(){for(var a=[],b=0;b<this.privateKeys.length;b++)a[b]=this.privateKeys[b].armored;for(var c=[],b=0;b<this.publicKeys.length;b++)c[b]=this.publicKeys[b].armored;window.localStorage.setItem("privatekeys",JSON.stringify(a));window.localStorage.setItem("publickeys",JSON.stringify(c))};this.getPublicKeyForAddress=function(a){var b=[],c=a.split("<"),d="",d=1<c.length?c[1].split(">")[0]:
+a.trim(),d=d.toLowerCase();if(!util.emailRegEx.test(d))return b;for(a=0;a<this.publicKeys.length;a++)for(c=0;c<this.publicKeys[a].obj.userIds.length;c++)0<=this.publicKeys[a].obj.userIds[c].text.toLowerCase().indexOf(d)&&(b[b.length]=this.publicKeys[a]);return b};this.getPrivateKeyForAddress=function(a){var b=[],c=a.split("<"),d="",d=1<c.length?c[1].split(">")[0]:a.trim(),d=d.toLowerCase();if(!util.emailRegEx.test(d))return b;for(a=0;a<this.privateKeys.length;a++)for(c=0;c<this.privateKeys[a].obj.userIds.length;c++)0<=
+this.privateKeys[a].obj.userIds[c].text.toLowerCase().indexOf(d)&&(b[b.length]=this.privateKeys[a]);return b};this.getPublicKeysForKeyId=function(a){for(var b=[],c=0;c<this.publicKeys.length;c++)a==this.publicKeys[c].obj.getKeyId()&&(b[b.length]=this.publicKeys[c]);return b};this.getPrivateKeyForKeyId=function(a){for(var b=[],c=0;c<this.privateKeys.length;c++)if(a==this.privateKeys[c].obj.getKeyId()&&(b[b.length]={key:this.privateKeys[c],keymaterial:this.privateKeys[c].obj.privateKeyPacket}),null!=
+this.privateKeys[c].obj.subKeys)for(var d=this.privateKeys[c].obj.getSubKeyIds(),e=0;e<d.length;e++)a==util.hexstrdump(d[e])&&(b[b.length]={key:this.privateKeys[c],keymaterial:this.privateKeys[c].obj.subKeys[e]});return b};this.importPublicKey=function(a){for(var b=openpgp.read_publicKey(a),c=0;c<b.length;c++)this.publicKeys[this.publicKeys.length]={armored:a,obj:b[c],keyId:b[c].getKeyId()};return!0};this.importPrivateKey=function(a,b){var c=openpgp.read_privateKey(a);if(!c[0].decryptSecretMPIs(b))return!1;
+for(var d=0;d<c.length;d++)this.privateKeys[this.privateKeys.length]={armored:a,obj:c[d],keyId:c[d].getKeyId()};return!0};this.exportPublicKey=function(a){return this.publicKey[a]};this.removePublicKey=function(a){a=this.publicKeys.splice(a,1);this.store();return a};this.exportPrivateKey=function(a){return this.privateKeys[a]};this.removePrivateKey=function(a){a=this.privateKeys.splice(a,1);this.store();return a}}
+function openpgp_msg_privatekey(){this.subKeys=[];this.privateKeyPacket=null;this.userIds=[];this.userAttributes=[];this.revocationSignatures=[];this.subKeys=[];this.getSigningKey=function(){if((17==this.privateKeyPacket.publicKey.publicKeyAlgorithm||2!=this.privateKeyPacket.publicKey.publicKeyAlgorithm)&&3==this.privateKeyPacket.publicKey.verifyKey())return this.privateKeyPacket;if(4==this.privateKeyPacket.publicKey.version)for(var a=0;a<this.privateKeyPacket.subKeys.length;a++)if((17==this.privateKeyPacket.subKeys[a].publicKey.publicKeyAlgorithm||
+2!=this.privateKeyPacket.subKeys[a].publicKey.publicKeyAlgorithm)&&3==this.privateKeyPacket.subKeys[a].publicKey.verifyKey())return this.privateKeyPacket.subKeys[a];return null};this.getFingerprint=function(){return this.privateKeyPacket.publicKey.getFingerprint()};this.getPreferredSignatureHashAlgorithm=function(){var a=this.getSigningKey();return null==a?(util.print_error("private key is for encryption only! Cannot create a signature."),null):17==a.publicKey.publicKeyAlgorithm?(new DSA).select_hash_algorithm(a.publicKey.MPIs[1].toBigInteger()):
+openpgp.config.config.prefer_hash_algorithm};this.read_nodes=function(a,b,c,d){this.privateKeyPacket=a;for(a=c;b.length>a;){var e=openpgp_packet.read_packet(b,a,b.length-a);if(null==e){util.print_error("openpgp.msg.messge decrypt:\n[pub/priv_key]parsing ends here @:"+a+" l:"+d);break}else switch(e.tagType){case 2:if(32==e.signatureType)this.revocationSignatures[this.revocationSignatures.length]=e;else if(15<e.signatureType&&20>e.signatureType){if(null==this.certificationsignatures)this.certificationSignatures=
+[];this.certificationSignatures[this.certificationSignatures.length]=e}else util.print_error("openpgp.msg.messge decrypt:\nunknown signature type directly on key "+e.signatureType+" @"+a);a+=e.packetLength+e.headerLength;break;case 7:this.subKeys[this.subKeys.length]=e;a+=e.packetLength+e.headerLength;a+=e.read_nodes(this.privateKeyPacket,b,a,b.length-a);break;case 17:this.userAttributes[this.userAttributes.length]=e;a+=e.packetLength+e.headerLength;a+=e.read_nodes(this.privateKeyPacket,b,a,b.length-
+a);break;case 13:this.userIds[this.userIds.length]=e;a+=e.packetLength+e.headerLength;a+=e.read_nodes(this.privateKeyPacket,b,a,b.length-a);break;default:return this.position=c-this.privateKeyPacket.packetLength-this.privateKeyPacket.headerLength,this.len=a-c}}this.position=c-this.privateKeyPacket.packetLength-this.privateKeyPacket.headerLength;return this.len=a-c};this.decryptSecretMPIs=function(a){return this.privateKeyPacket.decryptSecretMPIs(a)};this.getSubKeyIds=function(){if(4==this.privateKeyPacket.publicKey.version)var a=
+[];for(var b=0;b<this.subKeys.length;b++)a[b]=str_sha1(this.subKeys[b].publicKey.header+this.subKeys[b].publicKey.data).substring(12,20);return a};this.getKeyId=function(){return this.privateKeyPacket.publicKey.getKeyId()}}
 function openpgp_msg_publickey(){this.tostring="OPENPGP PUBLIC KEY\n";this.publicKeyPacket=this.bindingSignature=null;this.userIds=[];this.userAttributes=[];this.revocationSignatures=[];this.subKeys=[];this.arbitraryPacket=[];this.directSignatures=[];this.verifyCertificationSignatures=function(){for(var a=[],b=0;b<this.userIds.length;b++)a[b]=this.userIds[b].verifyCertificationSignatures(this.publicKeyPacket);return a};this.getEncryptionKey=function(){if(17!=this.publicKeyPacket.publicKeyAlgorithm&&
 3!=this.publicKeyPacket.publicKeyAlgorithm&&this.publicKeyPacket.verifyKey())return this.publicKeyPacket;if(4==this.publicKeyPacket.version)for(var a=0;a<this.subKeys.length;a++)if(17!=this.subKeys[a].publicKeyAlgorithm&&3!=this.subKeys[a].publicKeyAlgorithm&&this.subKeys[a].verifyKey())return this.subKeys[a];return null};this.getSigningKey=function(){if(17==this.publicKeyPacket.publicKeyAlgorithm||2!=this.publicKeyPacket.publicKeyAlgorithm)return this.publicKeyPacket;if(4==this.publicKeyPacket.version)for(var a=
 0;a<this.subKeys.length;a++)if((17==this.subKeys[a].publicKeyAlgorithm||2!=this.subKeys[a].publicKeyAlgorithm)&&this.subKeys[a].verifyKey())return this.subKeys[a];return null};this.read_nodes=function(a,b,c,d){this.publicKeyPacket=a;for(a=c;b.length!=a;){var e=openpgp_packet.read_packet(b,a,b.length-a);if(null==e){util.print_error("openpgp.msg.publickey read_nodes:\n[pub_key]parsing ends here @:"+a+" l:"+d);break}else switch(e.tagType){case 2:32==e.signatureType?this.revocationSignatures[this.revocationSignatures.length]=
@@ -391,21 +493,13 @@ b.length-a);break;case 17:this.userAttributes[this.userAttributes.length]=e;a+=e
 return this.len=a-c};this.write=function(){};this.toString=function(){for(var a=" OPENPGP Public Key\n    length: "+this.len+"\n",a=a+"    Revocation Signatures:\n",b=0;b<this.revocationSignatures.length;b++)a+="    "+this.revocationSignatures[b].toString();a+="    User Ids:\n";for(b=0;b<this.userIds.length;b++)a+="    "+this.userIds[b].toString();a+="    User Attributes:\n";for(b=0;b<this.userAttributes.length;b++)a+="    "+this.userAttributes[b].toString();a+="    Public Key SubKeys:\n";for(b=0;b<
 this.subKeys.length;b++)a+="    "+this.subKeys[b].toString();return a};this.validate=function(){for(var a=0;a<this.revocationSignatures.length;a++)if(this.revocationSignatures[a].verify(this.publicKeyPacket.header+this.publicKeyPacket.data,this.publicKeyPacket))return!1;if(0!=this.subKeys.length){for(var b=!1,a=0;a<this.subKeys.length;a++)if(3==this.subKeys[a].verifyKey()){b=!0;break}if(!b)return!1}b=!1;for(a=0;a<this.userIds.length;a++)if(0==this.userIds[a].verify(this.publicKeyPacket)){b=!0;break}return!b?
 !1:!0};this.getFingerprint=function(){return this.publicKeyPacket.getFingerprint()};this.getKeyId=function(){return this.publicKeyPacket.getKeyId()};this.verifyBasicSignatures=function(){for(var a=0;a<this.revocationSignatures.length;)return this.revocationSignatures[a].verify(this.publicKeyPacket.header+this.publicKeyPacket.data,this.publicKeyPacket),!1;if(0!=this.subKeys.length){for(var b=!1,a=0;a<this.subKeys.length;a++)if(null!=this.subKeys[a]&&3==this.subKeys[a].verifyKey()){b=!0;break}if(!b)return!1}b=
-this.getKeyId();for(a=0;a<this.userIds.length;a++)for(var c=0;c<this.userIds[a].certificationRevocationSignatures.length;c++)if(this.userIds[a].certificationSignatures[c].getIssuer==b&&4!=this.userIds[a].certificationSignatures[c].verifyBasic(this.publicKeyPacket))return!1;return!0}}
-function openpgp_config(){this.config=null;this.default_config={prefer_hash_algorithm:2,encryption_cipher:9,compression:1,show_version:!0,show_comment:!0,integrity_protect:!0,composition_behavior:0,keyserver:"keyserver.linux.it"};this.versionstring="OpenPGP.js v.1.20120821";this.commentstring="http://openpgpjs.org";this.debug=!1;this.read=function(){var a=JSON.parse(window.localStorage.getItem("config"));null==a?(this.config=this.default_config,this.write()):this.config=a};this.write=function(){window.localStorage.setItem("config",
-JSON.stringify(this.config))}}
-function openpgp_msg_privatekey(){this.subKeys=[];this.privateKeyPacket=null;this.userIds=[];this.userAttributes=[];this.revocationSignatures=[];this.subKeys=[];this.getSigningKey=function(){if((17==this.privateKeyPacket.publicKey.publicKeyAlgorithm||2!=this.privateKeyPacket.publicKey.publicKeyAlgorithm)&&3==this.privateKeyPacket.publicKey.verifyKey())return this.privateKeyPacket;if(4==this.privateKeyPacket.publicKey.version)for(var a=0;a<this.privateKeyPacket.subKeys.length;a++)if((17==this.privateKeyPacket.subKeys[a].publicKey.publicKeyAlgorithm||
-2!=this.privateKeyPacket.subKeys[a].publicKey.publicKeyAlgorithm)&&3==this.privateKeyPacket.subKeys[a].publicKey.verifyKey())return this.privateKeyPacket.subKeys[a];return null};this.getFingerprint=function(){return this.privateKeyPacket.publicKey.getFingerprint()};this.getPreferredSignatureHashAlgorithm=function(){var a=this.getSigningKey();return null==a?(util.print_error("private key is for encryption only! Cannot create a signature."),null):17==a.publicKey.publicKeyAlgorithm?(new DSA).select_hash_algorithm(a.publicKey.MPIs[1].toBigInteger()):
-openpgp.config.config.prefer_hash_algorithm};this.read_nodes=function(a,b,c,d){this.privateKeyPacket=a;for(a=c;b.length>a;){var e=openpgp_packet.read_packet(b,a,b.length-a);if(null==e){util.print_error("openpgp.msg.messge decrypt:\n[pub/priv_key]parsing ends here @:"+a+" l:"+d);break}else switch(e.tagType){case 2:if(32==e.signatureType)this.revocationSignatures[this.revocationSignatures.length]=e;else if(15<e.signatureType&&20>e.signatureType){if(null==this.certificationsignatures)this.certificationSignatures=
-[];this.certificationSignatures[this.certificationSignatures.length]=e}else util.print_error("openpgp.msg.messge decrypt:\nunknown signature type directly on key "+e.signatureType+" @"+a);a+=e.packetLength+e.headerLength;break;case 7:this.subKeys[this.subKeys.length]=e;a+=e.packetLength+e.headerLength;a+=e.read_nodes(this.privateKeyPacket,b,a,b.length-a);break;case 17:this.userAttributes[this.userAttributes.length]=e;a+=e.packetLength+e.headerLength;a+=e.read_nodes(this.privateKeyPacket,b,a,b.length-
-a);break;case 13:this.userIds[this.userIds.length]=e;a+=e.packetLength+e.headerLength;a+=e.read_nodes(this.privateKeyPacket,b,a,b.length-a);break;default:return this.position=c-this.privateKeyPacket.packetLength-this.privateKeyPacket.headerLength,this.len=a-c}}this.position=c-this.privateKeyPacket.packetLength-this.privateKeyPacket.headerLength;return this.len=a-c};this.decryptSecretMPIs=function(a){return this.privateKeyPacket.decryptSecretMPIs(a)};this.getSubKeyIds=function(){if(4==this.privateKeyPacket.publicKey.version)var a=
-[];for(var b=0;b<this.subKeys.length;b++)a[b]=str_sha1(this.subKeys[b].publicKey.header+this.subKeys[b].publicKey.data).substring(12,20);return a};this.getKeyId=function(){return this.privateKeyPacket.publicKey.getKeyId()}}function openpgp_encoding_base64_encode(a){return s2r(a)}function openpgp_encoding_base64_decode(a){return r2s(a)}function openpgp_encoding_html_encode(a){return null==a?"":$("<div/>").text(a).html()}
+this.getKeyId();for(a=0;a<this.userIds.length;a++)for(var c=0;c<this.userIds[a].certificationRevocationSignatures.length;c++)if(this.userIds[a].certificationSignatures[c].getIssuer==b&&4!=this.userIds[a].certificationSignatures[c].verifyBasic(this.publicKeyPacket))return!1;return!0}}function openpgp_encoding_base64_encode(a){return s2r(a)}function openpgp_encoding_base64_decode(a){return r2s(a)}function openpgp_encoding_html_encode(a){return null==a?"":$("<div/>").text(a).html()}
 function openpgp_encoding_eme_pkcs1_encode(a,b){if(a.length>b-11)return-1;var c;c=""+String.fromCharCode(0);c+=String.fromCharCode(2);for(var d=0;d<b-a.length-3;d++)c+=String.fromCharCode(openpgp_crypto_getPseudoRandom(1,255));c+=String.fromCharCode(0);return c+a}function openpgp_encoding_eme_pkcs1_decode(a,b){a.length<b&&(a=String.fromCharCode(0)+a);if(12>a.length||0!=a.charCodeAt(0)||2!=a.charCodeAt(1))return-1;for(var c=2;0!=a.charCodeAt(c)&&a.length>c;)c++;return a.substring(c+1,a.length)}
 hash_headers=[,[48,32,48,12,6,8,42,134,72,134,247,13,2,5,5,0,4,16],[48,33,48,9,6,5,43,14,3,2,26,5,0,4,20],[48,33,48,9,6,5,43,36,3,2,1,5,0,4,20]];hash_headers[8]=[48,49,48,13,6,9,96,134,72,1,101,3,4,2,1,5,0,4,32];hash_headers[9]=[48,65,48,13,6,9,96,134,72,1,101,3,4,2,2,5,0,4,48];hash_headers[10]=[48,81,48,13,6,9,96,134,72,1,101,3,4,2,3,5,0,4,64];hash_headers[11]=[48,49,48,13,6,9,96,134,72,1,101,3,4,2,4,5,0,4,28];
 function openpgp_encoding_emsa_pkcs1_encode(a,b,c){var d;d=""+String.fromCharCode(0);d+=String.fromCharCode(1);for(var e=0;e<c-hash_headers[a].length-3-openpgp_crypto_getHashByteLength(a);e++)d+=String.fromCharCode(255);d+=String.fromCharCode(0);for(e=0;e<hash_headers[a].length;e++)d+=String.fromCharCode(hash_headers[a][e]);d+=openpgp_crypto_hashData(a,b);return new BigInteger(util.hexstrdump(d),16)}
 function openpgp_encoding_emsa_pkcs1_decode(a,b){var c=0;if(0!=b.charCodeAt(0)&&1!=b.charCodeAt(0))return-1;for(c++;255==b.charCodeAt(c);)c++;if(0!=b.charCodeAt(c++))return-1;for(var d=0,d=0;d<hash_headers[a].length&&d+c<b.length;d++)if(b.charCodeAt(d+c)!=hash_headers[a][d])return-1;c+=d;return b.substring(c).length<openpgp_crypto_getHashByteLength(a)?-1:b.substring(c)}var b64s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-function s2r(a){var b,c,d,e="",f=0,h=0,g=a.length;for(d=0;d<g;d++)c=a.charCodeAt(d),0==h?(e+=b64s.charAt(c>>2&63),b=(c&3)<<4):1==h?(e+=b64s.charAt(b|c>>4&15),b=(c&15)<<2):2==h&&(e+=b64s.charAt(b|c>>6&3),f+=1,0==f%60&&(e+="\n"),e+=b64s.charAt(c&63)),f+=1,0==f%60&&(e+="\n"),h+=1,3==h&&(h=0);0<h&&(e+=b64s.charAt(b),f+=1,0==f%60&&(e+="\n"),e+="=",f+=1);1==h&&(0==f%60&&(e+="\n"),e+="=");return e}
-function r2s(a){var b,c,d="",e=0,f=0,h=a.length;for(c=0;c<h;c++)b=b64s.indexOf(a.charAt(c)),0<=b&&(e&&(d+=String.fromCharCode(f|b>>6-e&255)),e=e+2&7,f=b<<e&255);return d}
+function s2r(a){var b,c,d,e="",f=0,g=0,h=a.length;for(d=0;d<h;d++)c=a.charCodeAt(d),0==g?(e+=b64s.charAt(c>>2&63),b=(c&3)<<4):1==g?(e+=b64s.charAt(b|c>>4&15),b=(c&15)<<2):2==g&&(e+=b64s.charAt(b|c>>6&3),f+=1,0==f%60&&(e+="\n"),e+=b64s.charAt(c&63)),f+=1,0==f%60&&(e+="\n"),g+=1,3==g&&(g=0);0<g&&(e+=b64s.charAt(b),f+=1,0==f%60&&(e+="\n"),e+="=",f+=1);1==g&&(0==f%60&&(e+="\n"),e+="=");return e}
+function r2s(a){var b,c,d="",e=0,f=0,g=a.length;for(c=0;c<g;c++)b=b64s.indexOf(a.charAt(c)),0<=b&&(e&&(d+=String.fromCharCode(f|b>>6-e&255)),e=e+2&7,f=b<<e&255);return d}
 function openpgp_encoding_deArmor(a){var b=getPGPMessageType(a);if(2!=b){a=a.split("-----");data={openpgp:openpgp_encoding_base64_decode(a[2].split("\n\n")[1].split("\n=")[0].replace(/\n- /g,"\n")),type:b};if(verifyCheckSum(data.openpgp,a[2].split("\n\n")[1].split("\n=")[1].split("\n")[0]))return data;util.print_error("Ascii armor integrity check on message failed: '"+a[2].split("\n\n")[1].split("\n=")[1].split("\n")[0]+"' should be '"+getCheckSum(data))}else{a=a.split("-----");b={text:a[2].replace(/\n- /g,
 "\n").split("\n\n")[1],openpgp:openpgp_encoding_base64_decode(a[4].split("\n\n")[1].split("\n=")[0]),type:b};if(verifyCheckSum(b.openpgp,a[4].split("\n\n")[1].split("\n=")[1]))return b;util.print_error("Ascii armor integrity check on message failed")}}
 function getPGPMessageType(a){a=a.split("-----");if(a[1].match(/BEGIN PGP MESSAGE, PART \d+\/\d+/))return 0;if(a[1].match(/BEGIN PGP MESSAGE, PART \d+/))return 1;if(a[1].match(/BEGIN PGP SIGNED MESSAGE/))return 2;if(a[1].match(/BEGIN PGP MESSAGE/))return 3;if(a[1].match(/BEGIN PGP PUBLIC KEY BLOCK/))return 4;if(a[1].match(/BEGIN PGP PRIVATE KEY BLOCK/))return 5}
@@ -421,97 +515,4 @@ var crc_table=[0,8801531,25875725,17603062,60024545,51751450,35206124,44007191,1
 1126595968,1102643863,1094667884,1077139354,1085643617,1166763343,1158490548,1140961346,1149762745,1176011694,1184812885,1200772771,1192499800,1307552511,1298785796,1281720306,1289958153,1316768798,1325007077,1341561107,1332794856,1246636998,1254647613,1271201483,1262662192,1239272743,1230733788,1213667370,1221678289,1562785183,1570797924,1554833554,1546300521,1588974462,1580441477,1597965939,1605978760,1518843046,1510078557,1527603627,1535847760,1494504007,1502748348,1486784330,1478020017,1390639894,
 1382365165,1399434779,1408230112,1366334967,1375129868,1358579962,1350304769,1430452783,1438955220,1422405410,1414423513,1456544974,1448562741,1465633219,1474135352];
 function createcrc24(a){for(var b=11994318,c=0;16<a.length-c;)b=b<<8^crc_table[(b>>16^a.charCodeAt(c))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+1))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+2))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+3))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+4))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+5))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+6))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+7))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+8))&255],b=b<<8^crc_table[(b>>
-16^a.charCodeAt(c+9))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+10))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+11))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+12))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+13))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+14))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+15))&255],c+=16;for(var d=c;d<a.length;d++)b=b<<8^crc_table[(b>>16^a.charCodeAt(c++))&255];return b&16777215}JXG={exists:function(a){return function(b){return!(b===a||null===b)}}()};
-JXG.decompress=function(a){return unescape((new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(a))).unzip()[0][0])};JXG.Util={};
-JXG.Util.Unzip=function(a){function b(){ra+=8;return ba<Z.length?Z[ba++]:-1}function c(){var a;ra++;a=da&1;da>>=1;0==da&&(da=b(),a=da&1,da=da>>1|128);return a}function d(b){for(var a=0,d=b;d--;)a=a<<1|c();b&&(a=aa[a]>>8-b);return a}function e(b){ia++;B[A++]=b;m.push(String.fromCharCode(b));32768==A&&(A=0)}function f(){this.b1=this.b0=0;this.jump=null;this.jumppos=-1}function h(){for(;;){if(pa[ca]>=ua)return-1;if(Fa[pa[ca]]==ca)return pa[ca]++;pa[ca]++}}function g(){var b=oa[na],a;o&&document.write("<br>len:"+
-ca+" treepos:"+na);if(17==ca)return-1;na++;ca++;a=h();o&&document.write("<br>IsPat "+a);if(0<=a)b.b0=a,o&&document.write("<br>b0 "+b.b0);else if(b.b0=32768,o&&document.write("<br>b0 "+b.b0),g())return-1;a=h();if(0<=a)b.b1=a,o&&document.write("<br>b1 "+b.b1),b.jump=null;else if(b.b1=32768,o&&document.write("<br>b1 "+b.b1),b.jump=oa[na],b.jumppos=na,g())return-1;ca--;return 0}function k(b,a,c,d){o&&document.write("currentTree "+b+" numval "+a+" lengths "+c+" show "+d);oa=b;na=0;Fa=c;ua=a;for(b=0;17>
-b;b++)pa[b]=0;ca=0;if(g())return o&&alert("invalid huffman tree\n"),-1;if(o){document.write("<br>Tree: "+oa.length);for(b=0;32>b;b++)document.write("Places["+b+"].b0="+oa[b].b0+"<br>"),document.write("Places["+b+"].b1="+oa[b].b1+"<br>")}return 0}function j(b){for(var a,d,e=0,f=b[e];;)if(a=c(),o&&document.write("b="+a),a){if(!(f.b1&32768))return o&&document.write("ret1"),f.b1;f=f.jump;a=b.length;for(d=0;d<a;d++)if(b[d]===f){e=d;break}}else{if(!(f.b0&32768))return o&&document.write("ret2"),f.b0;e++;
-f=b[e]}o&&document.write("ret3");return-1}function l(){var a,h,g,l,q;do{a=c();g=d(2);switch(g){case 0:o&&alert("Stored\n");break;case 1:o&&alert("Fixed Huffman codes\n");break;case 2:o&&alert("Dynamic Huffman codes\n");break;case 3:o&&alert("Reserved block type!!\n");break;default:o&&alert("Unexpected value %d!\n",g)}if(0==g){da=1;g=b();g|=b()<<8;h=b();h|=b()<<8;for((g^~h)&65535&&document.write("BlockLen checksum mismatch\n");g--;)h=b(),e(h)}else if(1==g)for(;;)if(g=aa[d(7)]>>1,23<g?(g=g<<1|c(),199<
-g?(g-=128,g=g<<1|c()):(g-=48,143<g&&(g+=136))):g+=256,256>g)e(g);else if(256==g)break;else{var m;g-=257;q=d(K[g])+ha[g];g=aa[d(5)]>>3;8<V[g]?(m=d(8),m|=d(V[g]-8)<<8):m=d(V[g]);m+=E[g];for(g=0;g<q;g++)h=B[A-m&32767],e(h)}else if(2==g){var u=Array(320);h=257+d(5);m=1+d(5);l=4+d(4);for(g=0;19>g;g++)u[g]=0;for(g=0;g<l;g++)u[ma[g]]=d(3);q=W.length;for(l=0;l<q;l++)W[l]=new f;if(k(W,19,u,0))return A=0,1;if(o){document.write("<br>distanceTree");for(g=0;g<W.length;g++)document.write("<br>"+W[g].b0+" "+W[g].b1+
-" "+W[g].jump+" "+W[g].jumppos)}q=h+m;l=0;var D=-1;for(o&&document.write("<br>n="+q+" bits: "+ra+"<br>");l<q;)if(D++,g=j(W),o&&document.write("<br>"+D+" i:"+l+" decode: "+g+"    bits "+ra+"<br>"),16>g)u[l++]=g;else if(16==g){var O;g=3+d(2);if(l+g>q)return A=0,1;for(O=l?u[l-1]:0;g--;)u[l++]=O}else{g=17==g?3+d(3):11+d(7);if(l+g>q)return A=0,1;for(;g--;)u[l++]=0}q=sa.length;for(l=0;l<q;l++)sa[l]=new f;if(k(sa,h,u,0))return A=0,1;q=sa.length;for(l=0;l<q;l++)W[l]=new f;g=[];for(l=h;l<u.length;l++)g[l-
-h]=u[l];if(k(W,m,g,0))return A=0,1;for(o&&document.write("<br>literalTree");;)if(g=j(sa),256<=g){g-=256;if(0==g)break;g--;q=d(K[g])+ha[g];g=j(W);8<V[g]?(m=d(8),m|=d(V[g]-8)<<8):m=d(V[g]);for(m+=E[g];q--;)h=B[A-m&32767],e(h)}else e(g)}}while(!a);A=0;da=1;return 0}function q(){o&&alert("NEXTFILE");m=[];var a=[];ga=!1;a[0]=b();a[1]=b();o&&alert("type: "+a[0]+" "+a[1]);120==a[0]&&218==a[1]&&(o&&alert("GEONExT-GZIP"),l(),o&&alert(m.join("")),D[O]=Array(2),D[O][0]=m.join(""),D[O][1]="geonext.gxt",O++);
-120==a[0]&&156==a[1]&&(o&&alert("ZLIB"),l(),o&&alert(m.join("")),D[O]=Array(2),D[O][0]=m.join(""),D[O][1]="ZLIB",O++);31==a[0]&&139==a[1]&&(o&&alert("GZIP"),u(),o&&alert(m.join("")),D[O]=Array(2),D[O][0]=m.join(""),D[O][1]="file",O++);if(80==a[0]&&75==a[1]&&(ga=!0,a[2]=b(),a[3]=b(),3==a[2]&&4==a[3])){a[0]=b();a[1]=b();o&&alert("ZIP-Version: "+a[1]+" "+a[0]/10+"."+a[0]%10);M=b();M|=b()<<8;o&&alert("gpflags: "+M);a=b();a|=b()<<8;o&&alert("method: "+a);b();b();b();b();var c=b(),c=c|b()<<8,c=c|b()<<16,
-c=c|b()<<24,d=b(),d=d|b()<<8,d=d|b()<<16,d=d|b()<<24,e=b(),e=e|b()<<8,e=e|b()<<16,e=e|b()<<24;o&&alert("local CRC: "+c+"\nlocal Size: "+e+"\nlocal CompSize: "+d);c=b();c|=b()<<8;d=b();d|=b()<<8;o&&alert("filelen "+c);f=0;for(la=[];c--;)e=b(),"/"==e|":"==e?f=0:f<xa-1&&(la[f++]=String.fromCharCode(e));o&&alert("nameBuf: "+la);ta||(ta=la);for(var f=0;f<d;)b(),f++;ia=0;8==a&&(l(),o&&alert(m.join("")),D[O]=Array(2),D[O][0]=m.join(""),D[O][1]=la.join(""),O++);u()}}function u(){var a=[],c;M&8&&(a[0]=b(),
-a[1]=b(),a[2]=b(),a[3]=b(),80==a[0]&&75==a[1]&&7==a[2]&&8==a[3]&&(b(),b(),b(),b()),b(),b(),b(),b(),b(),b(),b(),b(),o&&alert("CRC:"));ga&&q();a[0]=b();if(8!=a[0])return o&&alert("Unknown compression method!"),0;M=b();o&&M&-32&&alert("Unknown flags set!");b();b();b();b();b();b();if(M&4){a[0]=b();a[2]=b();ca=a[0]+256*a[1];o&&alert("Extra field size: "+ca);for(a=0;a<ca;a++)b()}if(M&8){a=0;for(la=[];c=b();){if("7"==c||":"==c)a=0;a<xa-1&&(la[a++]=c)}o&&alert("original file name: "+la)}if(M&16)for(;b(););
-M&2&&(b(),b());l();b();b();b();b();b();b();b();b();ga&&q()}var m=[],o=!1,M,O=0,D=[],B=Array(32768),A=0,ga=!1,ia,aa=[0,128,64,192,32,160,96,224,16,144,80,208,48,176,112,240,8,136,72,200,40,168,104,232,24,152,88,216,56,184,120,248,4,132,68,196,36,164,100,228,20,148,84,212,52,180,116,244,12,140,76,204,44,172,108,236,28,156,92,220,60,188,124,252,2,130,66,194,34,162,98,226,18,146,82,210,50,178,114,242,10,138,74,202,42,170,106,234,26,154,90,218,58,186,122,250,6,134,70,198,38,166,102,230,22,150,86,214,54,
-182,118,246,14,142,78,206,46,174,110,238,30,158,94,222,62,190,126,254,1,129,65,193,33,161,97,225,17,145,81,209,49,177,113,241,9,137,73,201,41,169,105,233,25,153,89,217,57,185,121,249,5,133,69,197,37,165,101,229,21,149,85,213,53,181,117,245,13,141,77,205,45,173,109,237,29,157,93,221,61,189,125,253,3,131,67,195,35,163,99,227,19,147,83,211,51,179,115,243,11,139,75,203,43,171,107,235,27,155,91,219,59,187,123,251,7,135,71,199,39,167,103,231,23,151,87,215,55,183,119,247,15,143,79,207,47,175,111,239,31,
-159,95,223,63,191,127,255],ha=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],K=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,99,99],E=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],V=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],ma=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],Z=a,ba=0,da=1,ra=0,xa=256,la=[],ta,sa=Array(288),W=Array(32),na=0,oa=null,
-ca=0,pa=Array(17);pa[0]=0;var Fa,ua;JXG.Util.Unzip.prototype.unzipFile=function(b){var a;this.unzip();for(a=0;a<D.length;a++)if(D[a][1]==b)return D[a][0]};JXG.Util.Unzip.prototype.unzip=function(){o&&alert(Z);q();return D}};
-JXG.Util.Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(a){for(var b=[],c,d,e,f,h,g,k=0,a=JXG.Util.Base64._utf8_encode(a);k<a.length;)c=a.charCodeAt(k++),d=a.charCodeAt(k++),e=a.charCodeAt(k++),f=c>>2,c=(c&3)<<4|d>>4,h=(d&15)<<2|e>>6,g=e&63,isNaN(d)?h=g=64:isNaN(e)&&(g=64),b.push([this._keyStr.charAt(f),this._keyStr.charAt(c),this._keyStr.charAt(h),this._keyStr.charAt(g)].join(""));return b.join("")},decode:function(a,b){for(var c=[],d,e,f,h,g,
-k=0,a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");k<a.length;)d=this._keyStr.indexOf(a.charAt(k++)),e=this._keyStr.indexOf(a.charAt(k++)),h=this._keyStr.indexOf(a.charAt(k++)),g=this._keyStr.indexOf(a.charAt(k++)),d=d<<2|e>>4,e=(e&15)<<4|h>>2,f=(h&3)<<6|g,c.push(String.fromCharCode(d)),64!=h&&c.push(String.fromCharCode(e)),64!=g&&c.push(String.fromCharCode(f));c=c.join("");b&&(c=JXG.Util.Base64._utf8_decode(c));return c},_utf8_encode:function(a){for(var a=a.replace(/\r\n/g,"\n"),b="",c=0;c<a.length;c++){var d=
-a.charCodeAt(c);128>d?b+=String.fromCharCode(d):(127<d&&2048>d?b+=String.fromCharCode(d>>6|192):(b+=String.fromCharCode(d>>12|224),b+=String.fromCharCode(d>>6&63|128)),b+=String.fromCharCode(d&63|128))}return b},_utf8_decode:function(a){for(var b=[],c=0,d=0,e=0,f=0;c<a.length;)d=a.charCodeAt(c),128>d?(b.push(String.fromCharCode(d)),c++):191<d&&224>d?(e=a.charCodeAt(c+1),b.push(String.fromCharCode((d&31)<<6|e&63)),c+=2):(e=a.charCodeAt(c+1),f=a.charCodeAt(c+2),b.push(String.fromCharCode((d&15)<<12|
-(e&63)<<6|f&63)),c+=3);return b.join("")},_destrip:function(a,b){var c=[],d,e,f=[];null==b&&(b=76);a.replace(/ /g,"");d=a.length/b;for(e=0;e<d;e++)c[e]=a.substr(e*b,b);d!=a.length/b&&(c[c.length]=a.substr(d*b,a.length-d*b));for(e=0;e<c.length;e++)f.push(c[e]);return f.join("\n")},decodeAsArray:function(a){var a=this.decode(a),b=[],c;for(c=0;c<a.length;c++)b[c]=a.charCodeAt(c);return b},decodeGEONExT:function(a){return decodeAsArray(destrip(a),!1)}};
-JXG.Util.asciiCharCodeAt=function(a,b){var c=a.charCodeAt(b);if(255<c)switch(c){case 8364:c=128;break;case 8218:c=130;break;case 402:c=131;break;case 8222:c=132;break;case 8230:c=133;break;case 8224:c=134;break;case 8225:c=135;break;case 710:c=136;break;case 8240:c=137;break;case 352:c=138;break;case 8249:c=139;break;case 338:c=140;break;case 381:c=142;break;case 8216:c=145;break;case 8217:c=146;break;case 8220:c=147;break;case 8221:c=148;break;case 8226:c=149;break;case 8211:c=150;break;case 8212:c=
-151;break;case 732:c=152;break;case 8482:c=153;break;case 353:c=154;break;case 8250:c=155;break;case 339:c=156;break;case 382:c=158;break;case 376:c=159}return c};
-JXG.Util.utf8Decode=function(a){var b=[],c=0,d=0,e=0,f;if(!JXG.exists(a))return"";for(;c<a.length;)d=a.charCodeAt(c),128>d?(b.push(String.fromCharCode(d)),c++):191<d&&224>d?(e=a.charCodeAt(c+1),b.push(String.fromCharCode((d&31)<<6|e&63)),c+=2):(e=a.charCodeAt(c+1),f=a.charCodeAt(c+2),b.push(String.fromCharCode((d&15)<<12|(e&63)<<6|f&63)),c+=3);return b.join("")};
-JXG.Util.genUUID=function(){for(var a="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),b=Array(36),c=0,d,e=0;36>e;e++)8==e||13==e||18==e||23==e?b[e]="-":14==e?b[e]="4":(2>=c&&(c=33554432+16777216*Math.random()|0),d=c&15,c>>=4,b[e]=a[19==e?d&3|8:d]);return b.join("")};(function(a){a.zip={useWebWorkers:!1}})(this);
-(function(a){function b(){function b(a,c,d,Ha,k,l,w,y,o,p,r){var t,C,v,s,x,z,u,A,Q,B;u=0;v=d;do e[a[c+u]]++,u++,v--;while(0!==v);if(e[0]==d)return w[0]=-1,y[0]=0,g;z=y[0];for(s=1;s<=K&&!(0!==e[s]);s++);x=s;z<s&&(z=s);for(v=K;0!==v&&!(0!==e[v]);v--);C=v;z>v&&(z=v);y[0]=z;for(y=1<<s;s<v;s++,y<<=1)if(0>(y-=e[s]))return q;if(0>(y-=e[v]))return q;e[v]+=y;j[1]=s=0;u=1;for(A=2;0!==--v;)j[A]=s+=e[u],A++,u++;u=v=0;do{if(0!==(s=a[c+u]))r[j[s]++]=v;u++}while(++v<d);d=j[C];u=j[0]=v=0;c=-1;Q=-z;for(B=A=h[0]=0;x<=
-C;x++)for(a=e[x];0!==a--;){for(;x>Q+z;){c++;Q+=z;B=C-Q;B=B>z?z:B;if((t=1<<(s=x-Q))>a+1)if(t-=a+1,A=x,s<B)for(;++s<B&&!((t<<=1)<=e[++A]);)t-=e[A];B=1<<s;if(p[0]+B>M)return q;h[c]=A=p[0];p[0]+=B;0!==c?(j[c]=v,f[0]=s,f[1]=z,s=v>>>Q-z,f[2]=A-h[c-1]-s,o.set(f,3*(h[c-1]+s))):w[0]=A}f[1]=x-Q;u>=d?f[0]=192:r[u]<Ha?(f[0]=256>r[u]?0:96,f[2]=r[u++]):(f[0]=l[r[u]-Ha]+16+64,f[2]=k[r[u++]-Ha]);t=1<<x-Q;for(s=v>>>Q;s<B;s+=t)o.set(f,3*(A+s));for(s=1<<x-1;0!==(v&s);s>>>=1)v^=s;v^=s;for(s=(1<<Q)-1;(v&s)!=j[c];)c--,
-Q-=z,s=(1<<Q)-1}return 0!==y&&1!=C?m:g}function a(b){var g;c||(c=[],d=[],e=new Int32Array(K+1),f=[],h=new Int32Array(K),j=new Int32Array(K+1));d.length<b&&(d=[]);for(g=0;g<b;g++)d[g]=0;for(g=0;g<K+1;g++)e[g]=0;for(g=0;3>g;g++)f[g]=0;h.set(e.subarray(0,K),0);j.set(e.subarray(0,K+1),0)}var c,d,e,f,h,j;this.inflate_trees_bits=function(e,f,g,h,j){a(19);c[0]=0;e=b(e,0,19,19,null,null,g,f,h,c,d);if(e==q)j.msg="oversubscribed dynamic bit lengths tree";else if(e==m||0===f[0])j.msg="incomplete dynamic bit lengths tree",
-e=q;return e};this.inflate_trees_dynamic=function(e,f,h,j,k,l,w,y,o){a(288);c[0]=0;l=b(h,0,e,257,ga,ia,l,j,y,c,d);if(l!=g||0===j[0]){if(l==q)o.msg="oversubscribed literal/length tree";else if(l!=u)o.msg="incomplete literal/length tree",l=q;return l}a(288);l=b(h,e,f,0,aa,ha,w,k,y,c,d);if(l!=g||0===k[0]&&257<e){if(l==q)o.msg="oversubscribed distance tree";else if(l==m)o.msg="incomplete distance tree",l=q;else if(l!=u)o.msg="empty distance tree with lengths",l=q;return l}return g}}function c(){var b,
-a=0,c,d=0,e=0,f=0,h=0,j=0,m=0,t=0,u,z=0,A,B=0;this.init=function(a,d,e,f,g,h){b=E;m=a;t=d;u=e;z=f;A=g;B=h;c=null};this.proc=function(w,y,T){var p,r,R=0,C=0,v=0,s,x,N,v=y.next_in_index;s=y.avail_in;R=w.bitb;C=w.bitk;x=w.write;for(N=x<w.read?w.read-x-1:w.end-x;;)switch(b){case E:if(258<=N&&10<=s){w.bitb=R;w.bitk=C;y.avail_in=s;y.total_in+=v-y.next_in_index;y.next_in_index=v;w.write=x;a:{T=u;R=z;C=A;v=B;s=w;x=y;var L=void 0,D=void 0,O=void 0,M=r=p=N=void 0,K=void 0,U=void 0,W=void 0,aa=void 0,ca=void 0,
-P=void 0,Y=L=L=void 0,M=x.next_in_index,K=x.avail_in;p=s.bitb;r=s.bitk;U=s.write;W=U<s.read?s.read-U-1:s.end-U;aa=o[m];ca=o[t];do{for(;20>r;)K--,p|=(x.read_byte(M++)&255)<<r,r+=8;L=p&aa;D=T;O=R;Y=3*(O+L);if(0===(N=D[Y]))p>>=D[Y+1],r-=D[Y+1],s.window[U++]=D[Y+2],W--;else{do{p>>=D[Y+1];r-=D[Y+1];if(0!==(N&16)){N&=15;P=D[Y+2]+(p&o[N]);p>>=N;for(r-=N;15>r;)K--,p|=(x.read_byte(M++)&255)<<r,r+=8;L=p&ca;D=C;O=v;Y=3*(O+L);N=D[Y];do if(p>>=D[Y+1],r-=D[Y+1],0!==(N&16)){for(N&=15;r<N;)K--,p|=(x.read_byte(M++)&
-255)<<r,r+=8;L=D[Y+2]+(p&o[N]);p>>=N;r-=N;W-=P;if(U>=L)L=U-L,0<U-L&&2>U-L?(s.window[U++]=s.window[L++],s.window[U++]=s.window[L++]):(s.window.set(s.window.subarray(L,L+2),U),U+=2,L+=2),P-=2;else{L=U-L;do L+=s.end;while(0>L);N=s.end-L;if(P>N){P-=N;if(0<U-L&&N>U-L){do s.window[U++]=s.window[L++];while(0!==--N)}else s.window.set(s.window.subarray(L,L+N),U),U+=N;L=0}}if(0<U-L&&P>U-L){do s.window[U++]=s.window[L++];while(0!==--P)}else s.window.set(s.window.subarray(L,L+P),U),U+=P;break}else if(0===(N&
-64))L+=D[Y+2],L+=p&o[N],Y=3*(O+L),N=D[Y];else{x.msg="invalid distance code";P=x.avail_in-K;P=r>>3<P?r>>3:P;K+=P;M-=P;r-=P<<3;s.bitb=p;s.bitk=r;x.avail_in=K;x.total_in+=M-x.next_in_index;x.next_in_index=M;s.write=U;T=q;break a}while(1);break}if(0===(N&64)){if(L+=D[Y+2],L+=p&o[N],Y=3*(O+L),0===(N=D[Y])){p>>=D[Y+1];r-=D[Y+1];s.window[U++]=D[Y+2];W--;break}}else{if(0!==(N&32)){P=x.avail_in-K;P=r>>3<P?r>>3:P;K+=P;M-=P;r-=P<<3;s.bitb=p;s.bitk=r;x.avail_in=K;x.total_in+=M-x.next_in_index;x.next_in_index=
-M;s.write=U;T=k;break a}x.msg="invalid literal/length code";P=x.avail_in-K;P=r>>3<P?r>>3:P;K+=P;M-=P;r-=P<<3;s.bitb=p;s.bitk=r;x.avail_in=K;x.total_in+=M-x.next_in_index;x.next_in_index=M;s.write=U;T=q;break a}}while(1)}}while(258<=W&&10<=K);P=x.avail_in-K;P=r>>3<P?r>>3:P;K+=P;M-=P;r-=P<<3;s.bitb=p;s.bitk=r;x.avail_in=K;x.total_in+=M-x.next_in_index;x.next_in_index=M;s.write=U;T=g}v=y.next_in_index;s=y.avail_in;R=w.bitb;C=w.bitk;x=w.write;N=x<w.read?w.read-x-1:w.end-x;if(T!=g){b=T==k?xa:ta;break}}e=
-m;c=u;d=z;b=V;case V:for(p=e;C<p;){if(0!==s)T=g;else return w.bitb=R,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,T);s--;R|=(y.read_byte(v++)&255)<<C;C+=8}p=3*(d+(R&o[p]));R>>>=c[p+1];C-=c[p+1];r=c[p];if(0===r){f=c[p+2];b=ra;break}if(0!==(r&16)){h=r&15;a=c[p+2];b=ma;break}if(0===(r&64)){e=r;d=p/3+c[p+2];break}if(0!==(r&32)){b=xa;break}b=ta;y.msg="invalid literal/length code";T=q;w.bitb=R;w.bitk=C;y.avail_in=s;y.total_in+=v-y.next_in_index;y.next_in_index=
-v;w.write=x;return w.inflate_flush(y,T);case ma:for(p=h;C<p;){if(0!==s)T=g;else return w.bitb=R,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,T);s--;R|=(y.read_byte(v++)&255)<<C;C+=8}a+=R&o[p];R>>=p;C-=p;e=t;c=A;d=B;b=Z;case Z:for(p=e;C<p;){if(0!==s)T=g;else return w.bitb=R,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,T);s--;R|=(y.read_byte(v++)&255)<<C;C+=8}p=3*(d+(R&o[p]));R>>=c[p+1];C-=c[p+
-1];r=c[p];if(0!==(r&16)){h=r&15;j=c[p+2];b=ba;break}if(0===(r&64)){e=r;d=p/3+c[p+2];break}b=ta;y.msg="invalid distance code";T=q;w.bitb=R;w.bitk=C;y.avail_in=s;y.total_in+=v-y.next_in_index;y.next_in_index=v;w.write=x;return w.inflate_flush(y,T);case ba:for(p=h;C<p;){if(0!==s)T=g;else return w.bitb=R,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,T);s--;R|=(y.read_byte(v++)&255)<<C;C+=8}j+=R&o[p];R>>=p;C-=p;b=da;case da:for(p=x-j;0>p;)p+=w.end;for(;0!==
-a;){if(0===N&&(x==w.end&&0!==w.read&&(x=0,N=x<w.read?w.read-x-1:w.end-x),0===N&&(w.write=x,T=w.inflate_flush(y,T),x=w.write,N=x<w.read?w.read-x-1:w.end-x,x==w.end&&0!==w.read&&(x=0,N=x<w.read?w.read-x-1:w.end-x),0===N)))return w.bitb=R,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,T);w.window[x++]=w.window[p++];N--;p==w.end&&(p=0);a--}b=E;break;case ra:if(0===N&&(x==w.end&&0!==w.read&&(x=0,N=x<w.read?w.read-x-1:w.end-x),0===N&&(w.write=x,T=w.inflate_flush(y,
-T),x=w.write,N=x<w.read?w.read-x-1:w.end-x,x==w.end&&0!==w.read&&(x=0,N=x<w.read?w.read-x-1:w.end-x),0===N)))return w.bitb=R,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,T);T=g;w.window[x++]=f;N--;b=E;break;case xa:7<C&&(C-=8,s++,v--);w.write=x;T=w.inflate_flush(y,T);x=w.write;if(w.read!=w.write)return w.bitb=R,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,T);b=la;case la:return T=k,w.bitb=R,w.bitk=
-C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,T);case ta:return T=q,w.bitb=R,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,T);default:return T=l,w.bitb=R,w.bitk=C,y.avail_in=s,y.total_in+=v-y.next_in_index,y.next_in_index=v,w.write=x,w.inflate_flush(y,T)}};this.free=function(){}}function d(a,d){var e=this,f=W,h=0,j=0,t=0,u,A=[0],B=[0],D=new c,E=0,K=new Int32Array(3*M),O=new b;e.bitk=0;e.bitb=0;e.window=
-new Uint8Array(d);e.end=d;e.read=0;e.write=0;e.reset=function(b,a){a&&(a[0]=0);f==ua&&D.free(b);f=W;e.bitk=0;e.bitb=0;e.read=e.write=0};e.reset(a,null);e.inflate_flush=function(b,a){var c,d,f;d=b.next_out_index;f=e.read;c=(f<=e.write?e.write:e.end)-f;if(c>b.avail_out)c=b.avail_out;0!==c&&a==m&&(a=g);b.avail_out-=c;b.total_out+=c;b.next_out.set(e.window.subarray(f,f+c),d);d+=c;f+=c;if(f==e.end){f=0;if(e.write==e.end)e.write=0;c=e.write-f;if(c>b.avail_out)c=b.avail_out;0!==c&&a==m&&(a=g);b.avail_out-=
-c;b.total_out+=c;b.next_out.set(e.window.subarray(f,f+c),d);d+=c;f+=c}b.next_out_index=d;e.read=f;return a};e.proc=function(a,c){var d,p,r,m,C,v,s;m=a.next_in_index;C=a.avail_in;p=e.bitb;r=e.bitk;v=e.write;for(s=v<e.read?e.read-v-1:e.end-v;;)switch(f){case W:for(;3>r;){if(0!==C)c=g;else return e.bitb=p,e.bitk=r,a.avail_in=C,a.total_in+=m-a.next_in_index,a.next_in_index=m,e.write=v,e.inflate_flush(a,c);C--;p|=(a.read_byte(m++)&255)<<r;r+=8}d=p&7;E=d&1;switch(d>>>1){case 0:p>>>=3;r-=3;d=r&7;p>>>=d;
-r-=d;f=na;break;case 1:d=[];var x=[],Q=[[]],L=[[]];b.inflate_trees_fixed(d,x,Q,L,a);D.init(d[0],x[0],Q[0],0,L[0],0,a);p>>>=3;r-=3;f=ua;break;case 2:p>>>=3;r-=3;f=ca;break;case 3:return p>>>=3,r-=3,f=ja,a.msg="invalid block type",c=q,e.bitb=p,e.bitk=r,a.avail_in=C,a.total_in+=m-a.next_in_index,a.next_in_index=m,e.write=v,e.inflate_flush(a,c)}break;case na:for(;32>r;){if(0!==C)c=g;else return e.bitb=p,e.bitk=r,a.avail_in=C,a.total_in+=m-a.next_in_index,a.next_in_index=m,e.write=v,e.inflate_flush(a,
-c);C--;p|=(a.read_byte(m++)&255)<<r;r+=8}if((~p>>>16&65535)!=(p&65535))return f=ja,a.msg="invalid stored block lengths",c=q,e.bitb=p,e.bitk=r,a.avail_in=C,a.total_in+=m-a.next_in_index,a.next_in_index=m,e.write=v,e.inflate_flush(a,c);h=p&65535;p=r=0;f=0!==h?oa:0!==E?z:W;break;case oa:if(0===C||0===s&&(v==e.end&&0!==e.read&&(v=0,s=v<e.read?e.read-v-1:e.end-v),0===s&&(e.write=v,c=e.inflate_flush(a,c),v=e.write,s=v<e.read?e.read-v-1:e.end-v,v==e.end&&0!==e.read&&(v=0,s=v<e.read?e.read-v-1:e.end-v),0===
-s)))return e.bitb=p,e.bitk=r,a.avail_in=C,a.total_in+=m-a.next_in_index,a.next_in_index=m,e.write=v,e.inflate_flush(a,c);c=g;d=h;d>C&&(d=C);d>s&&(d=s);e.window.set(a.read_buf(m,d),v);m+=d;C-=d;v+=d;s-=d;if(0!==(h-=d))break;f=0!==E?z:W;break;case ca:for(;14>r;){if(0!==C)c=g;else return e.bitb=p,e.bitk=r,a.avail_in=C,a.total_in+=m-a.next_in_index,a.next_in_index=m,e.write=v,e.inflate_flush(a,c);C--;p|=(a.read_byte(m++)&255)<<r;r+=8}j=d=p&16383;if(29<(d&31)||29<(d>>5&31))return f=ja,a.msg="too many length or distance symbols",
-c=q,e.bitb=p,e.bitk=r,a.avail_in=C,a.total_in+=m-a.next_in_index,a.next_in_index=m,e.write=v,e.inflate_flush(a,c);d=258+(d&31)+(d>>5&31);if(!u||u.length<d)u=[];else for(s=0;s<d;s++)u[s]=0;p>>>=14;r-=14;t=0;f=pa;case pa:for(;t<4+(j>>>10);){for(;3>r;){if(0!==C)c=g;else return e.bitb=p,e.bitk=r,a.avail_in=C,a.total_in+=m-a.next_in_index,a.next_in_index=m,e.write=v,e.inflate_flush(a,c);C--;p|=(a.read_byte(m++)&255)<<r;r+=8}u[sa[t++]]=p&7;p>>>=3;r-=3}for(;19>t;)u[sa[t++]]=0;A[0]=7;d=O.inflate_trees_bits(u,
-A,B,K,a);if(d!=g)return c=d,c==q&&(u=null,f=ja),e.bitb=p,e.bitk=r,a.avail_in=C,a.total_in+=m-a.next_in_index,a.next_in_index=m,e.write=v,e.inflate_flush(a,c);t=0;f=Fa;case Fa:for(;;){d=j;if(!(t<258+(d&31)+(d>>5&31)))break;for(d=A[0];r<d;){if(0!==C)c=g;else return e.bitb=p,e.bitk=r,a.avail_in=C,a.total_in+=m-a.next_in_index,a.next_in_index=m,e.write=v,e.inflate_flush(a,c);C--;p|=(a.read_byte(m++)&255)<<r;r+=8}d=K[3*(B[0]+(p&o[d]))+1];Q=K[3*(B[0]+(p&o[d]))+2];if(16>Q)p>>>=d,r-=d,u[t++]=Q;else{s=18==
-Q?7:Q-14;for(x=18==Q?11:3;r<d+s;){if(0!==C)c=g;else return e.bitb=p,e.bitk=r,a.avail_in=C,a.total_in+=m-a.next_in_index,a.next_in_index=m,e.write=v,e.inflate_flush(a,c);C--;p|=(a.read_byte(m++)&255)<<r;r+=8}p>>>=d;r-=d;x+=p&o[s];p>>>=s;r-=s;s=t;d=j;if(s+x>258+(d&31)+(d>>5&31)||16==Q&&1>s)return u=null,f=ja,a.msg="invalid bit length repeat",c=q,e.bitb=p,e.bitk=r,a.avail_in=C,a.total_in+=m-a.next_in_index,a.next_in_index=m,e.write=v,e.inflate_flush(a,c);Q=16==Q?u[s-1]:0;do u[s++]=Q;while(0!==--x);t=
-s}}B[0]=-1;s=[];x=[];Q=[];L=[];s[0]=9;x[0]=6;d=j;d=O.inflate_trees_dynamic(257+(d&31),1+(d>>5&31),u,s,x,Q,L,K,a);if(d!=g)return d==q&&(u=null,f=ja),c=d,e.bitb=p,e.bitk=r,a.avail_in=C,a.total_in+=m-a.next_in_index,a.next_in_index=m,e.write=v,e.inflate_flush(a,c);D.init(s[0],x[0],K,Q[0],K,L[0],a);f=ua;case ua:e.bitb=p;e.bitk=r;a.avail_in=C;a.total_in+=m-a.next_in_index;a.next_in_index=m;e.write=v;if((c=D.proc(e,a,c))!=k)return e.inflate_flush(a,c);c=g;D.free(a);m=a.next_in_index;C=a.avail_in;p=e.bitb;
-r=e.bitk;v=e.write;s=v<e.read?e.read-v-1:e.end-v;if(0===E){f=W;break}f=z;case z:e.write=v;c=e.inflate_flush(a,c);v=e.write;if(e.read!=e.write)return e.bitb=p,e.bitk=r,a.avail_in=C,a.total_in+=m-a.next_in_index,a.next_in_index=m,e.write=v,e.inflate_flush(a,c);f=ya;case ya:return c=k,e.bitb=p,e.bitk=r,a.avail_in=C,a.total_in+=m-a.next_in_index,a.next_in_index=m,e.write=v,e.inflate_flush(a,c);case ja:return c=q,e.bitb=p,e.bitk=r,a.avail_in=C,a.total_in+=m-a.next_in_index,a.next_in_index=m,e.write=v,
-e.inflate_flush(a,c);default:return c=l,e.bitb=p,e.bitk=r,a.avail_in=C,a.total_in+=m-a.next_in_index,a.next_in_index=m,e.write=v,e.inflate_flush(a,c)}};e.free=function(a){e.reset(a,null);K=e.window=null};e.set_dictionary=function(a,b,c){e.window.set(a.subarray(b,b+c),0);e.read=e.write=c};e.sync_point=function(){return f==na?1:0}}function e(){function a(b){if(!b||!b.istate)return l;b.total_in=b.total_out=0;b.msg=null;b.istate.mode=qa;b.istate.blocks.reset(b,null);return g}var b=this;b.mode=0;b.method=
-0;b.was=[0];b.need=0;b.marker=0;b.wbits=0;b.inflateEnd=function(a){b.blocks&&b.blocks.free(a);b.blocks=null;return g};b.inflateInit=function(c,e){c.msg=null;b.blocks=null;if(8>e||15<e)return b.inflateEnd(c),l;b.wbits=e;c.istate.blocks=new d(c,1<<e);a(c);return g};b.inflate=function(a,b){var c,d;if(!a||!a.istate||!a.next_in)return l;b=b==D?m:g;for(c=m;;)switch(a.istate.mode){case za:if(0===a.avail_in)return c;c=b;a.avail_in--;a.total_in++;if(((a.istate.method=a.read_byte(a.next_in_index++))&15)!=Ga){a.istate.mode=
-ka;a.msg="unknown compression method";a.istate.marker=5;break}if((a.istate.method>>4)+8>a.istate.wbits){a.istate.mode=ka;a.msg="invalid window size";a.istate.marker=5;break}a.istate.mode=fa;case fa:if(0===a.avail_in)return c;c=b;a.avail_in--;a.total_in++;d=a.read_byte(a.next_in_index++)&255;if(0!==((a.istate.method<<8)+d)%31){a.istate.mode=ka;a.msg="incorrect header check";a.istate.marker=5;break}if(0===(d&ea)){a.istate.mode=qa;break}a.istate.mode=Aa;case Aa:if(0===a.avail_in)return c;c=b;a.avail_in--;
-a.total_in++;a.istate.need=(a.read_byte(a.next_in_index++)&255)<<24&4278190080;a.istate.mode=Ba;case Ba:if(0===a.avail_in)return c;c=b;a.avail_in--;a.total_in++;a.istate.need+=(a.read_byte(a.next_in_index++)&255)<<16&16711680;a.istate.mode=Ca;case Ca:if(0===a.avail_in)return c;c=b;a.avail_in--;a.total_in++;a.istate.need+=(a.read_byte(a.next_in_index++)&255)<<8&65280;a.istate.mode=Da;case Da:if(0===a.avail_in)return c;a.avail_in--;a.total_in++;a.istate.need+=a.read_byte(a.next_in_index++)&255;a.istate.mode=
-va;return j;case va:return a.istate.mode=ka,a.msg="need dictionary",a.istate.marker=0,l;case qa:c=a.istate.blocks.proc(a,c);if(c==q){a.istate.mode=ka;a.istate.marker=0;break}c==g&&(c=b);if(c!=k)return c;a.istate.blocks.reset(a,a.istate.was);a.istate.mode=Ea;case Ea:return k;case ka:return q;default:return l}};b.inflateSetDictionary=function(a,b,c){var d=0,e=c;if(!a||!a.istate||a.istate.mode!=va)return l;e>=1<<a.istate.wbits&&(e=(1<<a.istate.wbits)-1,d=c-e);a.istate.blocks.set_dictionary(b,d,e);a.istate.mode=
-qa;return g};b.inflateSync=function(b){var c,d,e;if(!b||!b.istate)return l;if(b.istate.mode!=ka)b.istate.mode=ka,b.istate.marker=0;if(0===(c=b.avail_in))return m;d=b.next_in_index;for(e=b.istate.marker;0!==c&&4>e;)b.read_byte(d)==t[e]?e++:e=0!==b.read_byte(d)?0:4-e,d++,c--;b.total_in+=d-b.next_in_index;b.next_in_index=d;b.avail_in=c;b.istate.marker=e;if(4!=e)return q;c=b.total_in;d=b.total_out;a(b);b.total_in=c;b.total_out=d;b.istate.mode=qa;return g};b.inflateSyncPoint=function(a){return!a||!a.istate||
-!a.istate.blocks?l:a.istate.blocks.sync_point()}}function f(){}function h(){var a=new f,b=O,c=new Uint8Array(512),d=!1;a.inflateInit();a.next_out=c;this.append=function(e,f){var h,j=[],l=0,o=0,q=0,t;if(0!==e.length){a.next_in_index=0;a.next_in=e;a.avail_in=e.length;do{a.next_out_index=0;a.avail_out=512;if(0===a.avail_in&&!d)a.next_in_index=0,d=!0;h=a.inflate(b);if(d&&h==m)return-1;if(h!=g&&h!=k)throw"inflating: "+a.msg;if((d||h==k)&&a.avail_out==e.length)return-1;a.next_out_index&&(512==a.next_out_index?
-j.push(new Uint8Array(c)):j.push(new Uint8Array(c.subarray(0,a.next_out_index))));q+=a.next_out_index;if(f&&0<a.next_in_index&&a.next_in_index!=l)f(a.next_in_index),l=a.next_in_index}while(0<a.avail_in||0===a.avail_out);t=new Uint8Array(q);j.forEach(function(a){t.set(a,o);o+=a.length});return t}};this.flush=function(){a.inflateEnd()}}var g=0,k=1,j=2,l=-2,q=-3,u=-4,m=-5,o=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535],M=1440,O=0,D=4,B=[96,7,256,0,8,80,0,8,16,84,8,115,82,7,31,
-0,8,112,0,8,48,0,9,192,80,7,10,0,8,96,0,8,32,0,9,160,0,8,0,0,8,128,0,8,64,0,9,224,80,7,6,0,8,88,0,8,24,0,9,144,83,7,59,0,8,120,0,8,56,0,9,208,81,7,17,0,8,104,0,8,40,0,9,176,0,8,8,0,8,136,0,8,72,0,9,240,80,7,4,0,8,84,0,8,20,85,8,227,83,7,43,0,8,116,0,8,52,0,9,200,81,7,13,0,8,100,0,8,36,0,9,168,0,8,4,0,8,132,0,8,68,0,9,232,80,7,8,0,8,92,0,8,28,0,9,152,84,7,83,0,8,124,0,8,60,0,9,216,82,7,23,0,8,108,0,8,44,0,9,184,0,8,12,0,8,140,0,8,76,0,9,248,80,7,3,0,8,82,0,8,18,85,8,163,83,7,35,0,8,114,0,8,50,0,9,
-196,81,7,11,0,8,98,0,8,34,0,9,164,0,8,2,0,8,130,0,8,66,0,9,228,80,7,7,0,8,90,0,8,26,0,9,148,84,7,67,0,8,122,0,8,58,0,9,212,82,7,19,0,8,106,0,8,42,0,9,180,0,8,10,0,8,138,0,8,74,0,9,244,80,7,5,0,8,86,0,8,22,192,8,0,83,7,51,0,8,118,0,8,54,0,9,204,81,7,15,0,8,102,0,8,38,0,9,172,0,8,6,0,8,134,0,8,70,0,9,236,80,7,9,0,8,94,0,8,30,0,9,156,84,7,99,0,8,126,0,8,62,0,9,220,82,7,27,0,8,110,0,8,46,0,9,188,0,8,14,0,8,142,0,8,78,0,9,252,96,7,256,0,8,81,0,8,17,85,8,131,82,7,31,0,8,113,0,8,49,0,9,194,80,7,10,0,8,97,
-0,8,33,0,9,162,0,8,1,0,8,129,0,8,65,0,9,226,80,7,6,0,8,89,0,8,25,0,9,146,83,7,59,0,8,121,0,8,57,0,9,210,81,7,17,0,8,105,0,8,41,0,9,178,0,8,9,0,8,137,0,8,73,0,9,242,80,7,4,0,8,85,0,8,21,80,8,258,83,7,43,0,8,117,0,8,53,0,9,202,81,7,13,0,8,101,0,8,37,0,9,170,0,8,5,0,8,133,0,8,69,0,9,234,80,7,8,0,8,93,0,8,29,0,9,154,84,7,83,0,8,125,0,8,61,0,9,218,82,7,23,0,8,109,0,8,45,0,9,186,0,8,13,0,8,141,0,8,77,0,9,250,80,7,3,0,8,83,0,8,19,85,8,195,83,7,35,0,8,115,0,8,51,0,9,198,81,7,11,0,8,99,0,8,35,0,9,166,0,8,
-3,0,8,131,0,8,67,0,9,230,80,7,7,0,8,91,0,8,27,0,9,150,84,7,67,0,8,123,0,8,59,0,9,214,82,7,19,0,8,107,0,8,43,0,9,182,0,8,11,0,8,139,0,8,75,0,9,246,80,7,5,0,8,87,0,8,23,192,8,0,83,7,51,0,8,119,0,8,55,0,9,206,81,7,15,0,8,103,0,8,39,0,9,174,0,8,7,0,8,135,0,8,71,0,9,238,80,7,9,0,8,95,0,8,31,0,9,158,84,7,99,0,8,127,0,8,63,0,9,222,82,7,27,0,8,111,0,8,47,0,9,190,0,8,15,0,8,143,0,8,79,0,9,254,96,7,256,0,8,80,0,8,16,84,8,115,82,7,31,0,8,112,0,8,48,0,9,193,80,7,10,0,8,96,0,8,32,0,9,161,0,8,0,0,8,128,0,8,64,
-0,9,225,80,7,6,0,8,88,0,8,24,0,9,145,83,7,59,0,8,120,0,8,56,0,9,209,81,7,17,0,8,104,0,8,40,0,9,177,0,8,8,0,8,136,0,8,72,0,9,241,80,7,4,0,8,84,0,8,20,85,8,227,83,7,43,0,8,116,0,8,52,0,9,201,81,7,13,0,8,100,0,8,36,0,9,169,0,8,4,0,8,132,0,8,68,0,9,233,80,7,8,0,8,92,0,8,28,0,9,153,84,7,83,0,8,124,0,8,60,0,9,217,82,7,23,0,8,108,0,8,44,0,9,185,0,8,12,0,8,140,0,8,76,0,9,249,80,7,3,0,8,82,0,8,18,85,8,163,83,7,35,0,8,114,0,8,50,0,9,197,81,7,11,0,8,98,0,8,34,0,9,165,0,8,2,0,8,130,0,8,66,0,9,229,80,7,7,0,8,
-90,0,8,26,0,9,149,84,7,67,0,8,122,0,8,58,0,9,213,82,7,19,0,8,106,0,8,42,0,9,181,0,8,10,0,8,138,0,8,74,0,9,245,80,7,5,0,8,86,0,8,22,192,8,0,83,7,51,0,8,118,0,8,54,0,9,205,81,7,15,0,8,102,0,8,38,0,9,173,0,8,6,0,8,134,0,8,70,0,9,237,80,7,9,0,8,94,0,8,30,0,9,157,84,7,99,0,8,126,0,8,62,0,9,221,82,7,27,0,8,110,0,8,46,0,9,189,0,8,14,0,8,142,0,8,78,0,9,253,96,7,256,0,8,81,0,8,17,85,8,131,82,7,31,0,8,113,0,8,49,0,9,195,80,7,10,0,8,97,0,8,33,0,9,163,0,8,1,0,8,129,0,8,65,0,9,227,80,7,6,0,8,89,0,8,25,0,9,147,
-83,7,59,0,8,121,0,8,57,0,9,211,81,7,17,0,8,105,0,8,41,0,9,179,0,8,9,0,8,137,0,8,73,0,9,243,80,7,4,0,8,85,0,8,21,80,8,258,83,7,43,0,8,117,0,8,53,0,9,203,81,7,13,0,8,101,0,8,37,0,9,171,0,8,5,0,8,133,0,8,69,0,9,235,80,7,8,0,8,93,0,8,29,0,9,155,84,7,83,0,8,125,0,8,61,0,9,219,82,7,23,0,8,109,0,8,45,0,9,187,0,8,13,0,8,141,0,8,77,0,9,251,80,7,3,0,8,83,0,8,19,85,8,195,83,7,35,0,8,115,0,8,51,0,9,199,81,7,11,0,8,99,0,8,35,0,9,167,0,8,3,0,8,131,0,8,67,0,9,231,80,7,7,0,8,91,0,8,27,0,9,151,84,7,67,0,8,123,0,8,
-59,0,9,215,82,7,19,0,8,107,0,8,43,0,9,183,0,8,11,0,8,139,0,8,75,0,9,247,80,7,5,0,8,87,0,8,23,192,8,0,83,7,51,0,8,119,0,8,55,0,9,207,81,7,15,0,8,103,0,8,39,0,9,175,0,8,7,0,8,135,0,8,71,0,9,239,80,7,9,0,8,95,0,8,31,0,9,159,84,7,99,0,8,127,0,8,63,0,9,223,82,7,27,0,8,111,0,8,47,0,9,191,0,8,15,0,8,143,0,8,79,0,9,255],A=[80,5,1,87,5,257,83,5,17,91,5,4097,81,5,5,89,5,1025,85,5,65,93,5,16385,80,5,3,88,5,513,84,5,33,92,5,8193,82,5,9,90,5,2049,86,5,129,192,5,24577,80,5,2,87,5,385,83,5,25,91,5,6145,81,5,7,89,
-5,1537,85,5,97,93,5,24577,80,5,4,88,5,769,84,5,49,92,5,12289,82,5,13,90,5,3073,86,5,193,192,5,24577],ga=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],ia=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,112,112],aa=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],ha=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],K=15;b.inflate_trees_fixed=function(a,b,c,d){a[0]=
-9;b[0]=5;c[0]=B;d[0]=A;return g};var E=0,V=1,ma=2,Z=3,ba=4,da=5,ra=6,xa=7,la=8,ta=9,sa=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],W=0,na=1,oa=2,ca=3,pa=4,Fa=5,ua=6,z=7,ya=8,ja=9,ea=32,Ga=8,za=0,fa=1,Aa=2,Ba=3,Ca=4,Da=5,va=6,qa=7,Ea=12,ka=13,t=[0,0,255,255];f.prototype={inflateInit:function(a){this.istate=new e;a||(a=15);return this.istate.inflateInit(this,a)},inflate:function(a){return!this.istate?l:this.istate.inflate(this,a)},inflateEnd:function(){if(!this.istate)return l;var a=this.istate.inflateEnd(this);
-this.istate=null;return a},inflateSync:function(){return!this.istate?l:this.istate.inflateSync(this)},inflateSetDictionary:function(a,b){return!this.istate?l:this.istate.inflateSetDictionary(this,a,b)},read_byte:function(a){return this.next_in.subarray(a,a+1)[0]},read_buf:function(a,b){return this.next_in.subarray(a,a+b)}};var wa;a.zip?a.zip.Inflater=h:(wa=new h,a.addEventListener("message",function(b){b=b.data;b.append&&a.postMessage({onappend:!0,data:wa.append(b.data,function(b){a.postMessage({progress:!0,
-current:b})})});b.flush&&(wa.flush(),a.postMessage({onflush:!0}))},!1))})(this);
-function openpgp_msg_message(){this.text="";this.decrypt=function(a,b){return this.decryptAndVerifySignature(a,b).text};this.decryptAndVerifySignature=function(a,b,c){if(null==a||null==b||""==b)return null;a=b.decrypt(this,a.keymaterial);if(null==a)return null;var d,b=0,e=a.length,f=[];for(util.print_debug_hexstr_dump("openpgp.msg.messge decrypt:\n",a);b!=a.length&&null!=(d=openpgp_packet.read_packet(a,b,e));){if(8==d.tagType)this.text=d.decompress(),a=d.decompress();util.print_debug(d.toString());
-b+=d.headerLength+d.packetLength;38<b&&util.print_debug_hexstr_dump("openpgp.msg.messge decrypt:\n",a.substring(b));e=a.length-b;if(11==d.tagType)this.text=d.data,util.print_info("message successfully decrypted");if(19!=d.tagType&&2==d.tagType&&3>d.signatureType){if(!c||0==c.length)c=openpgp.keyring.getPublicKeysForKeyId(d.issuerKeyId);0==c.length?(util.print_warning("Unable to verify signature of issuer: "+util.hexstrdump(d.issuerKeyId)+". Public key not found in keyring."),f[f.length]=!1):d.verify(this.text.replace(/\r\n/g,
-"\n").replace(/\n/g,"\r\n"),c[0])&&c[0].obj.validate()?(util.print_info("Found Good Signature from "+c[0].obj.userIds[0].text+" (0x"+util.hexstrdump(c[0].obj.getKeyId()).substring(8)+")"),f[f.length]=!0):(util.print_error("Signature verification failed: Bad Signature from "+c[0].obj.userIds[0].text+" (0x"+util.hexstrdump(c[0].obj.getKeyId()).substring(8)+")"),f[f.length]=!1)}}if(""==this.text)this.text=a;return{text:this.text,validSignatures:f}};this.verifySignature=function(a){var b=!1;if(2==this.type){if(!a||
-0==a.length)if(4==this.signature.version)a=openpgp.keyring.getPublicKeysForKeyId(this.signature.issuerKeyId);else if(3==this.signature.version)a=openpgp.keyring.getPublicKeysForKeyId(this.signature.keyId);else return util.print_error("unknown signature type on message!"),!1;if(0==a.length)util.print_warning("Unable to verify signature of issuer: "+util.hexstrdump(this.signature.issuerKeyId)+". Public key not found in keyring.");else for(var c=0;c<a.length;c++){var d=this.text.replace(/\r\n/g,"\n").replace(/\n/g,
-"\r\n");this.signature.verify(d.substring(0,d.length-2),a[c])?(util.print_info("Found Good Signature from "+a[c].obj.userIds[c].text+" (0x"+util.hexstrdump(a[c].obj.getKeyId()).substring(8)+")"),b=!0):util.print_error("Signature verification failed: Bad Signature from "+a[c].obj.userIds[0].text+" (0x"+util.hexstrdump(a[0].obj.getKeyId()).substring(8)+")")}}return b};this.toString=function(){var a="Session Keys:\n";if(null!=this.sessionKeys)for(var b=0;b<this.sessionKeys.length;b++)a+=this.sessionKeys[b].toString();
-a+="\n\n EncryptedData:\n";null!=this.encryptedData&&(a+=this.encryptedData.toString());a+="\n\n Signature:\n";null!=this.signature&&(a+=this.signature.toString());a+="\n\n Text:\n";null!=this.signature&&(a+=this.text);return a}}
-function openpgp_type_mpi(){this.data=this.mpiByteLength=this.mpiBitLength=this.MPI=null;this.read=function(a,b){var c=b;this.mpiBitLength=a[c++].charCodeAt()<<8|a[c++].charCodeAt();this.mpiByteLength=(this.mpiBitLength-this.mpiBitLength%8)/8;0!=this.mpiBitLength%8&&this.mpiByteLength++;this.MPI=a.substring(c,c+this.mpiByteLength);this.data=a.substring(b,b+2+this.mpiByteLength);this.packetLength=this.mpiByteLength+2;return this};this.toBigInteger=function(){return new BigInteger(util.hexstrdump(this.MPI),
-16)};this.toString=function(){var a="    MPI("+this.mpiBitLength+"b/"+this.mpiByteLength+"B) : 0x",a=a+util.hexstrdump(this.MPI);return a+"\n"};this.create=function(a){this.MPI=a;var b=8*(a.length-1),c;a:for(var d=a.charCodeAt(0),e=0;9>e;e++)if(0==d>>e){c=e;break a}this.mpiBitLength=b+c;this.mpiByteLength=a.length;return this};this.toBin=function(){var a=String.fromCharCode(this.mpiBitLength>>8&255),a=a+String.fromCharCode(this.mpiBitLength&255);return a+=this.MPI};this.getByteLength=function(){return this.mpiByteLength}}
-function openpgp_type_keyid(){this.read_packet=function(a,b){this.bytes=a.substring(b,b+8);return this};this.toString=function(){return util.hexstrdump(this.bytes)}}
-function openpgp_type_s2k(){this.read=function(a,b){var c=b;this.type=a[c++].charCodeAt();switch(this.type){case 0:this.hashAlgorithm=a[c++].charCodeAt();this.s2kLength=1;break;case 1:this.hashAlgorithm=a[c++].charCodeAt();this.saltValue=a.substring(c,c+8);this.s2kLength=9;break;case 3:this.hashAlgorithm=a[c++].charCodeAt();this.saltValue=a.substring(c,c+8);c+=8;this.EXPBIAS=6;c=a[c++].charCodeAt();this.count=16+(c&15)<<(c>>4)+this.EXPBIAS;this.s2kLength=10;break;default:util.print_error("unknown s2k type! "+
-this.type)}return this};this.write=function(a,b,c,d,e){this.type=a;if(3==this.type)this.saltValue=d,this.hashAlgorithm=b,this.count=16+(e&15)<<(e>>4)+6,this.s2kLength=10;return this.produce_key(c)};this.produce_key=function(a,b){if(0==this.type)return openpgp_crypto_hashData(this.hashAlgorithm,a);if(1==this.type)return openpgp_crypto_hashData(this.hashAlgorithm,this.saltValue+a);if(3==this.type){var c=[];for(c[0]=this.saltValue+a;c.length*(this.saltValue+a).length<this.count;)c.push(this.saltValue+
-a);c=c.join("");c.length>this.count&&(c=c.substr(0,this.count));return b&&(24==b||32==b)?openpgp_crypto_hashData(this.hashAlgorithm,c)+openpgp_crypto_hashData(this.hashAlgorithm,String.fromCharCode(0)+c):openpgp_crypto_hashData(this.hashAlgorithm,c)}return null}}
-function openpgp_keyring(){this.init=function(){var a=JSON.parse(window.localStorage.getItem("privatekeys")),b=JSON.parse(window.localStorage.getItem("publickeys"));if(null==a||0==a.length)a=[];if(null==b||0==b.length)b=[];this.publicKeys=[];this.privateKeys=[];for(var c=0,d=0;d<a.length;d++){var e=openpgp.read_privateKey(a[d]);this.privateKeys[c]={armored:a[d],obj:e[0],keyId:e[0].getKeyId()};c++}for(d=c=0;d<b.length;d++)e=openpgp.read_publicKey(b[d]),null!=e[0]&&(this.publicKeys[c]={armored:b[d],
-obj:e[0],keyId:e[0].getKeyId()},c++)};this.hasPrivateKey=function(){return 0<this.privateKeys.length};this.store=function(){for(var a=[],b=0;b<this.privateKeys.length;b++)a[b]=this.privateKeys[b].armored;for(var c=[],b=0;b<this.publicKeys.length;b++)c[b]=this.publicKeys[b].armored;window.localStorage.setItem("privatekeys",JSON.stringify(a));window.localStorage.setItem("publickeys",JSON.stringify(c))};this.getPublicKeyForAddress=function(a){var b=[],c=a.split("<"),d="",d=1<c.length?c[1].split(">")[0]:
-a.trim(),d=d.toLowerCase();if(!util.emailRegEx.test(d))return b;for(a=0;a<this.publicKeys.length;a++)for(c=0;c<this.publicKeys[a].obj.userIds.length;c++)0<=this.publicKeys[a].obj.userIds[c].text.toLowerCase().indexOf(d)&&(b[b.length]=this.publicKeys[a]);return b};this.getPrivateKeyForAddress=function(a){var b=[],c=a.split("<"),d="",d=1<c.length?c[1].split(">")[0]:a.trim(),d=d.toLowerCase();if(!util.emailRegEx.test(d))return b;for(a=0;a<this.privateKeys.length;a++)for(c=0;c<this.privateKeys[a].obj.userIds.length;c++)0<=
-this.privateKeys[a].obj.userIds[c].text.toLowerCase().indexOf(d)&&(b[b.length]=this.privateKeys[a]);return b};this.getPublicKeysForKeyId=function(a){for(var b=[],c=0;c<this.publicKeys.length;c++)a==this.publicKeys[c].obj.getKeyId()&&(b[b.length]=this.publicKeys[c]);return b};this.getPrivateKeyForKeyId=function(a){for(var b=[],c=0;c<this.privateKeys.length;c++)if(a==this.privateKeys[c].obj.getKeyId()&&(b[b.length]={key:this.privateKeys[c],keymaterial:this.privateKeys[c].obj.privateKeyPacket}),null!=
-this.privateKeys[c].obj.subKeys)for(var d=this.privateKeys[c].obj.getSubKeyIds(),e=0;e<d.length;e++)a==util.hexstrdump(d[e])&&(b[b.length]={key:this.privateKeys[c],keymaterial:this.privateKeys[c].obj.subKeys[e]});return b};this.importPublicKey=function(a){for(var b=openpgp.read_publicKey(a),c=0;c<b.length;c++)this.publicKeys[this.publicKeys.length]={armored:a,obj:b[c],keyId:b[c].getKeyId()};return!0};this.importPrivateKey=function(a,b){var c=openpgp.read_privateKey(a);if(!c[0].decryptSecretMPIs(b))return!1;
-for(var d=0;d<c.length;d++)this.privateKeys[this.privateKeys.length]={armored:a,obj:c[d],keyId:c[d].getKeyId()};return!0};this.exportPublicKey=function(a){return this.publicKey[a]};this.removePublicKey=function(a){a=this.publicKeys.splice(a,1);this.store();return a};this.exportPrivateKey=function(a){return this.privateKeys[a]};this.removePrivateKey=function(a){a=this.privateKeys.splice(a,1);this.store();return a}}
-var Util=function(){this.emailRegEx=/[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;this.hexdump=function(a){for(var b=[],c=a.length,d=0,e,f=0;d<c;){for(e=a.charCodeAt(d++).toString(16);2>e.length;)e="0"+e;b.push(" "+e);f++;0==f%32&&b.push("\n           ")}return b.join("")};this.hexstrdump=function(a){if(null==a)return"";for(var b=[],c=a.length,d=0,e;d<c;){for(e=a[d++].charCodeAt().toString(16);2>e.length;)e=
-"0"+e;b.push(""+e)}return b.join("")};this.hex2bin=function(a){for(var b="",c=0;c<a.length;c+=2)b+=String.fromCharCode(parseInt(a.substr(c,2),16));return b};this.hexidump=function(a){for(var b=[],c=a.length,d=0,e;d<c;){for(e=a[d++].toString(16);2>e.length;)e="0"+e;b.push(""+e)}return b.join("")};this.str2bin=function(a){for(var b=[],c=0;c<a.length;c++)b[c]=a.charCodeAt(c);return b};this.bin2str=function(a){for(var b=[],c=0;c<a.length;c++)b.push(String.fromCharCode(a[c]));return b.join("")};this.str2Uint8Array=
-function(a){for(var b=new Uint8Array(new ArrayBuffer(a.length)),c=0;c<a.length;c++)b[c]=a.charCodeAt(c);return b};this.Uint8Array2str=function(a){var b=[];for(n=0;n<a.length;n++)b[n]=String.fromCharCode(a[n]);return b.join("")};this.calc_checksum=function(a){for(var b={s:0,add:function(a){this.s=(this.s+a)%65536}},c=0;c<a.length;c++)b.add(a.charCodeAt(c));return b.s};this.print_debug=function(a){openpgp.config.debug&&(a=openpgp_encoding_html_encode(a),showMessages('<tt><p style="background-color: #ffffff; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;">'+
-a.replace(/\n/g,"<br>")+"</p></tt>"))};this.print_debug_hexstr_dump=function(a,b){openpgp.config.debug&&(a+=this.hexstrdump(b),a=openpgp_encoding_html_encode(a),showMessages('<tt><p style="background-color: #ffffff; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;">'+a.replace(/\n/g,"<br>")+"</p></tt>"))};this.print_error=function(a){a=openpgp_encoding_html_encode(a);showMessages('<p style="font-size: 80%; background-color: #FF8888; margin:0; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;"><span style="color: #888;"><b>ERROR:</b></span>\t'+
-a.replace(/\n/g,"<br>")+"</p>")};this.print_info=function(a){a=openpgp_encoding_html_encode(a);showMessages('<p style="font-size: 80%; background-color: #88FF88; margin:0; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;"><span style="color: #888;"><b>INFO:</b></span>\t'+a.replace(/\n/g,"<br>")+"</p>")};this.print_warning=function(a){a=openpgp_encoding_html_encode(a);showMessages('<p style="font-size: 80%; background-color: #FFAA88; margin:0; width: 652px; word-break: break-word; padding: 5px; border-bottom: 1px solid black;"><span style="color: #888;"><b>WARNING:</b></span>\t'+
-a.replace(/\n/g,"<br>")+"</p>")};this.getLeftNBits=function(a,b){var c=b%8;return 0==c?a.substring(0,b/8):this.shiftRight(a.substring(0,(b-c)/8+1),8-c)};this.shiftRight=function(a,b){var c=util.str2bin(a);if(0!=b%8)for(var d=c.length-1;0<=d;d--)c[d]>>=b%8,0<d&&(c[d]|=c[d-1]<<8-b%8&255);else return a;return util.bin2str(c)};this.get_hashAlgorithmString=function(a){switch(a){case 1:return"MD5";case 2:return"SHA1";case 3:return"RIPEMD160";case 8:return"SHA256";case 9:return"SHA384";case 10:return"SHA512";
-case 11:return"SHA224"}return"unknown"}},util=new Util;
+16^a.charCodeAt(c+9))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+10))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+11))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+12))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+13))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+14))&255],b=b<<8^crc_table[(b>>16^a.charCodeAt(c+15))&255],c+=16;for(var d=c;d<a.length;d++)b=b<<8^crc_table[(b>>16^a.charCodeAt(c++))&255];return b&16777215};
diff --git a/src/compression/zip/zip.js b/src/compression/zip/zip.js
deleted file mode 100644
index 32d0f9bc..00000000
--- a/src/compression/zip/zip.js
+++ /dev/null
@@ -1,2178 +0,0 @@
-/*
- Copyright (c) 2012 Gildas Lormeau. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the distribution.
-
- 3. The names of the authors may not be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
- INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
- OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-(function(obj) {
-
-	obj.zip = {
-		useWebWorkers : false
-	};
-
-})(this);
-
-// include inflate.js
-
-/*
- * zip.js and include.js are merged in one file because of a dependency in the
- * execution order: zip.Inflater is only defined if inflate.js is executed after zip.js
- */
-
-(function(obj) {
-
-	// Global
-	var MAX_BITS = 15;
-
-	var Z_OK = 0;
-	var Z_STREAM_END = 1;
-	var Z_NEED_DICT = 2;
-	var Z_STREAM_ERROR = -2;
-	var Z_DATA_ERROR = -3;
-	var Z_MEM_ERROR = -4;
-	var Z_BUF_ERROR = -5;
-
-	var inflate_mask = [ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, 0x000003ff,
-			0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff ];
-
-	var MANY = 1440;
-
-	var MAX_WBITS = 15; // 32K LZ77 window
-	var DEF_WBITS = MAX_WBITS;
-
-	// JZlib version : "1.0.2"
-	var Z_NO_FLUSH = 0;
-	var Z_FINISH = 4;
-
-	// InfTree
-	var fixed_bl = 9;
-	var fixed_bd = 5;
-
-	var fixed_tl = [ 96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115, 82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9, 192, 80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 160, 0, 8, 0,
-			0, 8, 128, 0, 8, 64, 0, 9, 224, 80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 144, 83, 7, 59, 0, 8, 120, 0, 8, 56, 0, 9, 208, 81, 7, 17, 0, 8, 104, 0, 8, 40,
-			0, 9, 176, 0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 240, 80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8, 227, 83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 200, 81, 7, 13,
-			0, 8, 100, 0, 8, 36, 0, 9, 168, 0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 232, 80, 7, 8, 0, 8, 92, 0, 8, 28, 0, 9, 152, 84, 7, 83, 0, 8, 124, 0, 8, 60,
-			0, 9, 216, 82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 184, 0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9, 248, 80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163, 83, 7,
-			35, 0, 8, 114, 0, 8, 50, 0, 9, 196, 81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 164, 0, 8, 2, 0, 8, 130, 0, 8, 66, 0, 9, 228, 80, 7, 7, 0, 8, 90, 0, 8,
-			26, 0, 9, 148, 84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 212, 82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9, 180, 0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 244, 80,
-			7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0, 83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 204, 81, 7, 15, 0, 8, 102, 0, 8, 38, 0, 9, 172, 0, 8, 6, 0, 8, 134, 0,
-			8, 70, 0, 9, 236, 80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 156, 84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9, 220, 82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 188, 0,
-			8, 14, 0, 8, 142, 0, 8, 78, 0, 9, 252, 96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131, 82, 7, 31, 0, 8, 113, 0, 8, 49, 0, 9, 194, 80, 7, 10, 0, 8, 97,
-			0, 8, 33, 0, 9, 162, 0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 226, 80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9, 146, 83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 210,
-			81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 178, 0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 242, 80, 7, 4, 0, 8, 85, 0, 8, 21, 80, 8, 258, 83, 7, 43, 0, 8, 117,
-			0, 8, 53, 0, 9, 202, 81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 170, 0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9, 234, 80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 154,
-			84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 218, 82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 186, 0, 8, 13, 0, 8, 141, 0, 8, 77, 0, 9, 250, 80, 7, 3, 0, 8, 83,
-			0, 8, 19, 85, 8, 195, 83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 198, 81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9, 166, 0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 230,
-			80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 150, 84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 214, 82, 7, 19, 0, 8, 107, 0, 8, 43, 0, 9, 182, 0, 8, 11, 0, 8, 139,
-			0, 8, 75, 0, 9, 246, 80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0, 83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9, 206, 81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 174,
-			0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 238, 80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 158, 84, 7, 99, 0, 8, 127, 0, 8, 63, 0, 9, 222, 82, 7, 27, 0, 8, 111,
-			0, 8, 47, 0, 9, 190, 0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 254, 96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115, 82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9,
-			193, 80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 161, 0, 8, 0, 0, 8, 128, 0, 8, 64, 0, 9, 225, 80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 145, 83, 7, 59, 0, 8,
-			120, 0, 8, 56, 0, 9, 209, 81, 7, 17, 0, 8, 104, 0, 8, 40, 0, 9, 177, 0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 241, 80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8,
-			227, 83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 201, 81, 7, 13, 0, 8, 100, 0, 8, 36, 0, 9, 169, 0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 233, 80, 7, 8, 0, 8,
-			92, 0, 8, 28, 0, 9, 153, 84, 7, 83, 0, 8, 124, 0, 8, 60, 0, 9, 217, 82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 185, 0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9,
-			249, 80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163, 83, 7, 35, 0, 8, 114, 0, 8, 50, 0, 9, 197, 81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 165, 0, 8, 2, 0, 8,
-			130, 0, 8, 66, 0, 9, 229, 80, 7, 7, 0, 8, 90, 0, 8, 26, 0, 9, 149, 84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 213, 82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9,
-			181, 0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 245, 80, 7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0, 83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 205, 81, 7, 15, 0, 8,
-			102, 0, 8, 38, 0, 9, 173, 0, 8, 6, 0, 8, 134, 0, 8, 70, 0, 9, 237, 80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 157, 84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9,
-			221, 82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 189, 0, 8, 14, 0, 8, 142, 0, 8, 78, 0, 9, 253, 96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131, 82, 7, 31, 0,
-			8, 113, 0, 8, 49, 0, 9, 195, 80, 7, 10, 0, 8, 97, 0, 8, 33, 0, 9, 163, 0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 227, 80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9,
-			147, 83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 211, 81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 179, 0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 243, 80, 7, 4, 0, 8,
-			85, 0, 8, 21, 80, 8, 258, 83, 7, 43, 0, 8, 117, 0, 8, 53, 0, 9, 203, 81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 171, 0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9,
-			235, 80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 155, 84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 219, 82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 187, 0, 8, 13, 0, 8,
-			141, 0, 8, 77, 0, 9, 251, 80, 7, 3, 0, 8, 83, 0, 8, 19, 85, 8, 195, 83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 199, 81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9,
-			167, 0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 231, 80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 151, 84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 215, 82, 7, 19, 0, 8,
-			107, 0, 8, 43, 0, 9, 183, 0, 8, 11, 0, 8, 139, 0, 8, 75, 0, 9, 247, 80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0, 83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9,
-			207, 81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 175, 0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 239, 80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 159, 84, 7, 99, 0, 8,
-			127, 0, 8, 63, 0, 9, 223, 82, 7, 27, 0, 8, 111, 0, 8, 47, 0, 9, 191, 0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 255 ];
-	var fixed_td = [ 80, 5, 1, 87, 5, 257, 83, 5, 17, 91, 5, 4097, 81, 5, 5, 89, 5, 1025, 85, 5, 65, 93, 5, 16385, 80, 5, 3, 88, 5, 513, 84, 5, 33, 92, 5,
-			8193, 82, 5, 9, 90, 5, 2049, 86, 5, 129, 192, 5, 24577, 80, 5, 2, 87, 5, 385, 83, 5, 25, 91, 5, 6145, 81, 5, 7, 89, 5, 1537, 85, 5, 97, 93, 5,
-			24577, 80, 5, 4, 88, 5, 769, 84, 5, 49, 92, 5, 12289, 82, 5, 13, 90, 5, 3073, 86, 5, 193, 192, 5, 24577 ];
-
-	// Tables for deflate from PKZIP's appnote.txt.
-	var cplens = [ // Copy lengths for literal codes 257..285
-	3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 ];
-
-	// see note #13 above about 258
-	var cplext = [ // Extra bits for literal codes 257..285
-	0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
-	];
-
-	var cpdist = [ // Copy offsets for distance codes 0..29
-	1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 ];
-
-	var cpdext = [ // Extra bits for distance codes
-	0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 ];
-
-	// If BMAX needs to be larger than 16, then h and x[] should be uLong.
-	var BMAX = 15; // maximum bit length of any code
-
-	function InfTree() {
-		var that = this;
-
-		var hn; // hufts used in space
-		var v; // work area for huft_build
-		var c; // bit length count table
-		var r; // table entry for structure assignment
-		var u; // table stack
-		var x; // bit offsets, then code stack
-
-		function huft_build(b, // code lengths in bits (all assumed <=
-		// BMAX)
-		bindex, n, // number of codes (assumed <= 288)
-		s, // number of simple-valued codes (0..s-1)
-		d, // list of base values for non-simple codes
-		e, // list of extra bits for non-simple codes
-		t, // result: starting table
-		m, // maximum lookup bits, returns actual
-		hp,// space for trees
-		hn,// hufts used in space
-		v // working area: values in order of bit length
-		) {
-			// Given a list of code lengths and a maximum table size, make a set of
-			// tables to decode that set of codes. Return Z_OK on success,
-			// Z_BUF_ERROR
-			// if the given code set is incomplete (the tables are still built in
-			// this
-			// case), Z_DATA_ERROR if the input is invalid (an over-subscribed set
-			// of
-			// lengths), or Z_MEM_ERROR if not enough memory.
-
-			var a; // counter for codes of length k
-			var f; // i repeats in table every f entries
-			var g; // maximum code length
-			var h; // table level
-			var i; // counter, current code
-			var j; // counter
-			var k; // number of bits in current code
-			var l; // bits per table (returned in m)
-			var mask; // (1 << w) - 1, to avoid cc -O bug on HP
-			var p; // pointer into c[], b[], or v[]
-			var q; // points to current table
-			var w; // bits before this table == (l * h)
-			var xp; // pointer into x
-			var y; // number of dummy codes added
-			var z; // number of entries in current table
-
-			// Generate counts for each bit length
-
-			p = 0;
-			i = n;
-			do {
-				c[b[bindex + p]]++;
-				p++;
-				i--; // assume all entries <= BMAX
-			} while (i !== 0);
-
-			if (c[0] == n) { // null input--all zero length codes
-				t[0] = -1;
-				m[0] = 0;
-				return Z_OK;
-			}
-
-			// Find minimum and maximum length, bound *m by those
-			l = m[0];
-			for (j = 1; j <= BMAX; j++)
-				if (c[j] !== 0)
-					break;
-			k = j; // minimum code length
-			if (l < j) {
-				l = j;
-			}
-			for (i = BMAX; i !== 0; i--) {
-				if (c[i] !== 0)
-					break;
-			}
-			g = i; // maximum code length
-			if (l > i) {
-				l = i;
-			}
-			m[0] = l;
-
-			// Adjust last length count to fill out codes, if needed
-			for (y = 1 << j; j < i; j++, y <<= 1) {
-				if ((y -= c[j]) < 0) {
-					return Z_DATA_ERROR;
-				}
-			}
-			if ((y -= c[i]) < 0) {
-				return Z_DATA_ERROR;
-			}
-			c[i] += y;
-
-			// Generate starting offsets into the value table for each length
-			x[1] = j = 0;
-			p = 1;
-			xp = 2;
-			while (--i !== 0) { // note that i == g from above
-				x[xp] = (j += c[p]);
-				xp++;
-				p++;
-			}
-
-			// Make a table of values in order of bit lengths
-			i = 0;
-			p = 0;
-			do {
-				if ((j = b[bindex + p]) !== 0) {
-					v[x[j]++] = i;
-				}
-				p++;
-			} while (++i < n);
-			n = x[g]; // set n to length of v
-
-			// Generate the Huffman codes and for each, make the table entries
-			x[0] = i = 0; // first Huffman code is zero
-			p = 0; // grab values in bit order
-			h = -1; // no tables yet--level -1
-			w = -l; // bits decoded == (l * h)
-			u[0] = 0; // just to keep compilers happy
-			q = 0; // ditto
-			z = 0; // ditto
-
-			// go through the bit lengths (k already is bits in shortest code)
-			for (; k <= g; k++) {
-				a = c[k];
-				while (a-- !== 0) {
-					// here i is the Huffman code of length k bits for value *p
-					// make tables up to required level
-					while (k > w + l) {
-						h++;
-						w += l; // previous table always l bits
-						// compute minimum size table less than or equal to l bits
-						z = g - w;
-						z = (z > l) ? l : z; // table size upper limit
-						if ((f = 1 << (j = k - w)) > a + 1) { // try a k-w bit table
-							// too few codes for
-							// k-w bit table
-							f -= a + 1; // deduct codes from patterns left
-							xp = k;
-							if (j < z) {
-								while (++j < z) { // try smaller tables up to z bits
-									if ((f <<= 1) <= c[++xp])
-										break; // enough codes to use up j bits
-									f -= c[xp]; // else deduct codes from patterns
-								}
-							}
-						}
-						z = 1 << j; // table entries for j-bit table
-
-						// allocate new table
-						if (hn[0] + z > MANY) { // (note: doesn't matter for fixed)
-							return Z_DATA_ERROR; // overflow of MANY
-						}
-						u[h] = q = /* hp+ */hn[0]; // DEBUG
-						hn[0] += z;
-
-						// connect to last table, if there is one
-						if (h !== 0) {
-							x[h] = i; // save pattern for backing up
-							r[0] = /* (byte) */j; // bits in this table
-							r[1] = /* (byte) */l; // bits to dump before this table
-							j = i >>> (w - l);
-							r[2] = /* (int) */(q - u[h - 1] - j); // offset to this table
-							hp.set(r, (u[h - 1] + j) * 3);
-							// to
-							// last
-							// table
-						} else {
-							t[0] = q; // first table is returned result
-						}
-					}
-
-					// set up table entry in r
-					r[1] = /* (byte) */(k - w);
-					if (p >= n) {
-						r[0] = 128 + 64; // out of values--invalid code
-					} else if (v[p] < s) {
-						r[0] = /* (byte) */(v[p] < 256 ? 0 : 32 + 64); // 256 is
-						// end-of-block
-						r[2] = v[p++]; // simple code is just the value
-					} else {
-						r[0] = /* (byte) */(e[v[p] - s] + 16 + 64); // non-simple--look
-						// up in lists
-						r[2] = d[v[p++] - s];
-					}
-
-					// fill code-like entries with r
-					f = 1 << (k - w);
-					for (j = i >>> w; j < z; j += f) {
-						hp.set(r, (q + j) * 3);
-					}
-
-					// backwards increment the k-bit code i
-					for (j = 1 << (k - 1); (i & j) !== 0; j >>>= 1) {
-						i ^= j;
-					}
-					i ^= j;
-
-					// backup over finished tables
-					mask = (1 << w) - 1; // needed on HP, cc -O bug
-					while ((i & mask) != x[h]) {
-						h--; // don't need to update q
-						w -= l;
-						mask = (1 << w) - 1;
-					}
-				}
-			}
-			// Return Z_BUF_ERROR if we were given an incomplete table
-			return y !== 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
-		}
-
-		function initWorkArea(vsize) {
-			var i;
-			if (!hn) {
-				hn = []; // []; //new Array(1);
-				v = []; // new Array(vsize);
-				c = new Int32Array(BMAX + 1); // new Array(BMAX + 1);
-				r = []; // new Array(3);
-				u = new Int32Array(BMAX); // new Array(BMAX);
-				x = new Int32Array(BMAX + 1); // new Array(BMAX + 1);
-			}
-			if (v.length < vsize) {
-				v = []; // new Array(vsize);
-			}
-			for (i = 0; i < vsize; i++) {
-				v[i] = 0;
-			}
-			for (i = 0; i < BMAX + 1; i++) {
-				c[i] = 0;
-			}
-			for (i = 0; i < 3; i++) {
-				r[i] = 0;
-			}
-			// for(int i=0; i<BMAX; i++){u[i]=0;}
-			u.set(c.subarray(0, BMAX), 0);
-			// for(int i=0; i<BMAX+1; i++){x[i]=0;}
-			x.set(c.subarray(0, BMAX + 1), 0);
-		}
-
-		that.inflate_trees_bits = function(c, // 19 code lengths
-		bb, // bits tree desired/actual depth
-		tb, // bits tree result
-		hp, // space for trees
-		z // for messages
-		) {
-			var result;
-			initWorkArea(19);
-			hn[0] = 0;
-			result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
-
-			if (result == Z_DATA_ERROR) {
-				z.msg = "oversubscribed dynamic bit lengths tree";
-			} else if (result == Z_BUF_ERROR || bb[0] === 0) {
-				z.msg = "incomplete dynamic bit lengths tree";
-				result = Z_DATA_ERROR;
-			}
-			return result;
-		};
-
-		that.inflate_trees_dynamic = function(nl, // number of literal/length codes
-		nd, // number of distance codes
-		c, // that many (total) code lengths
-		bl, // literal desired/actual bit depth
-		bd, // distance desired/actual bit depth
-		tl, // literal/length tree result
-		td, // distance tree result
-		hp, // space for trees
-		z // for messages
-		) {
-			var result;
-
-			// build literal/length tree
-			initWorkArea(288);
-			hn[0] = 0;
-			result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
-			if (result != Z_OK || bl[0] === 0) {
-				if (result == Z_DATA_ERROR) {
-					z.msg = "oversubscribed literal/length tree";
-				} else if (result != Z_MEM_ERROR) {
-					z.msg = "incomplete literal/length tree";
-					result = Z_DATA_ERROR;
-				}
-				return result;
-			}
-
-			// build distance tree
-			initWorkArea(288);
-			result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
-
-			if (result != Z_OK || (bd[0] === 0 && nl > 257)) {
-				if (result == Z_DATA_ERROR) {
-					z.msg = "oversubscribed distance tree";
-				} else if (result == Z_BUF_ERROR) {
-					z.msg = "incomplete distance tree";
-					result = Z_DATA_ERROR;
-				} else if (result != Z_MEM_ERROR) {
-					z.msg = "empty distance tree with lengths";
-					result = Z_DATA_ERROR;
-				}
-				return result;
-			}
-
-			return Z_OK;
-		};
-
-	}
-
-	InfTree.inflate_trees_fixed = function(bl, // literal desired/actual bit depth
-	bd, // distance desired/actual bit depth
-	tl,// literal/length tree result
-	td,// distance tree result
-	z // for memory allocation
-	) {
-		bl[0] = fixed_bl;
-		bd[0] = fixed_bd;
-		tl[0] = fixed_tl;
-		td[0] = fixed_td;
-		return Z_OK;
-	};
-
-	// InfCodes
-
-	// waiting for "i:"=input,
-	// "o:"=output,
-	// "x:"=nothing
-	var START = 0; // x: set up for LEN
-	var LEN = 1; // i: get length/literal/eob next
-	var LENEXT = 2; // i: getting length extra (have base)
-	var DIST = 3; // i: get distance next
-	var DISTEXT = 4;// i: getting distance extra
-	var COPY = 5; // o: copying bytes in window, waiting
-	// for space
-	var LIT = 6; // o: got literal, waiting for output
-	// space
-	var WASH = 7; // o: got eob, possibly still output
-	// waiting
-	var END = 8; // x: got eob and all data flushed
-	var BADCODE = 9;// x: got error
-
-	function InfCodes() {
-		var that = this;
-
-		var mode; // current inflate_codes mode
-
-		// mode dependent information
-		var len = 0;
-
-		var tree; // pointer into tree
-		var tree_index = 0;
-		var need = 0; // bits needed
-
-		var lit = 0;
-
-		// if EXT or COPY, where and how much
-		var get = 0; // bits to get for extra
-		var dist = 0; // distance back to copy from
-
-		var lbits = 0; // ltree bits decoded per branch
-		var dbits = 0; // dtree bits decoder per branch
-		var ltree; // literal/length/eob tree
-		var ltree_index = 0; // literal/length/eob tree
-		var dtree; // distance tree
-		var dtree_index = 0; // distance tree
-
-		// Called with number of bytes left to write in window at least 258
-		// (the maximum string length) and number of input bytes available
-		// at least ten. The ten bytes are six bytes for the longest length/
-		// distance pair plus four bytes for overloading the bit buffer.
-
-		function inflate_fast(bl, bd, tl, tl_index, td, td_index, s, z) {
-			var t; // temporary pointer
-			var tp; // temporary pointer
-			var tp_index; // temporary pointer
-			var e; // extra bits or operation
-			var b; // bit buffer
-			var k; // bits in bit buffer
-			var p; // input data pointer
-			var n; // bytes available there
-			var q; // output window write pointer
-			var m; // bytes to end of window or read pointer
-			var ml; // mask for literal/length tree
-			var md; // mask for distance tree
-			var c; // bytes to copy
-			var d; // distance back to copy from
-			var r; // copy source pointer
-
-			var tp_index_t_3; // (tp_index+t)*3
-
-			// load input, output, bit values
-			p = z.next_in_index;
-			n = z.avail_in;
-			b = s.bitb;
-			k = s.bitk;
-			q = s.write;
-			m = q < s.read ? s.read - q - 1 : s.end - q;
-
-			// initialize masks
-			ml = inflate_mask[bl];
-			md = inflate_mask[bd];
-
-			// do until not enough input or output space for fast loop
-			do { // assume called with m >= 258 && n >= 10
-				// get literal/length code
-				while (k < (20)) { // max bits for literal/length code
-					n--;
-					b |= (z.read_byte(p++) & 0xff) << k;
-					k += 8;
-				}
-
-				t = b & ml;
-				tp = tl;
-				tp_index = tl_index;
-				tp_index_t_3 = (tp_index + t) * 3;
-				if ((e = tp[tp_index_t_3]) === 0) {
-					b >>= (tp[tp_index_t_3 + 1]);
-					k -= (tp[tp_index_t_3 + 1]);
-
-					s.window[q++] = /* (byte) */tp[tp_index_t_3 + 2];
-					m--;
-					continue;
-				}
-				do {
-
-					b >>= (tp[tp_index_t_3 + 1]);
-					k -= (tp[tp_index_t_3 + 1]);
-
-					if ((e & 16) !== 0) {
-						e &= 15;
-						c = tp[tp_index_t_3 + 2] + (/* (int) */b & inflate_mask[e]);
-
-						b >>= e;
-						k -= e;
-
-						// decode distance base of block to copy
-						while (k < (15)) { // max bits for distance code
-							n--;
-							b |= (z.read_byte(p++) & 0xff) << k;
-							k += 8;
-						}
-
-						t = b & md;
-						tp = td;
-						tp_index = td_index;
-						tp_index_t_3 = (tp_index + t) * 3;
-						e = tp[tp_index_t_3];
-
-						do {
-
-							b >>= (tp[tp_index_t_3 + 1]);
-							k -= (tp[tp_index_t_3 + 1]);
-
-							if ((e & 16) !== 0) {
-								// get extra bits to add to distance base
-								e &= 15;
-								while (k < (e)) { // get extra bits (up to 13)
-									n--;
-									b |= (z.read_byte(p++) & 0xff) << k;
-									k += 8;
-								}
-
-								d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
-
-								b >>= (e);
-								k -= (e);
-
-								// do the copy
-								m -= c;
-								if (q >= d) { // offset before dest
-									// just copy
-									r = q - d;
-									if (q - r > 0 && 2 > (q - r)) {
-										s.window[q++] = s.window[r++]; // minimum
-										// count is
-										// three,
-										s.window[q++] = s.window[r++]; // so unroll
-										// loop a
-										// little
-										c -= 2;
-									} else {
-										s.window.set(s.window.subarray(r, r + 2), q);
-										q += 2;
-										r += 2;
-										c -= 2;
-									}
-								} else { // else offset after destination
-									r = q - d;
-									do {
-										r += s.end; // force pointer in window
-									} while (r < 0); // covers invalid distances
-									e = s.end - r;
-									if (c > e) { // if source crosses,
-										c -= e; // wrapped copy
-										if (q - r > 0 && e > (q - r)) {
-											do {
-												s.window[q++] = s.window[r++];
-											} while (--e !== 0);
-										} else {
-											s.window.set(s.window.subarray(r, r + e), q);
-											q += e;
-											r += e;
-											e = 0;
-										}
-										r = 0; // copy rest from start of window
-									}
-
-								}
-
-								// copy all or what's left
-								if (q - r > 0 && c > (q - r)) {
-									do {
-										s.window[q++] = s.window[r++];
-									} while (--c !== 0);
-								} else {
-									s.window.set(s.window.subarray(r, r + c), q);
-									q += c;
-									r += c;
-									c = 0;
-								}
-								break;
-							} else if ((e & 64) === 0) {
-								t += tp[tp_index_t_3 + 2];
-								t += (b & inflate_mask[e]);
-								tp_index_t_3 = (tp_index + t) * 3;
-								e = tp[tp_index_t_3];
-							} else {
-								z.msg = "invalid distance code";
-
-								c = z.avail_in - n;
-								c = (k >> 3) < c ? k >> 3 : c;
-								n += c;
-								p -= c;
-								k -= c << 3;
-
-								s.bitb = b;
-								s.bitk = k;
-								z.avail_in = n;
-								z.total_in += p - z.next_in_index;
-								z.next_in_index = p;
-								s.write = q;
-
-								return Z_DATA_ERROR;
-							}
-						} while (true);
-						break;
-					}
-
-					if ((e & 64) === 0) {
-						t += tp[tp_index_t_3 + 2];
-						t += (b & inflate_mask[e]);
-						tp_index_t_3 = (tp_index + t) * 3;
-						if ((e = tp[tp_index_t_3]) === 0) {
-
-							b >>= (tp[tp_index_t_3 + 1]);
-							k -= (tp[tp_index_t_3 + 1]);
-
-							s.window[q++] = /* (byte) */tp[tp_index_t_3 + 2];
-							m--;
-							break;
-						}
-					} else if ((e & 32) !== 0) {
-
-						c = z.avail_in - n;
-						c = (k >> 3) < c ? k >> 3 : c;
-						n += c;
-						p -= c;
-						k -= c << 3;
-
-						s.bitb = b;
-						s.bitk = k;
-						z.avail_in = n;
-						z.total_in += p - z.next_in_index;
-						z.next_in_index = p;
-						s.write = q;
-
-						return Z_STREAM_END;
-					} else {
-						z.msg = "invalid literal/length code";
-
-						c = z.avail_in - n;
-						c = (k >> 3) < c ? k >> 3 : c;
-						n += c;
-						p -= c;
-						k -= c << 3;
-
-						s.bitb = b;
-						s.bitk = k;
-						z.avail_in = n;
-						z.total_in += p - z.next_in_index;
-						z.next_in_index = p;
-						s.write = q;
-
-						return Z_DATA_ERROR;
-					}
-				} while (true);
-			} while (m >= 258 && n >= 10);
-
-			// not enough input or output--restore pointers and return
-			c = z.avail_in - n;
-			c = (k >> 3) < c ? k >> 3 : c;
-			n += c;
-			p -= c;
-			k -= c << 3;
-
-			s.bitb = b;
-			s.bitk = k;
-			z.avail_in = n;
-			z.total_in += p - z.next_in_index;
-			z.next_in_index = p;
-			s.write = q;
-
-			return Z_OK;
-		}
-
-		that.init = function(bl, bd, tl, tl_index, td, td_index, z) {
-			mode = START;
-			lbits = /* (byte) */bl;
-			dbits = /* (byte) */bd;
-			ltree = tl;
-			ltree_index = tl_index;
-			dtree = td;
-			dtree_index = td_index;
-			tree = null;
-		};
-
-		that.proc = function(s, z, r) {
-			var j; // temporary storage
-			var t; // temporary pointer
-			var tindex; // temporary pointer
-			var e; // extra bits or operation
-			var b = 0; // bit buffer
-			var k = 0; // bits in bit buffer
-			var p = 0; // input data pointer
-			var n; // bytes available there
-			var q; // output window write pointer
-			var m; // bytes to end of window or read pointer
-			var f; // pointer to copy strings from
-
-			// copy input/output information to locals (UPDATE macro restores)
-			p = z.next_in_index;
-			n = z.avail_in;
-			b = s.bitb;
-			k = s.bitk;
-			q = s.write;
-			m = q < s.read ? s.read - q - 1 : s.end - q;
-
-			// process input and output based on current state
-			while (true) {
-				switch (mode) {
-				// waiting for "i:"=input, "o:"=output, "x:"=nothing
-				case START: // x: set up for LEN
-					if (m >= 258 && n >= 10) {
-
-						s.bitb = b;
-						s.bitk = k;
-						z.avail_in = n;
-						z.total_in += p - z.next_in_index;
-						z.next_in_index = p;
-						s.write = q;
-						r = inflate_fast(lbits, dbits, ltree, ltree_index, dtree, dtree_index, s, z);
-
-						p = z.next_in_index;
-						n = z.avail_in;
-						b = s.bitb;
-						k = s.bitk;
-						q = s.write;
-						m = q < s.read ? s.read - q - 1 : s.end - q;
-
-						if (r != Z_OK) {
-							mode = r == Z_STREAM_END ? WASH : BADCODE;
-							break;
-						}
-					}
-					need = lbits;
-					tree = ltree;
-					tree_index = ltree_index;
-
-					mode = LEN;
-				case LEN: // i: get length/literal/eob next
-					j = need;
-
-					while (k < (j)) {
-						if (n !== 0)
-							r = Z_OK;
-						else {
-
-							s.bitb = b;
-							s.bitk = k;
-							z.avail_in = n;
-							z.total_in += p - z.next_in_index;
-							z.next_in_index = p;
-							s.write = q;
-							return s.inflate_flush(z, r);
-						}
-						n--;
-						b |= (z.read_byte(p++) & 0xff) << k;
-						k += 8;
-					}
-
-					tindex = (tree_index + (b & inflate_mask[j])) * 3;
-
-					b >>>= (tree[tindex + 1]);
-					k -= (tree[tindex + 1]);
-
-					e = tree[tindex];
-
-					if (e === 0) { // literal
-						lit = tree[tindex + 2];
-						mode = LIT;
-						break;
-					}
-					if ((e & 16) !== 0) { // length
-						get = e & 15;
-						len = tree[tindex + 2];
-						mode = LENEXT;
-						break;
-					}
-					if ((e & 64) === 0) { // next table
-						need = e;
-						tree_index = tindex / 3 + tree[tindex + 2];
-						break;
-					}
-					if ((e & 32) !== 0) { // end of block
-						mode = WASH;
-						break;
-					}
-					mode = BADCODE; // invalid code
-					z.msg = "invalid literal/length code";
-					r = Z_DATA_ERROR;
-
-					s.bitb = b;
-					s.bitk = k;
-					z.avail_in = n;
-					z.total_in += p - z.next_in_index;
-					z.next_in_index = p;
-					s.write = q;
-					return s.inflate_flush(z, r);
-
-				case LENEXT: // i: getting length extra (have base)
-					j = get;
-
-					while (k < (j)) {
-						if (n !== 0)
-							r = Z_OK;
-						else {
-
-							s.bitb = b;
-							s.bitk = k;
-							z.avail_in = n;
-							z.total_in += p - z.next_in_index;
-							z.next_in_index = p;
-							s.write = q;
-							return s.inflate_flush(z, r);
-						}
-						n--;
-						b |= (z.read_byte(p++) & 0xff) << k;
-						k += 8;
-					}
-
-					len += (b & inflate_mask[j]);
-
-					b >>= j;
-					k -= j;
-
-					need = dbits;
-					tree = dtree;
-					tree_index = dtree_index;
-					mode = DIST;
-				case DIST: // i: get distance next
-					j = need;
-
-					while (k < (j)) {
-						if (n !== 0)
-							r = Z_OK;
-						else {
-
-							s.bitb = b;
-							s.bitk = k;
-							z.avail_in = n;
-							z.total_in += p - z.next_in_index;
-							z.next_in_index = p;
-							s.write = q;
-							return s.inflate_flush(z, r);
-						}
-						n--;
-						b |= (z.read_byte(p++) & 0xff) << k;
-						k += 8;
-					}
-
-					tindex = (tree_index + (b & inflate_mask[j])) * 3;
-
-					b >>= tree[tindex + 1];
-					k -= tree[tindex + 1];
-
-					e = (tree[tindex]);
-					if ((e & 16) !== 0) { // distance
-						get = e & 15;
-						dist = tree[tindex + 2];
-						mode = DISTEXT;
-						break;
-					}
-					if ((e & 64) === 0) { // next table
-						need = e;
-						tree_index = tindex / 3 + tree[tindex + 2];
-						break;
-					}
-					mode = BADCODE; // invalid code
-					z.msg = "invalid distance code";
-					r = Z_DATA_ERROR;
-
-					s.bitb = b;
-					s.bitk = k;
-					z.avail_in = n;
-					z.total_in += p - z.next_in_index;
-					z.next_in_index = p;
-					s.write = q;
-					return s.inflate_flush(z, r);
-
-				case DISTEXT: // i: getting distance extra
-					j = get;
-
-					while (k < (j)) {
-						if (n !== 0)
-							r = Z_OK;
-						else {
-
-							s.bitb = b;
-							s.bitk = k;
-							z.avail_in = n;
-							z.total_in += p - z.next_in_index;
-							z.next_in_index = p;
-							s.write = q;
-							return s.inflate_flush(z, r);
-						}
-						n--;
-						b |= (z.read_byte(p++) & 0xff) << k;
-						k += 8;
-					}
-
-					dist += (b & inflate_mask[j]);
-
-					b >>= j;
-					k -= j;
-
-					mode = COPY;
-				case COPY: // o: copying bytes in window, waiting for space
-					f = q - dist;
-					while (f < 0) { // modulo window size-"while" instead
-						f += s.end; // of "if" handles invalid distances
-					}
-					while (len !== 0) {
-
-						if (m === 0) {
-							if (q == s.end && s.read !== 0) {
-								q = 0;
-								m = q < s.read ? s.read - q - 1 : s.end - q;
-							}
-							if (m === 0) {
-								s.write = q;
-								r = s.inflate_flush(z, r);
-								q = s.write;
-								m = q < s.read ? s.read - q - 1 : s.end - q;
-
-								if (q == s.end && s.read !== 0) {
-									q = 0;
-									m = q < s.read ? s.read - q - 1 : s.end - q;
-								}
-
-								if (m === 0) {
-									s.bitb = b;
-									s.bitk = k;
-									z.avail_in = n;
-									z.total_in += p - z.next_in_index;
-									z.next_in_index = p;
-									s.write = q;
-									return s.inflate_flush(z, r);
-								}
-							}
-						}
-
-						s.window[q++] = s.window[f++];
-						m--;
-
-						if (f == s.end)
-							f = 0;
-						len--;
-					}
-					mode = START;
-					break;
-				case LIT: // o: got literal, waiting for output space
-					if (m === 0) {
-						if (q == s.end && s.read !== 0) {
-							q = 0;
-							m = q < s.read ? s.read - q - 1 : s.end - q;
-						}
-						if (m === 0) {
-							s.write = q;
-							r = s.inflate_flush(z, r);
-							q = s.write;
-							m = q < s.read ? s.read - q - 1 : s.end - q;
-
-							if (q == s.end && s.read !== 0) {
-								q = 0;
-								m = q < s.read ? s.read - q - 1 : s.end - q;
-							}
-							if (m === 0) {
-								s.bitb = b;
-								s.bitk = k;
-								z.avail_in = n;
-								z.total_in += p - z.next_in_index;
-								z.next_in_index = p;
-								s.write = q;
-								return s.inflate_flush(z, r);
-							}
-						}
-					}
-					r = Z_OK;
-
-					s.window[q++] = /* (byte) */lit;
-					m--;
-
-					mode = START;
-					break;
-				case WASH: // o: got eob, possibly more output
-					if (k > 7) { // return unused byte, if any
-						k -= 8;
-						n++;
-						p--; // can always return one
-					}
-
-					s.write = q;
-					r = s.inflate_flush(z, r);
-					q = s.write;
-					m = q < s.read ? s.read - q - 1 : s.end - q;
-
-					if (s.read != s.write) {
-						s.bitb = b;
-						s.bitk = k;
-						z.avail_in = n;
-						z.total_in += p - z.next_in_index;
-						z.next_in_index = p;
-						s.write = q;
-						return s.inflate_flush(z, r);
-					}
-					mode = END;
-				case END:
-					r = Z_STREAM_END;
-					s.bitb = b;
-					s.bitk = k;
-					z.avail_in = n;
-					z.total_in += p - z.next_in_index;
-					z.next_in_index = p;
-					s.write = q;
-					return s.inflate_flush(z, r);
-
-				case BADCODE: // x: got error
-
-					r = Z_DATA_ERROR;
-
-					s.bitb = b;
-					s.bitk = k;
-					z.avail_in = n;
-					z.total_in += p - z.next_in_index;
-					z.next_in_index = p;
-					s.write = q;
-					return s.inflate_flush(z, r);
-
-				default:
-					r = Z_STREAM_ERROR;
-
-					s.bitb = b;
-					s.bitk = k;
-					z.avail_in = n;
-					z.total_in += p - z.next_in_index;
-					z.next_in_index = p;
-					s.write = q;
-					return s.inflate_flush(z, r);
-				}
-			}
-		};
-
-		that.free = function(z) {
-			// ZFREE(z, c);
-		};
-
-	}
-
-	// InfBlocks
-
-	// Table for deflate from PKZIP's appnote.txt.
-	var border = [ // Order of the bit length code lengths
-	16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];
-
-	var TYPE = 0; // get type bits (3, including end bit)
-	var LENS = 1; // get lengths for stored
-	var STORED = 2;// processing stored block
-	var TABLE = 3; // get table lengths
-	var BTREE = 4; // get bit lengths tree for a dynamic
-	// block
-	var DTREE = 5; // get length, distance trees for a
-	// dynamic block
-	var CODES = 6; // processing fixed or dynamic block
-	var DRY = 7; // output remaining window bytes
-	var DONELOCKS = 8; // finished last block, done
-	var BADBLOCKS = 9; // ot a data error--stuck here
-
-	function InfBlocks(z, w) {
-		var that = this;
-
-		var mode = TYPE; // current inflate_block mode
-
-		var left = 0; // if STORED, bytes left to copy
-
-		var table = 0; // table lengths (14 bits)
-		var index = 0; // index into blens (or border)
-		var blens; // bit lengths of codes
-		var bb = [ 0 ]; // bit length tree depth
-		var tb = [ 0 ]; // bit length decoding tree
-
-		var codes = new InfCodes(); // if CODES, current state
-
-		var last = 0; // true if this block is the last block
-
-		var hufts = new Int32Array(MANY * 3); // single malloc for tree space
-		var check = 0; // check on output
-		var inftree = new InfTree();
-
-		that.bitk = 0; // bits in bit buffer
-		that.bitb = 0; // bit buffer
-		that.window = new Uint8Array(w); // sliding window
-		that.end = w; // one byte after sliding window
-		that.read = 0; // window read pointer
-		that.write = 0; // window write pointer
-
-		that.reset = function(z, c) {
-			if (c)
-				c[0] = check;
-			// if (mode == BTREE || mode == DTREE) {
-			// }
-			if (mode == CODES) {
-				codes.free(z);
-			}
-			mode = TYPE;
-			that.bitk = 0;
-			that.bitb = 0;
-			that.read = that.write = 0;
-		};
-
-		that.reset(z, null);
-
-		// copy as much as possible from the sliding window to the output area
-		that.inflate_flush = function(z, r) {
-			var n;
-			var p;
-			var q;
-
-			// local copies of source and destination pointers
-			p = z.next_out_index;
-			q = that.read;
-
-			// compute number of bytes to copy as far as end of window
-			n = /* (int) */((q <= that.write ? that.write : that.end) - q);
-			if (n > z.avail_out)
-				n = z.avail_out;
-			if (n !== 0 && r == Z_BUF_ERROR)
-				r = Z_OK;
-
-			// update counters
-			z.avail_out -= n;
-			z.total_out += n;
-
-			// copy as far as end of window
-			z.next_out.set(that.window.subarray(q, q + n), p);
-			p += n;
-			q += n;
-
-			// see if more to copy at beginning of window
-			if (q == that.end) {
-				// wrap pointers
-				q = 0;
-				if (that.write == that.end)
-					that.write = 0;
-
-				// compute bytes to copy
-				n = that.write - q;
-				if (n > z.avail_out)
-					n = z.avail_out;
-				if (n !== 0 && r == Z_BUF_ERROR)
-					r = Z_OK;
-
-				// update counters
-				z.avail_out -= n;
-				z.total_out += n;
-
-				// copy
-				z.next_out.set(that.window.subarray(q, q + n), p);
-				p += n;
-				q += n;
-			}
-
-			// update pointers
-			z.next_out_index = p;
-			that.read = q;
-
-			// done
-			return r;
-		};
-
-		that.proc = function(z, r) {
-			var t; // temporary storage
-			var b; // bit buffer
-			var k; // bits in bit buffer
-			var p; // input data pointer
-			var n; // bytes available there
-			var q; // output window write pointer
-			var m; // bytes to end of window or read pointer
-
-			var i;
-
-			// copy input/output information to locals (UPDATE macro restores)
-			// {
-			p = z.next_in_index;
-			n = z.avail_in;
-			b = that.bitb;
-			k = that.bitk;
-			// }
-			// {
-			q = that.write;
-			m = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);
-			// }
-
-			// process input based on current state
-			// DEBUG dtree
-			while (true) {
-				switch (mode) {
-				case TYPE:
-
-					while (k < (3)) {
-						if (n !== 0) {
-							r = Z_OK;
-						} else {
-							that.bitb = b;
-							that.bitk = k;
-							z.avail_in = n;
-							z.total_in += p - z.next_in_index;
-							z.next_in_index = p;
-							that.write = q;
-							return that.inflate_flush(z, r);
-						}
-						n--;
-						b |= (z.read_byte(p++) & 0xff) << k;
-						k += 8;
-					}
-					t = /* (int) */(b & 7);
-					last = t & 1;
-
-					switch (t >>> 1) {
-					case 0: // stored
-						// {
-						b >>>= (3);
-						k -= (3);
-						// }
-						t = k & 7; // go to byte boundary
-
-						// {
-						b >>>= (t);
-						k -= (t);
-						// }
-						mode = LENS; // get length of stored block
-						break;
-					case 1: // fixed
-						// {
-						var bl = []; // new Array(1);
-						var bd = []; // new Array(1);
-						var tl = [ [] ]; // new Array(1);
-						var td = [ [] ]; // new Array(1);
-
-						InfTree.inflate_trees_fixed(bl, bd, tl, td, z);
-						codes.init(bl[0], bd[0], tl[0], 0, td[0], 0, z);
-						// }
-
-						// {
-						b >>>= (3);
-						k -= (3);
-						// }
-
-						mode = CODES;
-						break;
-					case 2: // dynamic
-
-						// {
-						b >>>= (3);
-						k -= (3);
-						// }
-
-						mode = TABLE;
-						break;
-					case 3: // illegal
-
-						// {
-						b >>>= (3);
-						k -= (3);
-						// }
-						mode = BADBLOCKS;
-						z.msg = "invalid block type";
-						r = Z_DATA_ERROR;
-
-						that.bitb = b;
-						that.bitk = k;
-						z.avail_in = n;
-						z.total_in += p - z.next_in_index;
-						z.next_in_index = p;
-						that.write = q;
-						return that.inflate_flush(z, r);
-					}
-					break;
-				case LENS:
-
-					while (k < (32)) {
-						if (n !== 0) {
-							r = Z_OK;
-						} else {
-							that.bitb = b;
-							that.bitk = k;
-							z.avail_in = n;
-							z.total_in += p - z.next_in_index;
-							z.next_in_index = p;
-							that.write = q;
-							return that.inflate_flush(z, r);
-						}
-						n--;
-						b |= (z.read_byte(p++) & 0xff) << k;
-						k += 8;
-					}
-
-					if ((((~b) >>> 16) & 0xffff) != (b & 0xffff)) {
-						mode = BADBLOCKS;
-						z.msg = "invalid stored block lengths";
-						r = Z_DATA_ERROR;
-
-						that.bitb = b;
-						that.bitk = k;
-						z.avail_in = n;
-						z.total_in += p - z.next_in_index;
-						z.next_in_index = p;
-						that.write = q;
-						return that.inflate_flush(z, r);
-					}
-					left = (b & 0xffff);
-					b = k = 0; // dump bits
-					mode = left !== 0 ? STORED : (last !== 0 ? DRY : TYPE);
-					break;
-				case STORED:
-					if (n === 0) {
-						that.bitb = b;
-						that.bitk = k;
-						z.avail_in = n;
-						z.total_in += p - z.next_in_index;
-						z.next_in_index = p;
-						that.write = q;
-						return that.inflate_flush(z, r);
-					}
-
-					if (m === 0) {
-						if (q == that.end && that.read !== 0) {
-							q = 0;
-							m = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);
-						}
-						if (m === 0) {
-							that.write = q;
-							r = that.inflate_flush(z, r);
-							q = that.write;
-							m = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);
-							if (q == that.end && that.read !== 0) {
-								q = 0;
-								m = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);
-							}
-							if (m === 0) {
-								that.bitb = b;
-								that.bitk = k;
-								z.avail_in = n;
-								z.total_in += p - z.next_in_index;
-								z.next_in_index = p;
-								that.write = q;
-								return that.inflate_flush(z, r);
-							}
-						}
-					}
-					r = Z_OK;
-
-					t = left;
-					if (t > n)
-						t = n;
-					if (t > m)
-						t = m;
-					that.window.set(z.read_buf(p, t), q);
-					p += t;
-					n -= t;
-					q += t;
-					m -= t;
-					if ((left -= t) !== 0)
-						break;
-					mode = last !== 0 ? DRY : TYPE;
-					break;
-				case TABLE:
-
-					while (k < (14)) {
-						if (n !== 0) {
-							r = Z_OK;
-						} else {
-							that.bitb = b;
-							that.bitk = k;
-							z.avail_in = n;
-							z.total_in += p - z.next_in_index;
-							z.next_in_index = p;
-							that.write = q;
-							return that.inflate_flush(z, r);
-						}
-
-						n--;
-						b |= (z.read_byte(p++) & 0xff) << k;
-						k += 8;
-					}
-
-					table = t = (b & 0x3fff);
-					if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) {
-						mode = BADBLOCKS;
-						z.msg = "too many length or distance symbols";
-						r = Z_DATA_ERROR;
-
-						that.bitb = b;
-						that.bitk = k;
-						z.avail_in = n;
-						z.total_in += p - z.next_in_index;
-						z.next_in_index = p;
-						that.write = q;
-						return that.inflate_flush(z, r);
-					}
-					t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
-					if (!blens || blens.length < t) {
-						blens = []; // new Array(t);
-					} else {
-						for (i = 0; i < t; i++) {
-							blens[i] = 0;
-						}
-					}
-
-					// {
-					b >>>= (14);
-					k -= (14);
-					// }
-
-					index = 0;
-					mode = BTREE;
-				case BTREE:
-					while (index < 4 + (table >>> 10)) {
-						while (k < (3)) {
-							if (n !== 0) {
-								r = Z_OK;
-							} else {
-								that.bitb = b;
-								that.bitk = k;
-								z.avail_in = n;
-								z.total_in += p - z.next_in_index;
-								z.next_in_index = p;
-								that.write = q;
-								return that.inflate_flush(z, r);
-							}
-							n--;
-							b |= (z.read_byte(p++) & 0xff) << k;
-							k += 8;
-						}
-
-						blens[border[index++]] = b & 7;
-
-						// {
-						b >>>= (3);
-						k -= (3);
-						// }
-					}
-
-					while (index < 19) {
-						blens[border[index++]] = 0;
-					}
-
-					bb[0] = 7;
-					t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z);
-					if (t != Z_OK) {
-						r = t;
-						if (r == Z_DATA_ERROR) {
-							blens = null;
-							mode = BADBLOCKS;
-						}
-
-						that.bitb = b;
-						that.bitk = k;
-						z.avail_in = n;
-						z.total_in += p - z.next_in_index;
-						z.next_in_index = p;
-						that.write = q;
-						return that.inflate_flush(z, r);
-					}
-
-					index = 0;
-					mode = DTREE;
-				case DTREE:
-					while (true) {
-						t = table;
-						if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))) {
-							break;
-						}
-
-						var h;
-						var j, c;
-
-						t = bb[0];
-
-						while (k < (t)) {
-							if (n !== 0) {
-								r = Z_OK;
-							} else {
-								that.bitb = b;
-								that.bitk = k;
-								z.avail_in = n;
-								z.total_in += p - z.next_in_index;
-								z.next_in_index = p;
-								that.write = q;
-								return that.inflate_flush(z, r);
-							}
-							n--;
-							b |= (z.read_byte(p++) & 0xff) << k;
-							k += 8;
-						}
-
-						// if (tb[0] == -1) {
-						// System.err.println("null...");
-						// }
-
-						t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1];
-						c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2];
-
-						if (c < 16) {
-							b >>>= (t);
-							k -= (t);
-							blens[index++] = c;
-						} else { // c == 16..18
-							i = c == 18 ? 7 : c - 14;
-							j = c == 18 ? 11 : 3;
-
-							while (k < (t + i)) {
-								if (n !== 0) {
-									r = Z_OK;
-								} else {
-									that.bitb = b;
-									that.bitk = k;
-									z.avail_in = n;
-									z.total_in += p - z.next_in_index;
-									z.next_in_index = p;
-									that.write = q;
-									return that.inflate_flush(z, r);
-								}
-								n--;
-								b |= (z.read_byte(p++) & 0xff) << k;
-								k += 8;
-							}
-
-							b >>>= (t);
-							k -= (t);
-
-							j += (b & inflate_mask[i]);
-
-							b >>>= (i);
-							k -= (i);
-
-							i = index;
-							t = table;
-							if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || (c == 16 && i < 1)) {
-								blens = null;
-								mode = BADBLOCKS;
-								z.msg = "invalid bit length repeat";
-								r = Z_DATA_ERROR;
-
-								that.bitb = b;
-								that.bitk = k;
-								z.avail_in = n;
-								z.total_in += p - z.next_in_index;
-								z.next_in_index = p;
-								that.write = q;
-								return that.inflate_flush(z, r);
-							}
-
-							c = c == 16 ? blens[i - 1] : 0;
-							do {
-								blens[i++] = c;
-							} while (--j !== 0);
-							index = i;
-						}
-					}
-
-					tb[0] = -1;
-					// {
-					var bl_ = []; // new Array(1);
-					var bd_ = []; // new Array(1);
-					var tl_ = []; // new Array(1);
-					var td_ = []; // new Array(1);
-					bl_[0] = 9; // must be <= 9 for lookahead assumptions
-					bd_[0] = 6; // must be <= 9 for lookahead assumptions
-
-					t = table;
-					t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), blens, bl_, bd_, tl_, td_, hufts, z);
-
-					if (t != Z_OK) {
-						if (t == Z_DATA_ERROR) {
-							blens = null;
-							mode = BADBLOCKS;
-						}
-						r = t;
-
-						that.bitb = b;
-						that.bitk = k;
-						z.avail_in = n;
-						z.total_in += p - z.next_in_index;
-						z.next_in_index = p;
-						that.write = q;
-						return that.inflate_flush(z, r);
-					}
-					codes.init(bl_[0], bd_[0], hufts, tl_[0], hufts, td_[0], z);
-					// }
-					mode = CODES;
-				case CODES:
-					that.bitb = b;
-					that.bitk = k;
-					z.avail_in = n;
-					z.total_in += p - z.next_in_index;
-					z.next_in_index = p;
-					that.write = q;
-
-					if ((r = codes.proc(that, z, r)) != Z_STREAM_END) {
-						return that.inflate_flush(z, r);
-					}
-					r = Z_OK;
-					codes.free(z);
-
-					p = z.next_in_index;
-					n = z.avail_in;
-					b = that.bitb;
-					k = that.bitk;
-					q = that.write;
-					m = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);
-
-					if (last === 0) {
-						mode = TYPE;
-						break;
-					}
-					mode = DRY;
-				case DRY:
-					that.write = q;
-					r = that.inflate_flush(z, r);
-					q = that.write;
-					m = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);
-					if (that.read != that.write) {
-						that.bitb = b;
-						that.bitk = k;
-						z.avail_in = n;
-						z.total_in += p - z.next_in_index;
-						z.next_in_index = p;
-						that.write = q;
-						return that.inflate_flush(z, r);
-					}
-					mode = DONELOCKS;
-				case DONELOCKS:
-					r = Z_STREAM_END;
-
-					that.bitb = b;
-					that.bitk = k;
-					z.avail_in = n;
-					z.total_in += p - z.next_in_index;
-					z.next_in_index = p;
-					that.write = q;
-					return that.inflate_flush(z, r);
-				case BADBLOCKS:
-					r = Z_DATA_ERROR;
-
-					that.bitb = b;
-					that.bitk = k;
-					z.avail_in = n;
-					z.total_in += p - z.next_in_index;
-					z.next_in_index = p;
-					that.write = q;
-					return that.inflate_flush(z, r);
-
-				default:
-					r = Z_STREAM_ERROR;
-
-					that.bitb = b;
-					that.bitk = k;
-					z.avail_in = n;
-					z.total_in += p - z.next_in_index;
-					z.next_in_index = p;
-					that.write = q;
-					return that.inflate_flush(z, r);
-				}
-			}
-		};
-
-		that.free = function(z) {
-			that.reset(z, null);
-			that.window = null;
-			hufts = null;
-			// ZFREE(z, s);
-		};
-
-		that.set_dictionary = function(d, start, n) {
-			that.window.set(d.subarray(start, start + n), 0);
-			that.read = that.write = n;
-		};
-
-		// Returns true if inflate is currently at the end of a block generated
-		// by Z_SYNC_FLUSH or Z_FULL_FLUSH.
-		that.sync_point = function() {
-			return mode == LENS ? 1 : 0;
-		};
-
-	}
-
-	// Inflate
-
-	// preset dictionary flag in zlib header
-	var PRESET_DICT = 0x20;
-
-	var Z_DEFLATED = 8;
-
-	var METHOD = 0; // waiting for method byte
-	var FLAG = 1; // waiting for flag byte
-	var DICT4 = 2; // four dictionary check bytes to go
-	var DICT3 = 3; // three dictionary check bytes to go
-	var DICT2 = 4; // two dictionary check bytes to go
-	var DICT1 = 5; // one dictionary check byte to go
-	var DICT0 = 6; // waiting for inflateSetDictionary
-	var BLOCKS = 7; // decompressing blocks
-	var DONE = 12; // finished check, done
-	var BAD = 13; // got an error--stay here
-
-	var mark = [ 0, 0, 0xff, 0xff ];
-
-	function Inflate() {
-		var that = this;
-
-		that.mode = 0; // current inflate mode
-
-		// mode dependent information
-		that.method = 0; // if FLAGS, method byte
-
-		// if CHECK, check values to compare
-		that.was = [ 0 ]; // new Array(1); // computed check value
-		that.need = 0; // stream check value
-
-		// if BAD, inflateSync's marker bytes count
-		that.marker = 0;
-
-		// mode independent information
-		that.wbits = 0; // log2(window size) (8..15, defaults to 15)
-
-		// this.blocks; // current inflate_blocks state
-
-		function inflateReset(z) {
-			if (!z || !z.istate)
-				return Z_STREAM_ERROR;
-
-			z.total_in = z.total_out = 0;
-			z.msg = null;
-			z.istate.mode = BLOCKS;
-			z.istate.blocks.reset(z, null);
-			return Z_OK;
-		}
-
-		that.inflateEnd = function(z) {
-			if (that.blocks)
-				that.blocks.free(z);
-			that.blocks = null;
-			// ZFREE(z, z->state);
-			return Z_OK;
-		};
-
-		that.inflateInit = function(z, w) {
-			z.msg = null;
-			that.blocks = null;
-
-			// set window size
-			if (w < 8 || w > 15) {
-				that.inflateEnd(z);
-				return Z_STREAM_ERROR;
-			}
-			that.wbits = w;
-
-			z.istate.blocks = new InfBlocks(z, 1 << w);
-
-			// reset state
-			inflateReset(z);
-			return Z_OK;
-		};
-
-		that.inflate = function(z, f) {
-			var r;
-			var b;
-
-			if (!z || !z.istate || !z.next_in)
-				return Z_STREAM_ERROR;
-			f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
-			r = Z_BUF_ERROR;
-			while (true) {
-				// System.out.println("mode: "+z.istate.mode);
-				switch (z.istate.mode) {
-				case METHOD:
-
-					if (z.avail_in === 0)
-						return r;
-					r = f;
-
-					z.avail_in--;
-					z.total_in++;
-					if (((z.istate.method = z.read_byte(z.next_in_index++)) & 0xf) != Z_DEFLATED) {
-						z.istate.mode = BAD;
-						z.msg = "unknown compression method";
-						z.istate.marker = 5; // can't try inflateSync
-						break;
-					}
-					if ((z.istate.method >> 4) + 8 > z.istate.wbits) {
-						z.istate.mode = BAD;
-						z.msg = "invalid window size";
-						z.istate.marker = 5; // can't try inflateSync
-						break;
-					}
-					z.istate.mode = FLAG;
-				case FLAG:
-
-					if (z.avail_in === 0)
-						return r;
-					r = f;
-
-					z.avail_in--;
-					z.total_in++;
-					b = (z.read_byte(z.next_in_index++)) & 0xff;
-
-					if ((((z.istate.method << 8) + b) % 31) !== 0) {
-						z.istate.mode = BAD;
-						z.msg = "incorrect header check";
-						z.istate.marker = 5; // can't try inflateSync
-						break;
-					}
-
-					if ((b & PRESET_DICT) === 0) {
-						z.istate.mode = BLOCKS;
-						break;
-					}
-					z.istate.mode = DICT4;
-				case DICT4:
-
-					if (z.avail_in === 0)
-						return r;
-					r = f;
-
-					z.avail_in--;
-					z.total_in++;
-					z.istate.need = ((z.read_byte(z.next_in_index++) & 0xff) << 24) & 0xff000000;
-					z.istate.mode = DICT3;
-				case DICT3:
-
-					if (z.avail_in === 0)
-						return r;
-					r = f;
-
-					z.avail_in--;
-					z.total_in++;
-					z.istate.need += ((z.read_byte(z.next_in_index++) & 0xff) << 16) & 0xff0000;
-					z.istate.mode = DICT2;
-				case DICT2:
-
-					if (z.avail_in === 0)
-						return r;
-					r = f;
-
-					z.avail_in--;
-					z.total_in++;
-					z.istate.need += ((z.read_byte(z.next_in_index++) & 0xff) << 8) & 0xff00;
-					z.istate.mode = DICT1;
-				case DICT1:
-
-					if (z.avail_in === 0)
-						return r;
-					r = f;
-
-					z.avail_in--;
-					z.total_in++;
-					z.istate.need += (z.read_byte(z.next_in_index++) & 0xff);
-					z.istate.mode = DICT0;
-					return Z_NEED_DICT;
-				case DICT0:
-					z.istate.mode = BAD;
-					z.msg = "need dictionary";
-					z.istate.marker = 0; // can try inflateSync
-					return Z_STREAM_ERROR;
-				case BLOCKS:
-
-					r = z.istate.blocks.proc(z, r);
-					if (r == Z_DATA_ERROR) {
-						z.istate.mode = BAD;
-						z.istate.marker = 0; // can try inflateSync
-						break;
-					}
-					if (r == Z_OK) {
-						r = f;
-					}
-					if (r != Z_STREAM_END) {
-						return r;
-					}
-					r = f;
-					z.istate.blocks.reset(z, z.istate.was);
-					z.istate.mode = DONE;
-				case DONE:
-					return Z_STREAM_END;
-				case BAD:
-					return Z_DATA_ERROR;
-				default:
-					return Z_STREAM_ERROR;
-				}
-			}
-		};
-
-		that.inflateSetDictionary = function(z, dictionary, dictLength) {
-			var index = 0;
-			var length = dictLength;
-			if (!z || !z.istate || z.istate.mode != DICT0)
-				return Z_STREAM_ERROR;
-
-			if (length >= (1 << z.istate.wbits)) {
-				length = (1 << z.istate.wbits) - 1;
-				index = dictLength - length;
-			}
-			z.istate.blocks.set_dictionary(dictionary, index, length);
-			z.istate.mode = BLOCKS;
-			return Z_OK;
-		};
-
-		that.inflateSync = function(z) {
-			var n; // number of bytes to look at
-			var p; // pointer to bytes
-			var m; // number of marker bytes found in a row
-			var r, w; // temporaries to save total_in and total_out
-
-			// set up
-			if (!z || !z.istate)
-				return Z_STREAM_ERROR;
-			if (z.istate.mode != BAD) {
-				z.istate.mode = BAD;
-				z.istate.marker = 0;
-			}
-			if ((n = z.avail_in) === 0)
-				return Z_BUF_ERROR;
-			p = z.next_in_index;
-			m = z.istate.marker;
-
-			// search
-			while (n !== 0 && m < 4) {
-				if (z.read_byte(p) == mark[m]) {
-					m++;
-				} else if (z.read_byte(p) !== 0) {
-					m = 0;
-				} else {
-					m = 4 - m;
-				}
-				p++;
-				n--;
-			}
-
-			// restore
-			z.total_in += p - z.next_in_index;
-			z.next_in_index = p;
-			z.avail_in = n;
-			z.istate.marker = m;
-
-			// return no joy or set up to restart on a new block
-			if (m != 4) {
-				return Z_DATA_ERROR;
-			}
-			r = z.total_in;
-			w = z.total_out;
-			inflateReset(z);
-			z.total_in = r;
-			z.total_out = w;
-			z.istate.mode = BLOCKS;
-			return Z_OK;
-		};
-
-		// Returns true if inflate is currently at the end of a block generated
-		// by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
-		// implementation to provide an additional safety check. PPP uses
-		// Z_SYNC_FLUSH
-		// but removes the length bytes of the resulting empty stored block. When
-		// decompressing, PPP checks that at the end of input packet, inflate is
-		// waiting for these length bytes.
-		that.inflateSyncPoint = function(z) {
-			if (!z || !z.istate || !z.istate.blocks)
-				return Z_STREAM_ERROR;
-			return z.istate.blocks.sync_point();
-		};
-	}
-
-	// ZStream
-
-	function ZStream() {
-	}
-
-	ZStream.prototype = {
-		inflateInit : function(bits) {
-			var that = this;
-			that.istate = new Inflate();
-			if (!bits)
-				bits = MAX_BITS;
-			return that.istate.inflateInit(that, bits);
-		},
-
-		inflate : function(f) {
-			var that = this;
-			if (!that.istate)
-				return Z_STREAM_ERROR;
-			return that.istate.inflate(that, f);
-		},
-
-		inflateEnd : function() {
-			var that = this;
-			if (!that.istate)
-				return Z_STREAM_ERROR;
-			var ret = that.istate.inflateEnd(that);
-			that.istate = null;
-			return ret;
-		},
-
-		inflateSync : function() {
-			var that = this;
-			if (!that.istate)
-				return Z_STREAM_ERROR;
-			return that.istate.inflateSync(that);
-		},
-		inflateSetDictionary : function(dictionary, dictLength) {
-			var that = this;
-			if (!that.istate)
-				return Z_STREAM_ERROR;
-			return that.istate.inflateSetDictionary(that, dictionary, dictLength);
-		},
-		read_byte : function(start) {
-			var that = this;
-			return that.next_in.subarray(start, start + 1)[0];
-		},
-		read_buf : function(start, size) {
-			var that = this;
-			return that.next_in.subarray(start, start + size);
-		}
-	};
-
-	// Inflater
-
-	function Inflater() {
-		var that = this;
-		var z = new ZStream();
-		var bufsize = 512;
-		var flush = Z_NO_FLUSH;
-		var buf = new Uint8Array(bufsize);
-		var nomoreinput = false;
-
-		z.inflateInit();
-		z.next_out = buf;
-
-		that.append = function(data, onprogress) {
-			var err, buffers = [], lastIndex = 0, bufferIndex = 0, bufferSize = 0, array;
-			if (data.length === 0)
-				return;
-			z.next_in_index = 0;
-			z.next_in = data;
-			z.avail_in = data.length;
-			do {
-				z.next_out_index = 0;
-				z.avail_out = bufsize;
-				if ((z.avail_in === 0) && (!nomoreinput)) { // if buffer is empty and more input is available, refill it
-					z.next_in_index = 0;
-					nomoreinput = true;
-				}
-				err = z.inflate(flush);
-				if (nomoreinput && (err == Z_BUF_ERROR))
-					return -1;
-				if (err != Z_OK && err != Z_STREAM_END)
-					throw "inflating: " + z.msg;
-				if ((nomoreinput || err == Z_STREAM_END) && (z.avail_out == data.length))
-					return -1;
-				if (z.next_out_index)
-					if (z.next_out_index == bufsize)
-						buffers.push(new Uint8Array(buf));
-					else
-						buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
-				bufferSize += z.next_out_index;
-				if (onprogress && z.next_in_index > 0 && z.next_in_index != lastIndex) {
-					onprogress(z.next_in_index);
-					lastIndex = z.next_in_index;
-				}
-			} while (z.avail_in > 0 || z.avail_out === 0);
-			array = new Uint8Array(bufferSize);
-			buffers.forEach(function(chunk) {
-				array.set(chunk, bufferIndex);
-				bufferIndex += chunk.length;
-			});
-			return array;
-		};
-		that.flush = function() {
-			z.inflateEnd();
-		};
-	}
-
-	var inflater;
-
-	if (obj.zip)
-		obj.zip.Inflater = Inflater;
-	else {
-		inflater = new Inflater();
-		obj.addEventListener("message", function(event) {
-			var message = event.data;
-
-			if (message.append)
-				obj.postMessage({
-					onappend : true,
-					data : inflater.append(message.data, function(current) {
-						obj.postMessage({
-							progress : true,
-							current : current
-						});
-					})
-				});
-			if (message.flush) {
-				inflater.flush();
-				obj.postMessage({
-					onflush : true
-				});
-			}
-		}, false);
-	}
-
-})(this);
-
diff --git a/src/compression/zlib/jsxcompressor.js b/src/compression/zlib/jsxcompressor.js
index e213e88e..65a78417 100644
--- a/src/compression/zlib/jsxcompressor.js
+++ b/src/compression/zlib/jsxcompressor.js
@@ -625,7 +625,20 @@ JXG.Util.Unzip.prototype.unzipFile = function(name) {
 	}
 	
   };
-    
+
+JXG.Util.Unzip.prototype.deflate = function() {
+    outputArr = [];
+    var tmp = [];
+    modeZIP = false;
+    DeflateLoop();
+    if (debug)
+        alert(outputArr.join(''));
+    unzipped[files] = new Array(2);
+    unzipped[files][0] = outputArr.join('');
+    unzipped[files][1] = "DEFLATE";
+    files++;
+    return unzipped;
+}    
     
 JXG.Util.Unzip.prototype.unzip = function() {
 	//convertToByteArray(input);
diff --git a/src/packet/openpgp.packet.compressed.js b/src/packet/openpgp.packet.compressed.js
index d58f22b1..2af1ed50 100644
--- a/src/packet/openpgp.packet.compressed.js
+++ b/src/packet/openpgp.packet.compressed.js
@@ -60,12 +60,14 @@ function openpgp_packet_compressed() {
 			this.decompressedData = this.compressedData;
 			break;
 		case 1: // - ZIP [RFC1951]
-            var inflater = new zip.Inflater();
-            var output = inflater.append(util.str2Uint8Array(this.compressedData));
-            var outputString = util.Uint8Array2str(output);
-            var packet = openpgp_packet.read_packet(outputString,0,outputString.length);
-            util.print_info('Decompressed packet [Type 1-ZIP]: ' + packet);
-            this.decompressedData = packet.data;
+			var compData = this.compressedData;
+			var radix = s2r(compData).replace(/\n/g,"");
+			// no header in this case, directly call deflate
+			var jxg_obj = new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(radix));
+			var outputString = unescape(jxg_obj.deflate()[0][0]);
+			var packet = openpgp_packet.read_packet(outputString, 0, outputString.length);
+			util.print_info('Decompressed packet [Type 1-ZIP]: ' + packet);
+			this.decompressedData = packet.data;
 			break;
 		case 2: // - ZLIB [RFC1950]
 			var compressionMethod = this.compressedData.charCodeAt(0) % 0x10; //RFC 1950. Bits 0-3 Compression Method
diff --git a/test/encryption.html b/test/encryption.html
index 1bb29751..6f22d0cf 100644
--- a/test/encryption.html
+++ b/test/encryption.html
@@ -25,7 +25,6 @@
 <script type="text/javascript" src="../src/ciphers/openpgp.cfb.js"></script>
 
 <!-- compression -->
-<script type="text/javascript" src="../src/compression/zip/zip.js"></script>
 <script type="text/javascript" src="../src/compression/zlib/jsxcompressor.js"></script>
 
 <!-- encoding -->