diff --git a/resources/openpgp.js b/resources/openpgp.js
index a060ca84..539d4754 100644
--- a/resources/openpgp.js
+++ b/resources/openpgp.js
@@ -3925,7 +3925,7 @@ function openpgp_crypto_verifySignature(algo, hash_algo, msg_MPIs, publickey_MPI
  * @param {openpgp_type_mpi[]} secretMPIs Private key multiprecision 
  * integers which is used to sign the data
  * @param {String} data Data to be signed
- * @return {(String|openpgp_type_mpi)}
+ * @return {openpgp_type_mpi[]}
  */
 function openpgp_crypto_signData(hash_algo, algo, publicMPIs, secretMPIs, data) {
 	
@@ -3936,7 +3936,7 @@ function openpgp_crypto_signData(hash_algo, algo, publicMPIs, secretMPIs, data)
 		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);
+		var m = openpgp_encoding_emsa_pkcs1_encode(hash_algo, data,publicMPIs[0].byteLength());
 		util.print_debug("signing using RSA");
 		return rsa.sign(m, d, n).toMPI();
 	case 17: // DSA (Digital Signature Algorithm) [FIPS186] [HAC]
@@ -3950,7 +3950,7 @@ function openpgp_crypto_signData(hash_algo, algo, publicMPIs, secretMPIs, data)
 		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];
+		return result[0].toString() + result[1].toString();
 	case 16: // Elgamal (Encrypt-Only) [ELGAMAL] [HAC]
 			util.print_debug("signing with Elgamal is not defined in the OpenPGP standard.");
 			return null;
