diff --git a/resources/openpgp.js b/resources/openpgp.js
index 722202ad..c3ed8712 100644
--- a/resources/openpgp.js
+++ b/resources/openpgp.js
@@ -9257,6 +9257,159 @@ function openpgp_msg_publickey() {
 // License along with this library; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
+/**
+ * @class
+ * @classdesc 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_literal() {
+	this.tag = 11;
+	this.format = openpgp_packet_literal.format.utf8;
+	this.data = '';
+	this.date = new Date();
+
+	
+	/**
+	 * Set the packet data to a javascript native string or a squence of 
+	 * bytes. Conversion to a proper utf8 encoding takes place when the 
+	 * packet is written.
+	 * @param {String} str Any native javascript string
+	 * @param {openpgp_packet_literaldata.format} format 
+	 */
+	this.set_data = function(str, format) {
+		this.format = format;
+		this.data = str;
+	}
+
+	/**
+	 * Set the packet data to value represented by the provided string
+	 * of bytes together with the appropriate conversion format.
+	 * @param {String} bytes The string of bytes
+	 * @param {openpgp_packet_literaldata.format} format
+	 */
+	this.set_data_bytes = function(bytes, format) {
+		this.format = format;
+
+		if(format == openpgp_packet_literal.format.utf8)
+			bytes = util.decode_utf8(bytes);
+
+		this.data = bytes;
+	}
+
+	/**
+	 * Get the byte sequence representing the literal packet data
+	 * @returns {String} A sequence of bytes
+	 */
+	this.get_data_bytes = function() {
+		if(this.format == openpgp_packet_literal.format.utf8)
+			return util.encode_utf8(this.data);
+		else
+			return this.data;
+	}
+	
+	
+
+	/**
+	 * Parsing function for a literal data packet (tag 11).
+	 * 
+	 * @param {String} input Payload of a tag 11 packet
+	 * @param {Integer} position
+	 *            Position to start reading from the input string
+	 * @param {Integer} len
+	 *            Length of the packet or the remaining length of
+	 *            input at position
+	 * @return {openpgp_packet_encrypteddata} object representation
+	 */
+	this.read = function(bytes) {
+		// - A one-octet field that describes how the data is formatted.
+
+		var format = bytes[0];
+
+		this.filename = util.decode_utf8(bytes.substr(2, bytes
+				.charCodeAt(1)));
+
+		this.date = new Date(parseInt(bytes.substr(2
+				+ bytes.charCodeAt(1), 4)) * 1000);
+
+		var data = bytes.substring(6
+				+ bytes.charCodeAt(1));
+	
+		this.set_data_bytes(data, format);
+	}
+
+	/**
+	 * Creates a string representation of the packet
+	 * 
+	 * @param {String} data The data to be inserted as body
+	 * @return {String} string-representation of the packet
+	 */
+	this.write = function() {
+		var filename = util.encode_utf8("msg.txt");
+
+		var data = this.get_data_bytes();
+
+		var result = '';
+		result += this.format;
+		result += String.fromCharCode(filename.length);
+		result += 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;
+		return result;
+	}
+
+	/**
+	 * Generates debug output (pretty print)
+	 * 
+	 * @return {String} String which gives some information about the keymaterial
+	 */
+	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';
+	}
+}
+
+/**
+ * Data types in the literal packet
+ * @readonly
+ * @enum {String}
+ */
+openpgp_packet_literal.format = {
+	/** Binary data */
+	binary: 'b',
+	/** Text data */
+	text: 't',
+	/** Utf8 data */
+	utf8: 'u'
+};
+// 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
+
 /**
  * @class
  * @classdesc Implementation of the Compressed Data Packet (Tag 8)
@@ -9439,86 +9592,6 @@ function openpgp_packet_compressed(bytes) {
 // License along with this library; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
-/**
- * @class
- * @classdesc 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.tag = 9;
-	this.encrypted = null;
-	this.data = new openpgp_packetlist();
-	this.algorithm = openpgp.symmetric.plaintext;
-
-	
-
-	this.read = function(bytes) {
-		this.encrypted = bytes;
-	}
-
-	this.write = function() {
-		return this.encrypted;
-	}
-
-	/**
-	 * Symmetrically decrypt the packet data
-	 * 
-	 * @param {Integer} symmetric_algorithm_type
-	 *             Symmetric key algorithm to use // See RFC4880 9.2
-	 * @param {String} key
-	 *             Key as string with the corresponding length to the
-	 *            algorithm
-	 * @return The decrypted data;
-	 */
-	this.decrypt = function(symmetric_algorithm_type, key) {
-		var decrypted = openpgp_crypto_symmetricDecrypt(
-				symmetric_algorithm_type, key, this.encryptedData, true);
-
-		util.print_debug("openpgp.packet.encryptedintegrityprotecteddata.js\n"+
-				"data: "+util.hexstrdump(this.decryptedData));
-
-
-		this.data = new openpgp_packetlist(decrypted);
-	}
-
-	this.encrypt = function(algo, key) {
-		var data = this.data.write();
-
-		this.encrypted = openpgp_crypto_symmetricEncrypt(
-				openpgp_crypto_getPrefixRandom(algo), algo, key, data, true);
-	}
-
-
-	this.toString = function () {
-		return '5.7.  Symmetrically Encrypted Data Packet (Tag 9)\n'
-				+ '    Used symmetric algorithm: ' + this.algorithmType + '\n'
-				+ '    encrypted data: Bytes ['
-				+ util.hexstrdump(this.encryptedData) + ']\n';
-	}
-};
-// 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
-
 /**
  * @class
  * @classdesc Implementation of the Sym. Encrypted Integrity Protected Data 
@@ -9900,439 +9973,6 @@ function openpgp_packet_encryptedsessionkey() {
 // License along with this library; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
-/**
- * @class
- * @classdesc Parent openpgp packet class. Operations focus on determining 
- * packet types and packet header.
- */
-function _openpgp_packet() {
-	/**
-	 * Encodes a given integer of length to the openpgp length specifier to a
-	 * string
-	 * 
-	 * @param {Integer} length The length to encode
-	 * @return {String} 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 {Integer} tag_type Tag type
-	 * @param {Integer} length Length of the payload
-	 * @return {String} 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 {Integer} tag_type Tag type
-	 * @param {Integer} length Length of the payload
-	 * @return {String} 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 {String} input Input stream as string
-	 * @param {integer} position Position to start parsing
-	 * @param {integer} len Length of the input from position on
-	 * @return {Object} 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 probably 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 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.
-				packet_length = len;
-				break;
-			}
-
-		} 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;
-
-
-	/**
-	 * @enum {Integer}
-	 * A list of packet type and numeric tags associated with them.
-	 */
-	this.type = {
-		reserved: 0,
-		public_key_encrypted_session_key: 1,
-		signature: 2,
-		symmetric_key_encrypted_session_key: 3,
-		one_pass_signature: 4,
-		secret_key: 5,
-		public_key: 6,
-		secret_subkey: 7,
-		compressed: 8,
-		symmetrically_encrypted_data: 9,
-		marker: 10,
-		literal: 11,
-		trust: 12,
-		userid: 13,
-		public_subkey: 14,
-		user_attribute: 17,
-		sym_encrypted_and_integrity_protected_data: 18,
-		modification_detection_code: 19
-	};
-}
-
-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
-
 /**
  * @class
  * @classdesc Implementation of the Key Material Packet (Tag 5,6,7,14)
@@ -11135,209 +10775,6 @@ function openpgp_packet_keymaterial() {
 	this.write_private_key = write_private_key;
 	this.write_public_key = write_public_key;
 }
-
-
-/**
- * @class
- * @classdesc This class represents a list of openpgp packets.
- */
-function openpgp_packetlist() {
-
-	/** @type {openpgp_packet_[]} A list of packets */
-	this.list = []
-
-
-
-	/**
-	 * Reads a stream of binary data and interprents it as a list of packets.
-	 * @param {openpgp_bytearray} An array of bytes.
-	 */
-	this.read = function(bytes) {
-		var i = 0;
-
-		while(i < bytes.length) {
-			var packet = openpgp_packet.read_packet(bytes, i, bytes.length - i);
-			i += packet.headerLength + packet.packetLength;
-
-			list.push(packet);
-		}
-	}
-
-	/**
-	 * Creates a binary representation of openpgp objects contained within the
-	 * class instance.
-	 * @returns {openpgp_bytearray} An array of bytes containing valid openpgp packets.
-	 */
-	this.write = function() {
-		var bytes = '';
-
-		for(var i in this.list) {
-			var packetbytes = this.list[i].write();
-			bytes += openpgp_packet.write_packet_header(this.list[i].tag, packetbytes.length);
-			bytes += packetbytes;
-		}
-		
-		return bytes;
-	}
-
-	this.push = function(packet) {
-		this.list.push(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
-
-/**
- * @class
- * @classdesc 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.tag = 11;
-	this.format = openpgp_packet_literaldata.formats.utf8;
-	this.data = '';
-	this.date = new Date();
-
-	
-	/**
-	 * Set the packet data to a javascript native string or a squence of 
-	 * bytes. Conversion to a proper utf8 encoding takes place when the 
-	 * packet is written.
-	 * @param {String} str Any native javascript string
-	 * @param {openpgp_packet_literaldata.formats} format 
-	 */
-	this.set_data = function(str, format) {
-		this.format = format;
-		this.data = str;
-	}
-
-	/**
-	 * Set the packet data to value represented by the provided string
-	 * of bytes together with the appropriate conversion format.
-	 * @param {String} bytes The string of bytes
-	 * @param {openpgp_packet_literaldata.formats} format
-	 */
-	this.set_data_bytes = function(bytes, format) {
-		this.format = format;
-
-		if(format == openpgp_packet_literaldata.formats.utf8)
-			bytes = util.decode_utf8(bytes);
-
-		this.data = bytes;
-	}
-
-	/**
-	 * Get the byte sequence representing the literal packet data
-	 * @returns {String} A sequence of bytes
-	 */
-	this.get_data_bytes = function() {
-		if(this.format == openpgp_packet_literaldata.formats.utf8)
-			return util.encode_utf8(this.data);
-		else
-			return this.data;
-	}
-	
-	
-
-	/**
-	 * Parsing function for a literal data packet (tag 11).
-	 * 
-	 * @param {String} input Payload of a tag 11 packet
-	 * @param {Integer} position
-	 *            Position to start reading from the input string
-	 * @param {Integer} len
-	 *            Length of the packet or the remaining length of
-	 *            input at position
-	 * @return {openpgp_packet_encrypteddata} object representation
-	 */
-	this.read = function(bytes) {
-		// - A one-octet field that describes how the data is formatted.
-
-		var format = input[position];
-
-		this.filename = util.decode_utf8(bytes.substr(2, bytes
-				.charCodeAt(1)));
-
-		this.date = new Date(parseInt(bytes.substr(2
-				+ bytes.charCodeAt(1), 4)) * 1000);
-
-		var data = bytes.substring(6
-				+ bytes.charCodeAt(1));
-	
-		this.set_data_bytes(data, format);
-		return this;
-	}
-
-	/**
-	 * Creates a string representation of the packet
-	 * 
-	 * @param {String} data The data to be inserted as body
-	 * @return {String} string-representation of the packet
-	 */
-	this.write = function() {
-		var filename = util.encode_utf8("msg.txt");
-
-		var data = this.get_data_bytes();
-
-		result += this.format;
-		result += String.fromCharCode(filename.length);
-		result += 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;
-		return result;
-	}
-
-	/**
-	 * Generates debug output (pretty print)
-	 * 
-	 * @return {String} String which gives some information about the keymaterial
-	 */
-	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';
-	}
-}
-
-/**
- * Data types in the literal packet
- * @readonly
- * @enum {String}
- */
-openpgp_packet_literaldata.formats = {
-	/** Binary data */
-	binary: 'b',
-	/** Text data */
-	text: 't',
-	/** Utf8 data */
-	utf8: 'u'
-};
 // GPG4Browsers - An OpenPGP implementation in javascript
 // Copyright (C) 2011 Recurity Labs GmbH
 // 
@@ -12856,6 +12293,445 @@ function openpgp_packet_userid() {
 // License along with this library; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
+/**
+ * @class
+ * @classdesc Parent openpgp packet class. Operations focus on determining 
+ * packet types and packet header.
+ */
+function _openpgp_packet() {
+	/**
+	 * Encodes a given integer of length to the openpgp length specifier to a
+	 * string
+	 * 
+	 * @param {Integer} length The length to encode
+	 * @return {String} 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 {Integer} tag_type Tag type
+	 * @param {Integer} length Length of the payload
+	 * @return {String} 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 {Integer} tag_type Tag type
+	 * @param {Integer} length Length of the payload
+	 * @return {String} 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 {String} input Input stream as string
+	 * @param {integer} position Position to start parsing
+	 * @param {integer} len Length of the input from position on
+	 * @return {Object} 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 probably 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 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.
+				packet_length = len;
+				break;
+			}
+
+		} 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;
+
+		var names_by_tag = {};
+
+		for(var i in this.type)
+			names_by_tag[this.type[i]] = i;
+
+		var classname = 'openpgp_packet_' + names_by_tag[tag];
+
+		var packetclass = window[classname];
+
+		if(packetclass == undefined) {
+			throw classname;
+			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;
+		}
+
+		var result = new packetclass();
+		result.read(bodydata);
+
+		return { 
+			packet: result, 
+			offset: mypos + packet_length
+		};
+	}
+
+	this.read_packet = read_packet;
+
+
+	/**
+	 * @enum {Integer}
+	 * A list of packet type and numeric tags associated with them.
+	 */
+	this.type = {
+		reserved: 0,
+		public_key_encrypted_session_key: 1,
+		signature: 2,
+		symmetric_key_encrypted_session_key: 3,
+		one_pass_signature: 4,
+		secret_key: 5,
+		public_key: 6,
+		secret_subkey: 7,
+		compressed: 8,
+		symmetrically_encrypted: 9,
+		marker: 10,
+		literal: 11,
+		trust: 12,
+		userid: 13,
+		public_subkey: 14,
+		user_attribute: 17,
+		sym_encrypted_and_integrity_protected: 18,
+		modification_detection_code: 19
+	};
+}
+
+var openpgp_packet = new _openpgp_packet();
+
+
+/**
+ * @class
+ * @classdesc This class represents a list of openpgp packets.
+ */
+function openpgp_packetlist() {
+
+	/** @type {openpgp_packet_[]} A list of packets */
+	this.packets = []
+
+
+
+	/**
+	 * Reads a stream of binary data and interprents it as a list of packets.
+	 * @param {openpgp_bytearray} An array of bytes.
+	 */
+	this.read = function(bytes) {
+		this.packets = [];
+		var i = 0;
+
+		while(i < bytes.length) {
+			var parsed = openpgp_packet.read_packet(bytes, i, bytes.length - i);
+			i += parsed.offset;
+
+			this.push(parsed.packet);
+		}
+	}
+
+	/**
+	 * Creates a binary representation of openpgp objects contained within the
+	 * class instance.
+	 * @returns {openpgp_bytearray} An array of bytes containing valid openpgp packets.
+	 */
+	this.write = function() {
+		var bytes = '';
+
+		for(var i in this.packets) {
+			var packetbytes = this.packets[i].write();
+			bytes += openpgp_packet.write_packet_header(this.packets[i].tag, packetbytes.length);
+			bytes += packetbytes;
+		}
+		
+		return bytes;
+	}
+
+	this.push = function(packet) {
+		this.packets.push(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
+
+/**
+ * @class
+ * @classdesc 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_symmetrically_encrypted() {
+	this.tag = 9;
+	this.encrypted = null;
+	this.data = new openpgp_packetlist();
+	this.algorithm = openpgp.symmetric.plaintext;
+
+	
+
+	this.read = function(bytes) {
+		this.encrypted = bytes;
+	}
+
+	this.write = function() {
+		return this.encrypted;
+	}
+
+	/**
+	 * Symmetrically decrypt the packet data
+	 * 
+	 * @param {Integer} symmetric_algorithm_type
+	 *             Symmetric key algorithm to use // See RFC4880 9.2
+	 * @param {String} key
+	 *             Key as string with the corresponding length to the
+	 *            algorithm
+	 * @return The decrypted data;
+	 */
+	this.decrypt = function(symmetric_algorithm_type, key) {
+		var decrypted = openpgp_crypto_symmetricDecrypt(
+				symmetric_algorithm_type, key, this.encrypted, true);
+
+		this.data.read(decrypted);
+	}
+
+	this.encrypt = function(algo, key) {
+		var data = this.data.write();
+
+		this.encrypted = openpgp_crypto_symmetricEncrypt(
+				openpgp_crypto_getPrefixRandom(algo), algo, key, data, true);
+	}
+
+
+	this.toString = function () {
+		return '5.7.  Symmetrically Encrypted Data Packet (Tag 9)\n'
+				+ '    Used symmetric algorithm: ' + this.algorithmType + '\n'
+				+ '    encrypted data: Bytes ['
+				+ util.hexstrdump(this.encryptedData) + ']\n';
+	}
+};
+// 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
+
 /**
  * @class
  * @classdesc Implementation of type key id (RFC4880 3.3)
diff --git a/resources/openpgp.min.js b/resources/openpgp.min.js
index 67ff5cae..457ea4df 100644
--- a/resources/openpgp.min.js
+++ b/resources/openpgp.min.js
@@ -351,13 +351,14 @@ function(){for(var b=" OPENPGP Public Key\n    length: "+this.len+"\n",b=b+"
 return b};this.validate=function(){for(var b=0;b<this.revocationSignatures.length;b++)if(this.revocationSignatures[b].verify(this.publicKeyPacket.header+this.publicKeyPacket.data,this.publicKeyPacket))return!1;if(0!=this.subKeys.length){for(var a=!1,b=0;b<this.subKeys.length;b++)if(3==this.subKeys[b].verifyKey()){a=!0;break}if(!a)return!1}a=!1;for(b=0;b<this.userIds.length;b++)if(0==this.userIds[b].verify(this.publicKeyPacket)){a=!0;break}return!a?!1:!0};this.getFingerprint=function(){return this.publicKeyPacket.getFingerprint()};
 this.getKeyId=function(){return this.publicKeyPacket.getKeyId()};this.verifyBasicSignatures=function(){for(var b=0;b<this.revocationSignatures.length;b++)if(this.revocationSignatures[b].verify(this.publicKeyPacket.header+this.publicKeyPacket.data,this.publicKeyPacket))return!1;if(0!=this.subKeys.length){for(var a=!1,b=0;b<this.subKeys.length;b++)if(null!=this.subKeys[b]&&3==this.subKeys[b].verifyKey()){a=!0;break}if(!a)return!1}a=this.getKeyId();for(b=0;b<this.userIds.length;b++)for(var c=0;c<this.userIds[b].certificationRevocationSignatures.length;c++)if(this.userIds[b].certificationSignatures[c].getIssuer==
 a&&4!=this.userIds[b].certificationSignatures[c].verifyBasic(this.publicKeyPacket))return!1;return!0};this.getSubKeyAsKey=function(b){var a=new openpgp_msg_publickey;a.userIds=this.userIds;a.userAttributes=this.userAttributes;a.publicKeyPacket=this.subKeys[b];return a}}
+function openpgp_packet_literal(){this.tag=11;this.format=openpgp_packet_literal.format.utf8;this.data="";this.date=new Date;this.set_data=function(b,a){this.format=a;this.data=b};this.set_data_bytes=function(b,a){this.format=a;a==openpgp_packet_literal.format.utf8&&(b=util.decode_utf8(b));this.data=b};this.get_data_bytes=function(){return this.format==openpgp_packet_literal.format.utf8?util.encode_utf8(this.data):this.data};this.read=function(b){var a=b[0];this.filename=util.decode_utf8(b.substr(2,
+b.charCodeAt(1)));this.date=new Date(1E3*parseInt(b.substr(2+b.charCodeAt(1),4)));this.set_data_bytes(b.substring(6+b.charCodeAt(1)),a)};this.write=function(){var b=util.encode_utf8("msg.txt"),a=this.get_data_bytes(),c;c=""+this.format;c+=String.fromCharCode(b.length);c=c+b+String.fromCharCode(Math.round(this.date.getTime()/1E3)>>24&255);c+=String.fromCharCode(Math.round(this.date.getTime()/1E3)>>16&255);c+=String.fromCharCode(Math.round(this.date.getTime()/1E3)>>8&255);c+=String.fromCharCode(Math.round(this.date.getTime()/
+1E3)&255);return c+a};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"}}openpgp_packet_literal.format={binary:"b",text:"t",utf8:"u"};
 function openpgp_packet_compressed(b){this.tagType=8;this.compressedData=this.decompressedData=null;this.type=0;void 0!=b&&this.read(b);this.read=function(){this.type=input.charCodeAt(mypos++);this.compressedData=input.substring(position+1,position+len);this.decompressedData=null};this.write=function(){null==this.compressedData&&this.compress();return String.fromCharCode(this.type)+this.compress()};this.read_packet=function(a,b,d){this.packetLength=d;var e=b;this.type=a.charCodeAt(e++);this.compressedData=
 a.substring(b+1,b+d);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(){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:util.print_info("Decompressed packet [Type 1-ZIP]: "+this.toString());
 var a=this.compressedData,a=s2r(a).replace(/\n/g,""),a=new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(a));this.decompressedData=unescape(a.deflate()[0][0]);break;case 2:util.print_info("Decompressed packet [Type 2-ZLIB]: "+this.toString());if(8==this.compressedData.charCodeAt(0)%16){a=this.compressedData.substring(0,this.compressedData.length-4);a=s2r(a).replace(/\n/g,"");this.decompressedData=JXG.decompress(a);break}else 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 d=String.fromCharCode(this.type)+this.compress(this.type);return openpgp_packet.write_packet_header(8,d.length)+d}}
-function openpgp_packet_encrypteddata(){this.tag=9;this.encrypted=null;this.data=new openpgp_packetlist;this.algorithm=openpgp.symmetric.plaintext;this.read=function(b){this.encrypted=b};this.write=function(){return this.encrypted};this.decrypt=function(b,a){var c=openpgp_crypto_symmetricDecrypt(b,a,this.encryptedData,!0);util.print_debug("openpgp.packet.encryptedintegrityprotecteddata.js\ndata: "+util.hexstrdump(this.decryptedData));this.data=new openpgp_packetlist(c)};this.encrypt=function(b,a){var c=
-this.data.write();this.encrypted=openpgp_crypto_symmetricEncrypt(openpgp_crypto_getPrefixRandom(b),b,a,c,!0)};this.toString=function(){return"5.7.  Symmetrically Encrypted Data Packet (Tag 9)\n    Used symmetric algorithm: "+this.algorithmType+"\n    encrypted data: Bytes ["+util.hexstrdump(this.encryptedData)+"]\n"}}
 function openpgp_packet_encryptedintegrityprotecteddata(){this.tagType=18;this.hash=this.decrytpedData=this.encryptedData=this.packetLength=this.version=null;this.write_packet=function(b,a,c){var d=openpgp_crypto_getPrefixRandom(b),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));b=openpgp_crypto_symmetricEncrypt(d,
 b,a,c,!1).substring(0,e.length+c.length);a=openpgp_packet.write_packet_header(18,b.length+1)+String.fromCharCode(1);this.encryptedData=b;return a+b};this.read_packet=function(b,a,c){this.packetLength=c;this.version=b[a].charCodeAt();if(1!=this.version)return util.print_error("openpgp.packet.encryptedintegrityprotecteddata.js\nunknown encrypted integrity protected data packet version: "+this.version+" , @ "+a+"hex:"+util.hexstrdump(b)),null;this.encryptedData=b.substring(a+1,a+1+c);util.print_debug("openpgp.packet.encryptedintegrityprotecteddata.js\n"+
 this.toString());return this};this.toString=function(){var b="";openpgp.config.debug&&(b="    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"+b};this.decrypt=function(b,a){this.decryptedData=openpgp_crypto_symmetricDecrypt(b,a,this.encryptedData,!1);this.hash=str_sha1(openpgp_crypto_MDCSystemBytes(b,a,this.encryptedData)+this.decryptedData.substring(0,
@@ -368,17 +369,6 @@ d);if(s2k.s2kLength+d<c){this.encryptedSessionKey=[];for(a=d-a;a<c;a++)this.encr
 return f=openpgp_packet.write_packet_header(1,f.length)+f};this.toString=function(){if(1==this.tagType){for(var b="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",a=0;a<this.MPIs.length;a++)b+=this.MPIs[a].toString();return b}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(b,a){if(1==this.tagType){var c=openpgp_crypto_asymetricDecrypt(this.publicKeyAlgorithmUsed,a.publicKey.MPIs,a.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),a.publicKey.MPIs[0].getByteLength()),c=d.substring(1),d=d.charCodeAt(0);return 18==b.encryptedData.tagType?
 b.encryptedData.decrypt(d,c):b.encryptedData.decrypt_sym(d,c)}if(3==this.tagType)return util.print_error("Symmetric encrypted sessionkey is not supported!"),null}}
-function _openpgp_packet(){function b(a){result="";192>a?result+=String.fromCharCode(a):191<a&&8384>a?(result+=String.fromCharCode((a-192>>8)+192),result+=String.fromCharCode(a-192&255)):(result+=String.fromCharCode(255),result+=String.fromCharCode(a>>24&255),result+=String.fromCharCode(a>>16&255),result+=String.fromCharCode(a>>8&255),result+=String.fromCharCode(a&255));return result}this.encode_length=b;this.write_old_packet_header=function(a,b){var d="";256>b?(d+=String.fromCharCode(128|a<<2),d+=
-String.fromCharCode(b)):(65536>b?(d+=String.fromCharCode(a<<2|129),d+=String.fromCharCode(b>>8)):(d+=String.fromCharCode(a<<2|130),d+=String.fromCharCode(b>>24&255),d+=String.fromCharCode(b>>16&255),d+=String.fromCharCode(b>>8&255)),d+=String.fromCharCode(b&255));return d};this.write_packet_header=function(a,c){var d;d=""+String.fromCharCode(192|a);return d+=b(c)};this.read_packet=function(a,b,d){if(null==a||a.length<=b||2>a.substring(b).length||0==(a[b].charCodeAt()&128))return util.print_error("Error during parsing. This message / key is probably not containing a valid OpenPGP format."),
-null;var e=b,f=-1,g=-1,g=0;0!=(a[e].charCodeAt()&64)&&(g=1);var h;g?f=a[e].charCodeAt()&63:(f=(a[e].charCodeAt()&63)>>2,h=a[e].charCodeAt()&3);e++;var j=null,k=-1;if(g)if(192>a[e].charCodeAt())packet_length=a[e++].charCodeAt(),util.print_debug("1 byte length:"+packet_length);else if(192<=a[e].charCodeAt()&&224>a[e].charCodeAt())packet_length=(a[e++].charCodeAt()-192<<8)+a[e++].charCodeAt()+192,util.print_debug("2 byte length:"+packet_length);else if(223<a[e].charCodeAt()&&255>a[e].charCodeAt()){packet_length=
-1<<(a[e++].charCodeAt()&31);util.print_debug("4 byte length:"+packet_length);k=e+packet_length;for(j=a.substring(e,e+packet_length);;)if(192>a[k].charCodeAt()){d=a[k++].charCodeAt();packet_length+=d;j+=a.substring(k,k+d);k+=d;break}else if(192<=a[k].charCodeAt()&&224>a[k].charCodeAt()){d=(a[k++].charCodeAt()-192<<8)+a[k++].charCodeAt()+192;packet_length+=d;j+=a.substring(k,k+d);k+=d;break}else if(223<a[k].charCodeAt()&&255>a[k].charCodeAt())d=1<<(a[k++].charCodeAt()&31),packet_length+=d,j+=a.substring(k,
-k+d),k+=d;else{k++;d=a[k++].charCodeAt()<<24|a[k++].charCodeAt()<<16|a[k++].charCodeAt()<<8|a[k++].charCodeAt();j+=a.substring(k,k+d);packet_length+=d;k+=d;break}}else e++,packet_length=a[e++].charCodeAt()<<24|a[e++].charCodeAt()<<16|a[e++].charCodeAt()<<8|a[e++].charCodeAt();else switch(h){case 0:packet_length=a[e++].charCodeAt();break;case 1:packet_length=a[e++].charCodeAt()<<8|a[e++].charCodeAt();break;case 2:packet_length=a[e++].charCodeAt()<<24|a[e++].charCodeAt()<<16|a[e++].charCodeAt()<<8|
-a[e++].charCodeAt();break;default:packet_length=d}-1==k&&(k=packet_length);null==j&&(j=a.substring(e,e+k));switch(f){case 0:break;case 1:f=new openpgp_packet_encryptedsessionkey;if(null!=f.read_pub_key_packet(j,0,packet_length))return f.headerLength=e-b,f.packetLength=k,f;break;case 2:f=new openpgp_packet_signature;if(null!=f.read_packet(j,0,packet_length))return f.headerLength=e-b,f.packetLength=k,f;break;case 3:f=new openpgp_packet_encryptedsessionkey;if(null!=f.read_symmetric_key_packet(j,0,packet_length))return f.headerLength=
-e-b,f.packetLength=k,f;break;case 4:f=new openpgp_packet_onepasssignature;if(f.read_packet(j,0,packet_length))return f.headerLength=e-b,f.packetLength=k,f;break;case 5:f=new openpgp_packet_keymaterial;f.header=a.substring(b,e);if(null!=f.read_tag5(j,0,packet_length))return f.headerLength=e-b,f.packetLength=k,f;break;case 6:f=new openpgp_packet_keymaterial;f.header=a.substring(b,e);if(null!=f.read_tag6(j,0,packet_length))return f.headerLength=e-b,f.packetLength=k,f;break;case 7:f=new openpgp_packet_keymaterial;
-if(null!=f.read_tag7(j,0,packet_length))return f.headerLength=e-b,f.packetLength=k,f;break;case 8:f=new openpgp_packet_compressed;if(null!=f.read_packet(j,0,packet_length))return f.headerLength=e-b,f.packetLength=k,f;break;case 9:f=new openpgp_packet_encrypteddata;if(null!=f.read_packet(j,0,packet_length))return f.headerLength=e-b,f.packetLength=k,f;break;case 10:f=new openpgp_packet_marker;if(null!=f.read_packet(j,0,packet_length))return f.headerLength=e-b,f.packetLength=k,f;break;case 11:f=new openpgp_packet_literaldata;
-if(null!=f.read_packet(j,0,packet_length))return f.headerLength=e-b,f.header=a.substring(b,e),f.packetLength=k,f;break;case 12:break;case 13:f=new openpgp_packet_userid;if(null!=f.read_packet(j,0,packet_length))return f.headerLength=e-b,f.packetLength=k,f;break;case 14:f=new openpgp_packet_keymaterial;f.header=a.substring(b,e);if(null!=f.read_tag14(j,0,packet_length))return f.headerLength=e-b,f.packetLength=k,f;break;case 17:f=new openpgp_packet_userattribute;if(null!=f.read_packet(j,0,packet_length))return f.headerLength=
-e-b,f.packetLength=k,f;break;case 18:f=new openpgp_packet_encryptedintegrityprotecteddata;if(null!=f.read_packet(j,0,packet_length))return f.headerLength=e-b,f.packetLength=k,f;break;case 19:f=new openpgp_packet_modificationdetectioncode;if(null!=f.read_packet(j,0,packet_length))return f.headerLength=e-b,f.packetLength=k,f;break;default:return util.print_error("openpgp.packet.js\n[ERROR] openpgp_packet: failed to parse packet @:"+e+"\nchar:'"+util.hexstrdump(a.substring(e))+"'\ninput:"+util.hexstrdump(a)),
-null}};this.type={reserved:0,public_key_encrypted_session_key:1,signature:2,symmetric_key_encrypted_session_key:3,one_pass_signature:4,secret_key:5,public_key:6,secret_subkey:7,compressed:8,symmetrically_encrypted_data:9,marker:10,literal:11,trust:12,userid:13,public_subkey:14,user_attribute:17,sym_encrypted_and_integrity_protected_data:18,modification_detection_code:19}}var openpgp_packet=new _openpgp_packet;
 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(b,a,c){this.tagType=5;this.read_priv_key(b,a,c);return this};this.read_tag6=function(b,a,c){this.tagType=
 6;this.packetLength=c;this.read_pub_key(b,a,c);return this};this.read_tag7=function(b,a,c){this.tagType=7;this.packetLength=c;return this.read_priv_key(b,a,c)};this.read_tag14=function(b,a,c){this.subKeySignature=null;this.subKeyRevocationSignature=[];this.tagType=14;this.packetLength=c;this.read_pub_key(b,a,c);return this};this.toString=function(){var b="";switch(this.tagType){case 6:b+="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:b+="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:b+="5.5.1.3. Secret-Key Packet (Tag 5)\n    length:             "+
@@ -406,11 +396,7 @@ this.parentNode.header.substring(1)+this.parentNode.data+String.fromCharCode(153
 a),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(a,b){var c=new openpgp_symenc_cast5;c.setKey(b);return c.encrypt(util.str2bin(a))},this.IVLength,util.str2bin(c.substring(0,16)),b+a,
 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,b+a,this.IV),e+=this.IV+ciphertextMPIs}else e+=String.fromCharCode(0),e+=a.d.toMPI()+a.p.toMPI()+a.q.toMPI()+a.u.toMPI(),c=util.calc_checksum(a.d.toMPI()+a.p.toMPI()+a.q.toMPI()+a.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 :"+b)}c=openpgp_packet.write_packet_header(5,e.length);return{string:c+e,header:c,body:e}};this.write_public_key=function(b,a,c){var d=String.fromCharCode(4),d=d+c;switch(b){case 1:d+=String.fromCharCode(1);d+=a.n.toMPI();d+=a.ee.toMPI();break;default:util.print_error("openpgp.packet.keymaterial.js\nerror writing private key, unknown type :"+b)}b=openpgp_packet.write_packet_header(6,d.length);
-return{string:b+d,header:b,body:d}}}function openpgp_packetlist(){this.list=[];this.read=function(b){for(var a=0;a<b.length;){var c=openpgp_packet.read_packet(b,a,b.length-a),a=a+(c.headerLength+c.packetLength);list.push(c)}};this.write=function(){var b="",a;for(a in this.list)var c=this.list[a].write(),b=b+openpgp_packet.write_packet_header(this.list[a].tag,c.length),b=b+c;return b};this.push=function(b){this.list.push(b)}}
-function openpgp_packet_literaldata(){this.tag=11;this.format=openpgp_packet_literaldata.formats.utf8;this.data="";this.date=new Date;this.set_data=function(b,a){this.format=a;this.data=b};this.set_data_bytes=function(b,a){this.format=a;a==openpgp_packet_literaldata.formats.utf8&&(b=util.decode_utf8(b));this.data=b};this.get_data_bytes=function(){return this.format==openpgp_packet_literaldata.formats.utf8?util.encode_utf8(this.data):this.data};this.read=function(b){var a=input[position];this.filename=
-util.decode_utf8(b.substr(2,b.charCodeAt(1)));this.date=new Date(1E3*parseInt(b.substr(2+b.charCodeAt(1),4)));this.set_data_bytes(b.substring(6+b.charCodeAt(1)),a);return this};this.write=function(){var b=util.encode_utf8("msg.txt"),a=this.get_data_bytes();result+=this.format;result+=String.fromCharCode(b.length);result+=b;result+=String.fromCharCode(Math.round(this.date.getTime()/1E3)>>24&255);result+=String.fromCharCode(Math.round(this.date.getTime()/1E3)>>16&255);result+=String.fromCharCode(Math.round(this.date.getTime()/
-1E3)>>8&255);result+=String.fromCharCode(Math.round(this.date.getTime()/1E3)&255);return result+=a};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"}}openpgp_packet_literaldata.formats={binary:"b",text:"t",utf8:"u"};
-function openpgp_packet_marker(){this.tagType=10;this.read_packet=function(b,a){this.packetLength=3;return 80==b[a].charCodeAt()&&71==b[a+1].charCodeAt()&&80==b[a+2].charCodeAt()?this:null};this.toString=function(){return'5.8.  Marker Packet (Obsolete Literal Packet) (Tag 10)\n     packet reads: "PGP"\n'}}
+return{string:b+d,header:b,body:d}}}function openpgp_packet_marker(){this.tagType=10;this.read_packet=function(b,a){this.packetLength=3;return 80==b[a].charCodeAt()&&71==b[a+1].charCodeAt()&&80==b[a+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(b,a,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=b.substring(a,a+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_onepasssignature(){this.tagType=4;this.flags=this.signingKeyId=this.publicKeyAlgorithm=this.hashAlgorithm=this.type=this.version=null;this.read_packet=read_packet;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=write_packet}
@@ -455,7 +441,16 @@ this.certificationSignatures[c].issuerKeyId)result[c]=0;else{var d=openpgp.keyri
 24&255)+String.fromCharCode(a.length>>16&255)+String.fromCharCode(a.length>>8&255)+String.fromCharCode(a.length&255)+a;if(e.verify(f,d)){result[c]=this.certificationSignatures[c].issuerKeyId==b.getKeyId()?6:3;continue}}f=String.fromCharCode(153)+b.header.substring(1)+b.data+String.fromCharCode(180)+String.fromCharCode(a.length>>24&255)+String.fromCharCode(a.length>>16&255)+String.fromCharCode(a.length>>8&255)+String.fromCharCode(a.length&255)+a;result[c]=this.certificationSignatures[c].verify(f,d)?
 4:0}}else if(3==this.certificationSignatures[c].version)if(null==this.certificationSignatures[c].keyId)result[c]=0;else if(d=openpgp.keyring.getPublicKeysForKeyId(this.certificationSignatures[c].keyId),null==d||0==d.length)result[c]=2;else if(d=publicKey.obj.getSigningKey(),null==d)result[c]=0;else{e=this.hasCertificationRevocationSignature(this.certificationSignatures[c].keyId);if(null!=e&&e.creationTime>this.certificationSignatures[c].creationTime&&(f=String.fromCharCode(153)+this.publicKeyPacket.header.substring(1)+
 this.publicKeyPacket.data+a,e.verify(f,d))){result[c]=e.keyId==b.getKeyId()?6:3;continue}f=String.fromCharCode(153)+b.header.substring(1)+b.data+a;result[c]=this.certificationSignatures[c].verify(f,d)?4:0}else result[c]=0;return result};this.verify=function(b){b=this.verifyCertificationSignatures(b);return-1!=b.indexOf(6)?2:-1!=b.indexOf(5)?1:0};this.addCertification=function(){};this.revokeCertification=function(){}}
-function openpgp_type_keyid(){this.read_packet=function(b,a){this.bytes=b.substring(a,a+8);return this};this.toString=function(){return util.hexstrdump(this.bytes)}}
+function _openpgp_packet(){function b(a){result="";192>a?result+=String.fromCharCode(a):191<a&&8384>a?(result+=String.fromCharCode((a-192>>8)+192),result+=String.fromCharCode(a-192&255)):(result+=String.fromCharCode(255),result+=String.fromCharCode(a>>24&255),result+=String.fromCharCode(a>>16&255),result+=String.fromCharCode(a>>8&255),result+=String.fromCharCode(a&255));return result}this.encode_length=b;this.write_old_packet_header=function(a,b){var d="";256>b?(d+=String.fromCharCode(128|a<<2),d+=
+String.fromCharCode(b)):(65536>b?(d+=String.fromCharCode(a<<2|129),d+=String.fromCharCode(b>>8)):(d+=String.fromCharCode(a<<2|130),d+=String.fromCharCode(b>>24&255),d+=String.fromCharCode(b>>16&255),d+=String.fromCharCode(b>>8&255)),d+=String.fromCharCode(b&255));return d};this.write_packet_header=function(a,c){var d;d=""+String.fromCharCode(192|a);return d+=b(c)};this.read_packet=function(a,b,d){if(null==a||a.length<=b||2>a.substring(b).length||0==(a[b].charCodeAt()&128))return util.print_error("Error during parsing. This message / key is probably not containing a valid OpenPGP format."),
+null;var e=-1,f=-1,f=0;0!=(a[b].charCodeAt()&64)&&(f=1);var g;f?e=a[b].charCodeAt()&63:(e=(a[b].charCodeAt()&63)>>2,g=a[b].charCodeAt()&3);b++;var h=null,j=-1;if(f)if(192>a[b].charCodeAt())packet_length=a[b++].charCodeAt(),util.print_debug("1 byte length:"+packet_length);else if(192<=a[b].charCodeAt()&&224>a[b].charCodeAt())packet_length=(a[b++].charCodeAt()-192<<8)+a[b++].charCodeAt()+192,util.print_debug("2 byte length:"+packet_length);else if(223<a[b].charCodeAt()&&255>a[b].charCodeAt()){packet_length=
+1<<(a[b++].charCodeAt()&31);util.print_debug("4 byte length:"+packet_length);d=b+packet_length;for(h=a.substring(b,b+packet_length);;)if(192>a[d].charCodeAt()){g=a[d++].charCodeAt();packet_length+=g;h+=a.substring(d,d+g);d+=g;break}else if(192<=a[d].charCodeAt()&&224>a[d].charCodeAt()){g=(a[d++].charCodeAt()-192<<8)+a[d++].charCodeAt()+192;packet_length+=g;h+=a.substring(d,d+g);d+=g;break}else if(223<a[d].charCodeAt()&&255>a[d].charCodeAt())g=1<<(a[d++].charCodeAt()&31),packet_length+=g,h+=a.substring(d,
+d+g),d+=g;else{d++;g=a[d++].charCodeAt()<<24|a[d++].charCodeAt()<<16|a[d++].charCodeAt()<<8|a[d++].charCodeAt();h+=a.substring(d,d+g);packet_length+=g;d+=g;break}j=d}else b++,packet_length=a[b++].charCodeAt()<<24|a[b++].charCodeAt()<<16|a[b++].charCodeAt()<<8|a[b++].charCodeAt();else switch(g){case 0:packet_length=a[b++].charCodeAt();break;case 1:packet_length=a[b++].charCodeAt()<<8|a[b++].charCodeAt();break;case 2:packet_length=a[b++].charCodeAt()<<24|a[b++].charCodeAt()<<16|a[b++].charCodeAt()<<
+8|a[b++].charCodeAt();break;default:packet_length=d}-1==j&&(j=packet_length);null==h&&(h=a.substring(b,b+j));var a={},k;for(k in this.type)a[this.type[k]]=k;k="openpgp_packet_"+a[e];a=window[k];if(void 0==a)throw k;k=new a;k.read(h);return{packet:k,offset:b+packet_length}};this.type={reserved:0,public_key_encrypted_session_key:1,signature:2,symmetric_key_encrypted_session_key:3,one_pass_signature:4,secret_key:5,public_key:6,secret_subkey:7,compressed:8,symmetrically_encrypted:9,marker:10,literal:11,
+trust:12,userid:13,public_subkey:14,user_attribute:17,sym_encrypted_and_integrity_protected:18,modification_detection_code:19}}var openpgp_packet=new _openpgp_packet;
+function openpgp_packetlist(){this.packets=[];this.read=function(b){this.packets=[];for(var a=0;a<b.length;){var c=openpgp_packet.read_packet(b,a,b.length-a),a=a+c.offset;this.push(c.packet)}};this.write=function(){var b="",a;for(a in this.packets)var c=this.packets[a].write(),b=b+openpgp_packet.write_packet_header(this.packets[a].tag,c.length),b=b+c;return b};this.push=function(b){this.packets.push(b)}}
+function openpgp_packet_symmetrically_encrypted(){this.tag=9;this.encrypted=null;this.data=new openpgp_packetlist;this.algorithm=openpgp.symmetric.plaintext;this.read=function(b){this.encrypted=b};this.write=function(){return this.encrypted};this.decrypt=function(b,a){this.data.read(openpgp_crypto_symmetricDecrypt(b,a,this.encrypted,!0))};this.encrypt=function(b,a){var c=this.data.write();this.encrypted=openpgp_crypto_symmetricEncrypt(openpgp_crypto_getPrefixRandom(b),b,a,c,!0)};this.toString=function(){return"5.7.  Symmetrically Encrypted Data Packet (Tag 9)\n    Used symmetric algorithm: "+
+this.algorithmType+"\n    encrypted data: Bytes ["+util.hexstrdump(this.encryptedData)+"]\n"}}function openpgp_type_keyid(){this.read_packet=function(b,a){this.bytes=b.substring(a,a+8);return this};this.toString=function(){return util.hexstrdump(this.bytes)}}
 function openpgp_type_mpi(){this.data=this.mpiByteLength=this.mpiBitLength=this.MPI=null;this.read=function(b,a){var c=a;this.mpiBitLength=b[c++].charCodeAt()<<8|b[c++].charCodeAt();this.mpiByteLength=(this.mpiBitLength-this.mpiBitLength%8)/8;0!=this.mpiBitLength%8&&this.mpiByteLength++;this.MPI=b.substring(c,c+this.mpiByteLength);this.data=b.substring(a,a+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 b="    MPI("+this.mpiBitLength+"b/"+this.mpiByteLength+"B) : 0x",b=b+util.hexstrdump(this.MPI);return b+"\n"};this.create=function(b){this.MPI=b;var a=8*(b.length-1),c;a:for(var d=b.charCodeAt(0),e=0;9>e;e++)if(0==d>>e){c=e;break a}this.mpiBitLength=a+c;this.mpiByteLength=b.length;return this};this.toBin=function(){var b=String.fromCharCode(this.mpiBitLength>>8&255),b=b+String.fromCharCode(this.mpiBitLength&255);return b+=this.MPI};this.getByteLength=function(){return this.mpiByteLength}}
 function openpgp_type_s2k(){this.read=function(b,a){var c=a;this.type=b[c++].charCodeAt();switch(this.type){case 0:this.hashAlgorithm=b[c++].charCodeAt();this.s2kLength=1;break;case 1:this.hashAlgorithm=b[c++].charCodeAt();this.saltValue=b.substring(c,c+8);this.s2kLength=9;break;case 3:this.hashAlgorithm=b[c++].charCodeAt();this.saltValue=b.substring(c,c+8);c+=8;this.EXPBIAS=6;c=b[c++].charCodeAt();this.count=16+(c&15)<<(c>>4)+this.EXPBIAS;this.s2kLength=10;break;case 101:"GNU"==b.substring(c+1,c+
diff --git a/src/packet/openpgp.packet.literaldata.js b/src/packet/literal.js
similarity index 91%
rename from src/packet/openpgp.packet.literaldata.js
rename to src/packet/literal.js
index bc76f18d..5ffdfe1a 100644
--- a/src/packet/openpgp.packet.literaldata.js
+++ b/src/packet/literal.js
@@ -22,9 +22,9 @@
  * 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() {
+function openpgp_packet_literal() {
 	this.tag = 11;
-	this.format = openpgp_packet_literaldata.formats.utf8;
+	this.format = openpgp_packet_literal.format.utf8;
 	this.data = '';
 	this.date = new Date();
 
@@ -34,7 +34,7 @@ function openpgp_packet_literaldata() {
 	 * bytes. Conversion to a proper utf8 encoding takes place when the 
 	 * packet is written.
 	 * @param {String} str Any native javascript string
-	 * @param {openpgp_packet_literaldata.formats} format 
+	 * @param {openpgp_packet_literaldata.format} format 
 	 */
 	this.set_data = function(str, format) {
 		this.format = format;
@@ -45,12 +45,12 @@ function openpgp_packet_literaldata() {
 	 * Set the packet data to value represented by the provided string
 	 * of bytes together with the appropriate conversion format.
 	 * @param {String} bytes The string of bytes
-	 * @param {openpgp_packet_literaldata.formats} format
+	 * @param {openpgp_packet_literaldata.format} format
 	 */
 	this.set_data_bytes = function(bytes, format) {
 		this.format = format;
 
-		if(format == openpgp_packet_literaldata.formats.utf8)
+		if(format == openpgp_packet_literal.format.utf8)
 			bytes = util.decode_utf8(bytes);
 
 		this.data = bytes;
@@ -61,7 +61,7 @@ function openpgp_packet_literaldata() {
 	 * @returns {String} A sequence of bytes
 	 */
 	this.get_data_bytes = function() {
-		if(this.format == openpgp_packet_literaldata.formats.utf8)
+		if(this.format == openpgp_packet_literal.format.utf8)
 			return util.encode_utf8(this.data);
 		else
 			return this.data;
@@ -83,7 +83,7 @@ function openpgp_packet_literaldata() {
 	this.read = function(bytes) {
 		// - A one-octet field that describes how the data is formatted.
 
-		var format = input[position];
+		var format = bytes[0];
 
 		this.filename = util.decode_utf8(bytes.substr(2, bytes
 				.charCodeAt(1)));
@@ -95,7 +95,6 @@ function openpgp_packet_literaldata() {
 				+ bytes.charCodeAt(1));
 	
 		this.set_data_bytes(data, format);
-		return this;
 	}
 
 	/**
@@ -109,6 +108,7 @@ function openpgp_packet_literaldata() {
 
 		var data = this.get_data_bytes();
 
+		var result = '';
 		result += this.format;
 		result += String.fromCharCode(filename.length);
 		result += filename;
@@ -143,7 +143,7 @@ function openpgp_packet_literaldata() {
  * @readonly
  * @enum {String}
  */
-openpgp_packet_literaldata.formats = {
+openpgp_packet_literal.format = {
 	/** Binary data */
 	binary: 'b',
 	/** Text data */
diff --git a/src/packet/openpgp.packet.js b/src/packet/packet.js
similarity index 66%
rename from src/packet/openpgp.packet.js
rename to src/packet/packet.js
index 36f84449..871d2875 100644
--- a/src/packet/openpgp.packet.js
+++ b/src/packet/packet.js
@@ -252,153 +252,32 @@ function _openpgp_packet() {
 		// 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:
+		var names_by_tag = {};
+
+		for(var i in this.type)
+			names_by_tag[this.type[i]] = i;
+
+		var classname = 'openpgp_packet_' + names_by_tag[tag];
+
+		var packetclass = window[classname];
+
+		if(packetclass == undefined) {
+			throw classname;
 			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;
 		}
+
+		var result = new packetclass();
+		result.read(bodydata);
+
+		return { 
+			packet: result, 
+			offset: mypos + packet_length
+		};
 	}
 
 	this.read_packet = read_packet;
@@ -418,14 +297,14 @@ function _openpgp_packet() {
 		public_key: 6,
 		secret_subkey: 7,
 		compressed: 8,
-		symmetrically_encrypted_data: 9,
+		symmetrically_encrypted: 9,
 		marker: 10,
 		literal: 11,
 		trust: 12,
 		userid: 13,
 		public_subkey: 14,
 		user_attribute: 17,
-		sym_encrypted_and_integrity_protected_data: 18,
+		sym_encrypted_and_integrity_protected: 18,
 		modification_detection_code: 19
 	};
 }
diff --git a/src/packet/openpgp.packetlist.js b/src/packet/packetlist.js
similarity index 67%
rename from src/packet/openpgp.packetlist.js
rename to src/packet/packetlist.js
index 69994410..d00c1190 100644
--- a/src/packet/openpgp.packetlist.js
+++ b/src/packet/packetlist.js
@@ -7,7 +7,7 @@
 function openpgp_packetlist() {
 
 	/** @type {openpgp_packet_[]} A list of packets */
-	this.list = []
+	this.packets = []
 
 
 
@@ -16,13 +16,14 @@ function openpgp_packetlist() {
 	 * @param {openpgp_bytearray} An array of bytes.
 	 */
 	this.read = function(bytes) {
+		this.packets = [];
 		var i = 0;
 
 		while(i < bytes.length) {
-			var packet = openpgp_packet.read_packet(bytes, i, bytes.length - i);
-			i += packet.headerLength + packet.packetLength;
+			var parsed = openpgp_packet.read_packet(bytes, i, bytes.length - i);
+			i += parsed.offset;
 
-			list.push(packet);
+			this.push(parsed.packet);
 		}
 	}
 
@@ -34,9 +35,9 @@ function openpgp_packetlist() {
 	this.write = function() {
 		var bytes = '';
 
-		for(var i in this.list) {
-			var packetbytes = this.list[i].write();
-			bytes += openpgp_packet.write_packet_header(this.list[i].tag, packetbytes.length);
+		for(var i in this.packets) {
+			var packetbytes = this.packets[i].write();
+			bytes += openpgp_packet.write_packet_header(this.packets[i].tag, packetbytes.length);
 			bytes += packetbytes;
 		}
 		
@@ -44,7 +45,7 @@ function openpgp_packetlist() {
 	}
 
 	this.push = function(packet) {
-		this.list.push(packet);
+		this.packets.push(packet);
 	}
 
 }
diff --git a/src/packet/openpgp.packet.encrypteddata.js b/src/packet/symmetrically_encrypted.js
similarity index 89%
rename from src/packet/openpgp.packet.encrypteddata.js
rename to src/packet/symmetrically_encrypted.js
index 116ba537..2855ed46 100644
--- a/src/packet/openpgp.packet.encrypteddata.js
+++ b/src/packet/symmetrically_encrypted.js
@@ -26,7 +26,7 @@
  * that form whole OpenPGP messages).
  */
 
-function openpgp_packet_encrypteddata() {
+function openpgp_packet_symmetrically_encrypted() {
 	this.tag = 9;
 	this.encrypted = null;
 	this.data = new openpgp_packetlist();
@@ -54,13 +54,9 @@ function openpgp_packet_encrypteddata() {
 	 */
 	this.decrypt = function(symmetric_algorithm_type, key) {
 		var decrypted = openpgp_crypto_symmetricDecrypt(
-				symmetric_algorithm_type, key, this.encryptedData, true);
+				symmetric_algorithm_type, key, this.encrypted, true);
 
-		util.print_debug("openpgp.packet.encryptedintegrityprotecteddata.js\n"+
-				"data: "+util.hexstrdump(this.decryptedData));
-
-
-		this.data = new openpgp_packetlist(decrypted);
+		this.data.read(decrypted);
 	}
 
 	this.encrypt = function(algo, key) {
diff --git a/test/general/packet.js b/test/general/packet.js
index fc1843a2..d99a3bd1 100644
--- a/test/general/packet.js
+++ b/test/general/packet.js
@@ -5,10 +5,10 @@ unittests.register("Packet testing", function() {
 
 
 
-		var literal = new openpgp_packet_literaldata();
-		literal.set_data('Hello world', openpgp_packet_literaldata.formats.utf8);
+		var literal = new openpgp_packet_literal();
+		literal.set_data('Hello world', openpgp_packet_literal.format.utf8);
 		
-		var enc = new openpgp_packet_encrypteddata();
+		var enc = new openpgp_packet_symmetrically_encrypted();
 		enc.data.push(literal);
 
 		var key = '12345678901234567890123456789012',
@@ -23,9 +23,10 @@ unittests.register("Packet testing", function() {
 		var msg2 = new openpgp_packetlist();
 		msg2.read(message.write());
 
-		msg2[0].decrypt(algo, key);
+		msg2.packets[0].decrypt(algo, key);
 
-		return msg2[0].data[0].data == literal.data;
+		return new test_result('Symmetrically encrypted data packet', 
+			msg2.packets[0].data.packets[0].data == literal.data);
 	}];
 
 	var results = [];