@@ -10917,15 +10917,19 @@ function openpgp_packet_secret_subkey() {
  */
 function openpgp_packet_signature() {
 	this.tag = 2;
+
 	this.signatureType = null;
-	this.created = null;
+	this.hashAlgorithm = null;
+	this.publicKeyAlgorithm = null; 
+	this.version = 4;
+
 	this.signatureData = null;
-	this.signatureExpirationTime = null;
-	this.signatureNeverExpires = null;
 	this.signedHashValue = null;
 	this.mpi = null;
-	this.publicKeyAlgorithm = null; 
-	this.hashAlgorithm = null;
+
+	this.created = null;
+	this.signatureExpirationTime = null;
+	this.signatureNeverExpires = null;
 	this.exportable = null;
 	this.trustLevel = null;
 	this.trustAmount = null;
@@ -10953,6 +10957,7 @@ function openpgp_packet_signature() {
 	this.signatureTargetHashAlgorithm = null;
 	this.signatureTargetHash = null;
 	this.embeddedSignature = null;
+
 	this.verified = false;
 	
 
@@ -11052,71 +11057,48 @@ function openpgp_packet_signature() {
 		this.signedHashValue = bytes.substr(i, 2);
 		i += 2;
 
-		var mpicount = 0;
-		// Algorithm-Specific Fields for RSA signatures:
-		// 	    - multiprecision number (MPI) of RSA signature value m**d mod n.
-		if (this.publicKeyAlgorithm > 0 && this.publicKeyAlgorithm < 4)
-			mpicount = 1;
-		//    Algorithm-Specific Fields for DSA signatures:
-		//      - MPI of DSA value r.
-		//      - MPI of DSA value s.
-		else if (this.publicKeyAlgorithm == 17)
-			mpicount = 2;
-		
-		this.mpi = [];
-		for (var j = 0; j < mpicount; j++) {
-			this.mpi[j] = new openpgp_type_mpi();
-			i += this.mpi[j].read(bytes.substr(i));
-		}
+		this.signature = bytes.substr(i);
+	}
+
+	this.write = function() {
+		return this.signatureData + 
+			openpgp_packet_number_write(0, 2) + // Number of unsigned subpackets.
+			this.signedHashValue +
+			this.signature;
 	}
 
 	/**
-	 * creates a string representation of a message signature packet (tag 2).
-	 * This can be only used on text data
-	 * @param {Integer} signature_type should be 1 (one) 
-	 * @param {String} data data to be signed
-	 * @param {openpgp_msg_privatekey} privatekey private key used to sign the message. (secmpi MUST be unlocked)
-	 * @return {String} string representation of a signature packet
+	 * Signs provided data. This needs to be done prior to serialization.
+	 * @param {Object} data Contains packets to be signed.
+	 * @param {openpgp_msg_privatekey} privatekey private key used to sign the message. 
 	 */
-	function write_message_signature(signature_type, data, privatekey) {
-		var publickey = privatekey.privateKeyPacket.publicKey;
-		var hash_algo = privatekey.getPreferredSignatureHashAlgorithm();
+	this.sign = function(privatekey, data) {
+		var publickey = privatekey.public_key;
+
 		var result = String.fromCharCode(4); 
-		result += String.fromCharCode(signature_type);
-		result += String.fromCharCode(publickey.publicKeyAlgorithm);
-		result += String.fromCharCode(hash_algo);
-		var d = Math.round(new Date().getTime() / 1000);
-		var datesubpacket = write_sub_signature_packet(2,""+
-				String.fromCharCode((d >> 24) & 0xFF) + 
-				String.fromCharCode((d >> 16) & 0xFF) +
-				String.fromCharCode((d >> 8) & 0xFF) + 
-				String.fromCharCode(d & 0xFF));
-		var issuersubpacket = write_sub_signature_packet(16, privatekey.getKeyId());
-		result += String.fromCharCode(((datesubpacket.length + issuersubpacket.length) >> 8) & 0xFF);
-		result += String.fromCharCode ((datesubpacket.length + issuersubpacket.length) & 0xFF);
-		result += datesubpacket;
-		result += issuersubpacket;
-		var trailer = '';
+		result += String.fromCharCode(this.signatureType);
+		result += String.fromCharCode(this.publicKeyAlgorithm);
+		result += String.fromCharCode(this.hashAlgorithm);
+
+
+		// Add subpackets here
+		result += openpgp_packet_number_write(0, 2);
+
+
+		this.signatureData = result;
+
+		var trailer = this.calculateTrailer();
 		
-		trailer += String.fromCharCode(4);
-		trailer += String.fromCharCode(0xFF);
-		trailer += String.fromCharCode((result.length) >> 24);
-		trailer += String.fromCharCode(((result.length) >> 16) & 0xFF);
-		trailer += String.fromCharCode(((result.length) >> 8) & 0xFF);
-		trailer += String.fromCharCode((result.length) & 0xFF);
-		var result2 = String.fromCharCode(0);
-		result2 += String.fromCharCode(0);
-		var hash = openpgp_crypto_hashData(hash_algo, data+result+trailer);
-		util.print_debug("DSA Signature is calculated with:|"+data+result+trailer+"|\n"+util.hexstrdump(data+result+trailer)+"\n hash:"+util.hexstrdump(hash));
-		result2 += hash.charAt(0);
-		result2 += hash.charAt(1);
-		result2 += openpgp_crypto_signData(hash_algo,privatekey.privateKeyPacket.publicKey.publicKeyAlgorithm,
-				publickey.mpi,
-				privatekey.privateKeyPacket.secmpi,
-				data+result+trailer);
-		return {openpgp: (openpgp_packet.write_packet_header(2, (result+result2).length)+result + result2), 
-				hash: util.get_hashAlgorithmString(hash_algo)};
+		var toHash = this.toSign(this.signatureType, data) + this.signatureData + trailer;
+		var hash = openpgp_crypto_hashData(this.hashAlgorithm, toHash);
+		
+		this.signedHashValue = hash.substr(0, 2);
+
+
+		this.signature = openpgp_crypto_signData(this.hashAlgorithm, this.publicKeyAlgorithm, 
+			publickey.mpi, privatekey.mpi, toHash);
 	}
+
 	/**
 	 * creates a string representation of a sub signature packet (See RFC 4880 5.2.3.1)
 	 * @param {Integer} type subpacket signature type. Signature types as described 
@@ -11124,7 +11106,7 @@ function openpgp_packet_signature() {
 	 * @param {String} data data to be included
 	 * @return {String} a string-representation of a sub signature packet (See RFC 4880 5.2.3.1)
 	 */
-	function write_sub_signature_packet(type, data) {
+	function write_sub_packet(type, data) {
 		var result = "";
 		result += openpgp_packet.encode_length(data.length+1);
 		result += String.fromCharCode(type);
@@ -11341,6 +11323,16 @@ function openpgp_packet_signature() {
 		}
 	}
 
+	
+	this.calculateTrailer = function() {
+		// calculating the trailer
+		var trailer = '';
+		trailer += String.fromCharCode(this.version);
+		trailer += String.fromCharCode(0xFF);
+		trailer += openpgp_packet_number_write(this.signatureData.length, 4);
+		return trailer
+	}
+
 
 	/**
 	 * verifys the signature packet. Note: not signature types are implemented
@@ -11350,16 +11342,29 @@ function openpgp_packet_signature() {
 	 */
 	this.verify = function(key, data) {
 
-		var bytes = this.toSign(this.signatureType, data);
+		var bytes = this.toSign(this.signatureType, data),
+			trailer = this.calculateTrailer();
 
-		// calculating the trailer
-		var trailer = '';
-		trailer += String.fromCharCode(this.version);
-		trailer += String.fromCharCode(0xFF);
-		trailer += openpgp_packet_number_write(this.signatureData.length, 4);
+
+		var mpicount = 0;
+		// Algorithm-Specific Fields for RSA signatures:
+		// 	    - multiprecision number (MPI) of RSA signature value m**d mod n.
+		if (this.publicKeyAlgorithm > 0 && this.publicKeyAlgorithm < 4)
+			mpicount = 1;
+		//    Algorithm-Specific Fields for DSA signatures:
+		//      - MPI of DSA value r.
+		//      - MPI of DSA value s.
+		else if (this.publicKeyAlgorithm == 17)
+			mpicount = 2;
+		
+		var mpi = [], i = 0;
+		for (var j = 0; j < mpicount; j++) {
+			mpi[j] = new openpgp_type_mpi();
+			i += mpi[j].read(this.signature.substr(i));
+		}
 
 		this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, 
-			this.hashAlgorithm, this.mpi, key.mpi, 
+			this.hashAlgorithm, mpi, key.mpi, 
 			bytes + this.signatureData + trailer);
 
 		return this.verified;
diff --git a/resources/openpgp.min.js b/resources/openpgp.min.js
index 9caa9f70..dd269657 100644
--- a/resources/openpgp.min.js
+++ b/resources/openpgp.min.js
@@ -114,8 +114,8 @@ function openpgp_crypto_MDCSystemBytes(a,b,c){util.print_debug_hexstr_dump("open
 "Twofish Algorithm not implemented"))}return null}function openpgp_crypto_generateSessionKey(a){return openpgp_crypto_getRandomBytes(openpgp_crypto_getKeyLength(a))}function openpgp_crypto_getKeyLength(a){switch(a){case 2:case 8:return 24;case 3:case 4:case 7:return 16;case 9:case 10:return 32}return null}function openpgp_crypto_getBlockLength(a){switch(a){case 1:case 2:case 3:return 8;case 4:case 7:case 8:case 9:return 16;case 10:return 32;default:return 0}}
 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(),j=d[2].toBigInteger(),d=d[3].toBigInteger(),d=a.verify(b,f,c,e,h,g,j,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_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].byteLength());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].toString()+a[1].toString();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)}}
@@ -383,18 +383,19 @@ switch(f){case 1:throw Error("IDEA is not implemented.");case 2:f=normal_cfb_dec
 b)},g.length,new keyExpansion(a),c,g);break;case 10:throw Error("Twofish is not implemented.");default:throw Error("Unknown symmetric algorithm.");}this.mpi=b(254==h?openpgp.hash.sha1:"mod",f,this.public_key.algorithm)}};this.getKeyId=function(){if(4==this.version)return this.getFingerprint().substring(12,20);if(3==this.version&&0<this.publicKeyAlgorithm&&4>this.publicKeyAlgorithm){var a=this.MPIs[0].substring(this.MPIs[0].mpiByteLength-8);util.print_debug("openpgp.msg.publickey read_nodes:\nV3 key ID: "+
 a);return a}};this.getFingerprint=function(){if(4==this.version)return tohash=String.fromCharCode(153)+String.fromCharCode(this.packetdata.length>>8&255)+String.fromCharCode(this.packetdata.length&255)+this.packetdata,util.print_debug("openpgp.msg.publickey creating subkey fingerprint by hashing:"+util.hexstrdump(tohash)+"\npublickeyalgorithm: "+this.publicKeyAlgorithm),str_sha1(tohash,tohash.length);if(3==this.version&&0<this.publicKeyAlgorithm&&4>this.publicKeyAlgorithm)return MD5(this.MPIs[0].MPI)}}
 function openpgp_packet_secret_subkey(){openpgp_packet_secret_key.call(this);this.tag=7}
-function openpgp_packet_signature(){this.tag=2;this.issuerKeyId=this.revocationKeyFingerprint=this.revocationKeyAlgorithm=this.revocationKeyClass=this.preferredSymmetricAlgorithms=this.keyNeverExpires=this.keyExpirationTime=this.revocable=this.regularExpression=this.trustAmount=this.trustLevel=this.exportable=this.hashAlgorithm=this.publicKeyAlgorithm=this.mpi=this.signedHashValue=this.signatureNeverExpires=this.signatureExpirationTime=this.signatureData=this.created=this.signatureType=null;this.notation=
-{};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=null;this.verified=!1;this.read=function(a){var b=0;this.version=a[b++].charCodeAt();switch(this.version){case 3:5!=a[b++].charCodeAt()&&
-util.print_debug("openpgp.packet.signature.js\ninvalid One-octet length of following hashed material.MUST be 5. @:"+(b-1));this.signatureType=a[b++].charCodeAt();this.created=openpgp_packet_time_read(a.substr(b,4));b+=4;this.signatureData=a.substring(position,b);this.issuerKeyId=a.substring(b,b+8);b+=8;this.publicKeyAlgorithm=a[b++].charCodeAt();this.hashAlgorithm=a[b++].charCodeAt();break;case 4:this.signatureType=a[b++].charCodeAt();this.publicKeyAlgorithm=a[b++].charCodeAt();this.hashAlgorithm=
-a[b++].charCodeAt();var c=function(a,b){for(var c=openpgp_packet_number_read(a.substr(0,2)),d=2;d<2+c;){var j=openpgp_packet.read_simple_length(a.substr(d)),d=d+j.offset;b&&this.read_sub_packet(a.substr(d,j.len));d+=j.len}return d},b=b+c.call(this,a.substr(b),!0);this.signatureData=a.substr(0,b);b+=c.call(this,a.substr(b),!1);break;default:util.print_error("openpgp.packet.signature.js\nunknown signature packet version"+this.version)}this.signedHashValue=a.substr(b,2);b+=2;c=0;0<this.publicKeyAlgorithm&&
-4>this.publicKeyAlgorithm?c=1:17==this.publicKeyAlgorithm&&(c=2);this.mpi=[];for(var d=0;d<c;d++)this.mpi[d]=new openpgp_type_mpi,b+=this.mpi[d].read(a.substr(b))};this.read_sub_packet=function(a){function b(a,b){this[a]=[];for(var c=0;c<b.length;c++)this[a].push(b[c].charCodeAt())}var c=0,d=a[c++].charCodeAt()&127;switch(d){case 2:this.created=openpgp_packet_time_read(a.substr(c));break;case 3:a=openpgp_packet_time_read(a.substr(c));this.signatureNeverExpires=0==a.getTime();this.signatureExpirationTime=
-a;break;case 4:this.exportable=1==a[c++].charCodeAt();break;case 5:this.trustLevel=a[c++].charCodeAt();this.trustAmount=a[c++].charCodeAt();break;case 6:this.regularExpression=a.substr(c);break;case 7:this.revocable=1==a[c++].charCodeAt();break;case 9:this.keyExpirationTime=a=openpgp_packet_time_read(a.substr(c));this.keyNeverExpires=0==a.getTime();break;case 11:for(this.preferredSymmetricAlgorithms=[];c!=a.length;)this.preferredSymmetricAlgorithms.push(a[c++].charCodeAt());break;case 12:this.revocationKeyClass=
-a[c++].charCodeAt();this.revocationKeyAlgorithm=a[c++].charCodeAt();this.revocationKeyFingerprint=a.substr(c,20);break;case 16:this.issuerKeyId=a.substr(c,8);break;case 20:if(128==a[c].charCodeAt()){var c=c+4,e=openpgp_packet_number_read(a.substr(c,2)),c=c+2,f=openpgp_packet_number_read(a.substr(c,2)),c=c+2,d=a.substr(c,e),a=a.substr(c+e,f);this.notation[d]=a}break;case 21:b.call(this,"preferredHashAlgorithms",a.substr(c));break;case 22:b.call(this,"preferredCompressionAlgorithms ",a.substr(c));break;
-case 23:b.call(this,"keyServerPreferencess",a.substr(c));break;case 24:this.preferredKeyServer=a.substr(c);break;case 25:this.isPrimaryUserID=0!=a[c++];break;case 26:this.policyURI=a.substr(c);break;case 27:b.call(this,"keyFlags",a.substr(c));break;case 28:this.signersUserId+=a.substr(c);break;case 29:this.reasonForRevocationFlag=a[c++].charCodeAt();this.reasonForRevocationString=a.substr(c);break;case 30:b.call(this,"features",a.substr(c));break;case 31:this.signatureTargetPublicKeyAlgorithm=a[c++].charCodeAt();
-this.signatureTargetHashAlgorithm=a[c++].charCodeAt();e=openpgp_crypto_getHashByteLength(this.signatureTargetHashAlgorithm);this.signatureTargetHash=a.substr(c,e);break;case 32:this.embeddedSignature=new openpgp_packet_signature;this.embeddedSignature.read(a.substr(c));break;default:util.print_error("openpgp.packet.signature.js\nunknown signature subpacket type "+d+" @:"+c+" subplen:"+subplen+" len:"+e)}};this.toSign=function(a,b){var c=openpgp_packet_signature.type;switch(a){case c.binary:return b.literal.get_data_bytes();
-case c.text:return toSign(c.binary,b).replace(/\r\n/g,"\n").replace(/\n/g,"\r\n");case c.standalone:return"";case c.cert_generic:case c.cert_persona:case c.cert_casual:case c.cert_positive:case c.cert_revocation:var d,e;if(void 0!=b.userid)e=180,d=b.userid;else if(void 0!=b.userattribute)e=209,d=b.userattribute;else throw Error("Either a userid or userattribute packet needs to be supplied for certification.");d=d.write();return this.toSign(c.key,b)+String.fromCharCode(e)+openpgp_packet_number_write(d.length,
-4)+d;case c.subkey_binding:case c.key_binding:return this.toSign(c.key,b)+this.toSign(c.key,{key:b.bind});case c.key:if(void 0==b.key)throw Error("Key packet is required for this sigtature.");d=b.key.write();return String.fromCharCode(153)+openpgp_packet_number_write(d.length,2)+d;case c.key_revocation:case c.subkey_revocation:return this.toSign(c.key,b);case c.timestamp:return"";case c.thrid_party:throw Error("Not implemented");default:throw Error("Unknown signature type.");}};this.verify=function(a,
-b){var c=this.toSign(this.signatureType,b),d;d=""+String.fromCharCode(this.version);d+=String.fromCharCode(255);d+=openpgp_packet_number_write(this.signatureData.length,4);return this.verified=openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.mpi,a.mpi,c+this.signatureData+d)}}
+function openpgp_packet_signature(){this.tag=2;this.publicKeyAlgorithm=this.hashAlgorithm=this.signatureType=null;this.version=4;this.issuerKeyId=this.revocationKeyFingerprint=this.revocationKeyAlgorithm=this.revocationKeyClass=this.preferredSymmetricAlgorithms=this.keyNeverExpires=this.keyExpirationTime=this.revocable=this.regularExpression=this.trustAmount=this.trustLevel=this.exportable=this.signatureNeverExpires=this.signatureExpirationTime=this.created=this.mpi=this.signedHashValue=this.signatureData=
+null;this.notation={};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=null;this.verified=!1;this.read=function(a){var b=0;this.version=a[b++].charCodeAt();switch(this.version){case 3:5!=
+a[b++].charCodeAt()&&util.print_debug("openpgp.packet.signature.js\ninvalid One-octet length of following hashed material.MUST be 5. @:"+(b-1));this.signatureType=a[b++].charCodeAt();this.created=openpgp_packet_time_read(a.substr(b,4));b+=4;this.signatureData=a.substring(position,b);this.issuerKeyId=a.substring(b,b+8);b+=8;this.publicKeyAlgorithm=a[b++].charCodeAt();this.hashAlgorithm=a[b++].charCodeAt();break;case 4:this.signatureType=a[b++].charCodeAt();this.publicKeyAlgorithm=a[b++].charCodeAt();
+this.hashAlgorithm=a[b++].charCodeAt();var c=function(a,b){for(var c=openpgp_packet_number_read(a.substr(0,2)),h=2;h<2+c;){var g=openpgp_packet.read_simple_length(a.substr(h)),h=h+g.offset;b&&this.read_sub_packet(a.substr(h,g.len));h+=g.len}return h},b=b+c.call(this,a.substr(b),!0);this.signatureData=a.substr(0,b);b+=c.call(this,a.substr(b),!1);break;default:util.print_error("openpgp.packet.signature.js\nunknown signature packet version"+this.version)}this.signedHashValue=a.substr(b,2);this.signature=
+a.substr(b+2)};this.write=function(){return this.signatureData+openpgp_packet_number_write(0,2)+this.signedHashValue+this.signature};this.sign=function(a,b){var c=a.public_key,d=String.fromCharCode(4),d=d+String.fromCharCode(this.signatureType),d=d+String.fromCharCode(this.publicKeyAlgorithm),d=d+String.fromCharCode(this.hashAlgorithm);this.signatureData=d+=openpgp_packet_number_write(0,2);d=this.calculateTrailer();d=this.toSign(this.signatureType,b)+this.signatureData+d;this.signedHashValue=openpgp_crypto_hashData(this.hashAlgorithm,
+d).substr(0,2);this.signature=openpgp_crypto_signData(this.hashAlgorithm,this.publicKeyAlgorithm,c.mpi,a.mpi,d)};this.read_sub_packet=function(a){function b(a,b){this[a]=[];for(var c=0;c<b.length;c++)this[a].push(b[c].charCodeAt())}var c=0,d=a[c++].charCodeAt()&127;switch(d){case 2:this.created=openpgp_packet_time_read(a.substr(c));break;case 3:a=openpgp_packet_time_read(a.substr(c));this.signatureNeverExpires=0==a.getTime();this.signatureExpirationTime=a;break;case 4:this.exportable=1==a[c++].charCodeAt();
+break;case 5:this.trustLevel=a[c++].charCodeAt();this.trustAmount=a[c++].charCodeAt();break;case 6:this.regularExpression=a.substr(c);break;case 7:this.revocable=1==a[c++].charCodeAt();break;case 9:this.keyExpirationTime=a=openpgp_packet_time_read(a.substr(c));this.keyNeverExpires=0==a.getTime();break;case 11:for(this.preferredSymmetricAlgorithms=[];c!=a.length;)this.preferredSymmetricAlgorithms.push(a[c++].charCodeAt());break;case 12:this.revocationKeyClass=a[c++].charCodeAt();this.revocationKeyAlgorithm=
+a[c++].charCodeAt();this.revocationKeyFingerprint=a.substr(c,20);break;case 16:this.issuerKeyId=a.substr(c,8);break;case 20:if(128==a[c].charCodeAt()){var c=c+4,e=openpgp_packet_number_read(a.substr(c,2)),c=c+2,f=openpgp_packet_number_read(a.substr(c,2)),c=c+2,d=a.substr(c,e),a=a.substr(c+e,f);this.notation[d]=a}break;case 21:b.call(this,"preferredHashAlgorithms",a.substr(c));break;case 22:b.call(this,"preferredCompressionAlgorithms ",a.substr(c));break;case 23:b.call(this,"keyServerPreferencess",
+a.substr(c));break;case 24:this.preferredKeyServer=a.substr(c);break;case 25:this.isPrimaryUserID=0!=a[c++];break;case 26:this.policyURI=a.substr(c);break;case 27:b.call(this,"keyFlags",a.substr(c));break;case 28:this.signersUserId+=a.substr(c);break;case 29:this.reasonForRevocationFlag=a[c++].charCodeAt();this.reasonForRevocationString=a.substr(c);break;case 30:b.call(this,"features",a.substr(c));break;case 31:this.signatureTargetPublicKeyAlgorithm=a[c++].charCodeAt();this.signatureTargetHashAlgorithm=
+a[c++].charCodeAt();e=openpgp_crypto_getHashByteLength(this.signatureTargetHashAlgorithm);this.signatureTargetHash=a.substr(c,e);break;case 32:this.embeddedSignature=new openpgp_packet_signature;this.embeddedSignature.read(a.substr(c));break;default:util.print_error("openpgp.packet.signature.js\nunknown signature subpacket type "+d+" @:"+c+" subplen:"+subplen+" len:"+e)}};this.toSign=function(a,b){var c=openpgp_packet_signature.type;switch(a){case c.binary:return b.literal.get_data_bytes();case c.text:return toSign(c.binary,
+b).replace(/\r\n/g,"\n").replace(/\n/g,"\r\n");case c.standalone:return"";case c.cert_generic:case c.cert_persona:case c.cert_casual:case c.cert_positive:case c.cert_revocation:var d,e;if(void 0!=b.userid)e=180,d=b.userid;else if(void 0!=b.userattribute)e=209,d=b.userattribute;else throw Error("Either a userid or userattribute packet needs to be supplied for certification.");d=d.write();return this.toSign(c.key,b)+String.fromCharCode(e)+openpgp_packet_number_write(d.length,4)+d;case c.subkey_binding:case c.key_binding:return this.toSign(c.key,
+b)+this.toSign(c.key,{key:b.bind});case c.key:if(void 0==b.key)throw Error("Key packet is required for this sigtature.");d=b.key.write();return String.fromCharCode(153)+openpgp_packet_number_write(d.length,2)+d;case c.key_revocation:case c.subkey_revocation:return this.toSign(c.key,b);case c.timestamp:return"";case c.thrid_party:throw Error("Not implemented");default:throw Error("Unknown signature type.");}};this.calculateTrailer=function(){var a;a=""+String.fromCharCode(this.version);a+=String.fromCharCode(255);
+return a+=openpgp_packet_number_write(this.signatureData.length,4)};this.verify=function(a,b){var c=this.toSign(this.signatureType,b),d=this.calculateTrailer(),e=0;0<this.publicKeyAlgorithm&&4>this.publicKeyAlgorithm?e=1:17==this.publicKeyAlgorithm&&(e=2);for(var f=[],h=0,g=0;g<e;g++)f[g]=new openpgp_type_mpi,h+=f[g].read(this.signature.substr(h));return this.verified=openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,f,a.mpi,c+this.signatureData+d)}}
 openpgp_packet_signature.type={binary:0,text:1,standalone:2,cert_generic:16,cert_persona:17,cert_casual:18,cert_positive:19,cert_revocation:48,subkey_binding:24,key_binding:25,key:31,key_revocation:32,subkey_revocation:40,timestamp:64,third_party:80};
 function openpgp_packet_sym_encrypted_integrity_protected(){this.tag=18;this.version=1;this.encrypted=null;this.modification=!1;this.packets=new openpgp_packetlist;this.read=function(a){this.version=a[0].charCodeAt();if(1!=this.version)return util.print_error("openpgp.packet.encryptedintegrityprotecteddata.js\nunknown encrypted integrity protected data packet version: "+this.version+"hex:"+util.hexstrdump(a)),null;this.encrypted=a.substr(1)};this.write=function(){return String.fromCharCode(this.version)+
 this.encrypted};this.encrypt=function(a,b){var c=this.packets.write(),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));this.encrypted=openpgp_crypto_symmetricEncrypt(d,a,b,c,!1).substring(0,e.length+c.length)};this.decrypt=function(a,b){var c=openpgp_crypto_symmetricDecrypt(a,
diff --git a/src/ciphers/openpgp.crypto.js b/src/ciphers/openpgp.crypto.js
index 7c6869b0..bd8e799b 100644
--- a/src/ciphers/openpgp.crypto.js
+++ b/src/ciphers/openpgp.crypto.js
@@ -283,7 +283,7 @@ function openpgp_crypto_verifySignature(algo, hash_algo, msg_MPIs, publickey_MPI
  * @param {openpgp_type_mpi[]} secretMPIs Private key multiprecision 
  * integers which is used to sign the data
  * @param {String} data Data to be signed
- * @return {(String|openpgp_type_mpi)}
+ * @return {openpgp_type_mpi[]}
  */
 function openpgp_crypto_signData(hash_algo, algo, publicMPIs, secretMPIs, data) {
 	
@@ -294,7 +294,7 @@ function openpgp_crypto_signData(hash_algo, algo, publicMPIs, secretMPIs, data)
 		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);
+		var m = openpgp_encoding_emsa_pkcs1_encode(hash_algo, data,publicMPIs[0].byteLength());
 		util.print_debug("signing using RSA");
 		return rsa.sign(m, d, n).toMPI();
 	case 17: // DSA (Digital Signature Algorithm) [FIPS186] [HAC]
@@ -308,7 +308,7 @@ function openpgp_crypto_signData(hash_algo, algo, publicMPIs, secretMPIs, data)
 		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];
+		return result[0].toString() + result[1].toString();
 	case 16: // Elgamal (Encrypt-Only) [ELGAMAL] [HAC]
 			util.print_debug("signing with Elgamal is not defined in the OpenPGP standard.");
 			return null;
diff --git a/src/packet/signature.js b/src/packet/signature.js
index 182068d2..6c6e78a7 100644
--- a/src/packet/signature.js
+++ b/src/packet/signature.js
@@ -26,15 +26,19 @@
  */
 function openpgp_packet_signature() {
 	this.tag = 2;
+
 	this.signatureType = null;
-	this.created = null;
+	this.hashAlgorithm = null;
+	this.publicKeyAlgorithm = null; 
+	this.version = 4;
+
 	this.signatureData = null;
-	this.signatureExpirationTime = null;
-	this.signatureNeverExpires = null;
 	this.signedHashValue = null;
 	this.mpi = null;
-	this.publicKeyAlgorithm = null; 
-	this.hashAlgorithm = null;
+
+	this.created = null;
+	this.signatureExpirationTime = null;
+	this.signatureNeverExpires = null;
 	this.exportable = null;
 	this.trustLevel = null;
 	this.trustAmount = null;
@@ -62,6 +66,7 @@ function openpgp_packet_signature() {
 	this.signatureTargetHashAlgorithm = null;
 	this.signatureTargetHash = null;
 	this.embeddedSignature = null;
+
 	this.verified = false;
 	
 
@@ -161,71 +166,48 @@ function openpgp_packet_signature() {
 		this.signedHashValue = bytes.substr(i, 2);
 		i += 2;
 
-		var mpicount = 0;
-		// Algorithm-Specific Fields for RSA signatures:
-		// 	    - multiprecision number (MPI) of RSA signature value m**d mod n.
-		if (this.publicKeyAlgorithm > 0 && this.publicKeyAlgorithm < 4)
-			mpicount = 1;
-		//    Algorithm-Specific Fields for DSA signatures:
-		//      - MPI of DSA value r.
-		//      - MPI of DSA value s.
-		else if (this.publicKeyAlgorithm == 17)
-			mpicount = 2;
-		
-		this.mpi = [];
-		for (var j = 0; j < mpicount; j++) {
-			this.mpi[j] = new openpgp_type_mpi();
-			i += this.mpi[j].read(bytes.substr(i));
-		}
+		this.signature = bytes.substr(i);
+	}
+
+	this.write = function() {
+		return this.signatureData + 
+			openpgp_packet_number_write(0, 2) + // Number of unsigned subpackets.
+			this.signedHashValue +
+			this.signature;
 	}
 
 	/**
-	 * creates a string representation of a message signature packet (tag 2).
-	 * This can be only used on text data
-	 * @param {Integer} signature_type should be 1 (one) 
-	 * @param {String} data data to be signed
-	 * @param {openpgp_msg_privatekey} privatekey private key used to sign the message. (secmpi MUST be unlocked)
-	 * @return {String} string representation of a signature packet
+	 * Signs provided data. This needs to be done prior to serialization.
+	 * @param {Object} data Contains packets to be signed.
+	 * @param {openpgp_msg_privatekey} privatekey private key used to sign the message. 
 	 */
-	function write_message_signature(signature_type, data, privatekey) {
-		var publickey = privatekey.privateKeyPacket.publicKey;
-		var hash_algo = privatekey.getPreferredSignatureHashAlgorithm();
+	this.sign = function(privatekey, data) {
+		var publickey = privatekey.public_key;
+
 		var result = String.fromCharCode(4); 
-		result += String.fromCharCode(signature_type);
-		result += String.fromCharCode(publickey.publicKeyAlgorithm);
-		result += String.fromCharCode(hash_algo);
-		var d = Math.round(new Date().getTime() / 1000);
-		var datesubpacket = write_sub_signature_packet(2,""+
-				String.fromCharCode((d >> 24) & 0xFF) + 
-				String.fromCharCode((d >> 16) & 0xFF) +
-				String.fromCharCode((d >> 8) & 0xFF) + 
-				String.fromCharCode(d & 0xFF));
-		var issuersubpacket = write_sub_signature_packet(16, privatekey.getKeyId());
-		result += String.fromCharCode(((datesubpacket.length + issuersubpacket.length) >> 8) & 0xFF);
-		result += String.fromCharCode ((datesubpacket.length + issuersubpacket.length) & 0xFF);
-		result += datesubpacket;
-		result += issuersubpacket;
-		var trailer = '';
+		result += String.fromCharCode(this.signatureType);
+		result += String.fromCharCode(this.publicKeyAlgorithm);
+		result += String.fromCharCode(this.hashAlgorithm);
+
+
+		// Add subpackets here
+		result += openpgp_packet_number_write(0, 2);
+
+
+		this.signatureData = result;
+
+		var trailer = this.calculateTrailer();
 		
-		trailer += String.fromCharCode(4);
-		trailer += String.fromCharCode(0xFF);
-		trailer += String.fromCharCode((result.length) >> 24);
-		trailer += String.fromCharCode(((result.length) >> 16) & 0xFF);
-		trailer += String.fromCharCode(((result.length) >> 8) & 0xFF);
-		trailer += String.fromCharCode((result.length) & 0xFF);
-		var result2 = String.fromCharCode(0);
-		result2 += String.fromCharCode(0);
-		var hash = openpgp_crypto_hashData(hash_algo, data+result+trailer);
-		util.print_debug("DSA Signature is calculated with:|"+data+result+trailer+"|\n"+util.hexstrdump(data+result+trailer)+"\n hash:"+util.hexstrdump(hash));
-		result2 += hash.charAt(0);
-		result2 += hash.charAt(1);
-		result2 += openpgp_crypto_signData(hash_algo,privatekey.privateKeyPacket.publicKey.publicKeyAlgorithm,
-				publickey.mpi,
-				privatekey.privateKeyPacket.secmpi,
-				data+result+trailer);
-		return {openpgp: (openpgp_packet.write_packet_header(2, (result+result2).length)+result + result2), 
-				hash: util.get_hashAlgorithmString(hash_algo)};
+		var toHash = this.toSign(this.signatureType, data) + this.signatureData + trailer;
+		var hash = openpgp_crypto_hashData(this.hashAlgorithm, toHash);
+		
+		this.signedHashValue = hash.substr(0, 2);
+
+
+		this.signature = openpgp_crypto_signData(this.hashAlgorithm, this.publicKeyAlgorithm, 
+			publickey.mpi, privatekey.mpi, toHash);
 	}
+
 	/**
 	 * creates a string representation of a sub signature packet (See RFC 4880 5.2.3.1)
 	 * @param {Integer} type subpacket signature type. Signature types as described 
@@ -233,7 +215,7 @@ function openpgp_packet_signature() {
 	 * @param {String} data data to be included
 	 * @return {String} a string-representation of a sub signature packet (See RFC 4880 5.2.3.1)
 	 */
-	function write_sub_signature_packet(type, data) {
+	function write_sub_packet(type, data) {
 		var result = "";
 		result += openpgp_packet.encode_length(data.length+1);
 		result += String.fromCharCode(type);
@@ -450,6 +432,16 @@ function openpgp_packet_signature() {
 		}
 	}
 
+	
+	this.calculateTrailer = function() {
+		// calculating the trailer
+		var trailer = '';
+		trailer += String.fromCharCode(this.version);
+		trailer += String.fromCharCode(0xFF);
+		trailer += openpgp_packet_number_write(this.signatureData.length, 4);
+		return trailer
+	}
+
 
 	/**
 	 * verifys the signature packet. Note: not signature types are implemented
@@ -459,16 +451,29 @@ function openpgp_packet_signature() {
 	 */
 	this.verify = function(key, data) {
 
-		var bytes = this.toSign(this.signatureType, data);
+		var bytes = this.toSign(this.signatureType, data),
+			trailer = this.calculateTrailer();
 
-		// calculating the trailer
-		var trailer = '';
-		trailer += String.fromCharCode(this.version);
-		trailer += String.fromCharCode(0xFF);
-		trailer += openpgp_packet_number_write(this.signatureData.length, 4);
+
+		var mpicount = 0;
+		// Algorithm-Specific Fields for RSA signatures:
+		// 	    - multiprecision number (MPI) of RSA signature value m**d mod n.
+		if (this.publicKeyAlgorithm > 0 && this.publicKeyAlgorithm < 4)
+			mpicount = 1;
+		//    Algorithm-Specific Fields for DSA signatures:
+		//      - MPI of DSA value r.
+		//      - MPI of DSA value s.
+		else if (this.publicKeyAlgorithm == 17)
+			mpicount = 2;
+		
+		var mpi = [], i = 0;
+		for (var j = 0; j < mpicount; j++) {
+			mpi[j] = new openpgp_type_mpi();
+			i += mpi[j].read(this.signature.substr(i));
+		}
 
 		this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, 
-			this.hashAlgorithm, this.mpi, key.mpi, 
+			this.hashAlgorithm, mpi, key.mpi, 
 			bytes + this.signatureData + trailer);
 
 		return this.verified;
diff --git a/test/general/packet.js b/test/general/packet.js
index ef023f62..12eaf1ac 100644
--- a/test/general/packet.js
+++ b/test/general/packet.js
@@ -424,6 +424,53 @@ unittests.register("Packet testing", function() {
 	
 		return new test_result('Writing and encryptio of a secret key packet.',
 			key[0].mpi.toString() == key2[0].mpi.toString());
+	}, function() {
+		var key = new openpgp_packet_secret_key;
+
+		var rsa = new RSA(),
+			mpi = rsa.generate(512, "10001")
+
+
+		var mpi = [
+			[mpi.d, mpi.p, mpi.q, mpi.u],
+			[mpi.n, mpi.ee]];
+
+		mpi = mpi.map(function(k) {
+			return k.map(function(bn) {
+				var mpi = new openpgp_type_mpi();
+				mpi.fromBigInteger(bn);
+				return mpi;
+				});
+		});
+
+		key.public_key.mpi = mpi[1];
+		key.mpi = mpi[0];
+
+		var signed = new openpgp_packetlist(),
+			literal = new openpgp_packet_literal(),
+			signature = new openpgp_packet_signature();
+
+		literal.set_data('Hello world', openpgp_packet_literal.format.utf8);
+
+		signature.hashAlgorithm = openpgp.hash.sha256;
+		signature.publicKeyAlgorithm = openpgp.publickey.rsa_sign;
+		signature.signatureType = openpgp_packet_signature.type.binary;
+
+		signature.sign(key, { literal: literal });
+
+		signed.push(literal);
+		signed.push(signature);
+
+		var raw = signed.write();
+
+		var signed2 = new openpgp_packetlist();
+		signed2.read(raw);
+
+		var verified = signed2[1].verify(key.public_key, { literal: signed2[0] });
+	
+	
+		return new test_result('Writing and verification of a signature packet.',
+			verified == true);
 	}];