Source: openpgp.msg.message.js

// 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

/**
 * @protected
 * @class
 * @classdesc Top-level message object. Contains information from one or more packets
 */

function openpgp_msg_message() {
	
	// -1 = no valid passphrase submitted
	// -2 = no private key found
	// -3 = decryption error
	// text = valid decryption
	this.text = "";
	this.messagePacket = null;
	this.type = null;
	
	/**
	 * Decrypts a message and generates user interface message out of the found.
	 * MDC will be verified as well as message signatures
	 * @param {openpgp_msg_privatekey} private_key the private the message is encrypted with (corresponding to the session key)
	 * @param {openpgp_packet_encryptedsessionkey} sessionkey the session key to be used to decrypt the message
	 * @return {String} plaintext of the message or null on error
	 */
	function decrypt(private_key, sessionkey) {
        return this.decryptAndVerifySignature(private_key, sessionkey).text;
	}

	/**
	 * Decrypts a message and generates user interface message out of the found.
	 * MDC will be verified as well as message signatures
	 * @param {openpgp_msg_privatekey} private_key the private the message is encrypted with (corresponding to the session key)
	 * @param {openpgp_packet_encryptedsessionkey} sessionkey the session key to be used to decrypt the message
	 * @param {openpgp_msg_publickey} pubkey Array of public keys to check signature against. If not provided, checks local keystore.
	 * @return {String} plaintext of the message or null on error
	 */
	function decryptAndVerifySignature(private_key, sessionkey, pubkey) {
		if (private_key == null || sessionkey == null || sessionkey == "")
			return null;
		var decrypted = sessionkey.decrypt(this, private_key.keymaterial);
		if (decrypted == null)
			return null;
		var packet;
		var position = 0;
		var len = decrypted.length;
		var validSignatures = new Array();
		util.print_debug_hexstr_dump("openpgp.msg.messge decrypt:\n",decrypted);
		
		var messages = openpgp.read_messages_dearmored({text: decrypted, openpgp: decrypted});
		for(var m in messages){
			if(messages[m].data){
				this.text = messages[m].data;
			}
			if(messages[m].signature){
			    validSignatures.push(messages[m].verifySignature(pubkey));
			}
		}
		return {text:this.text, validSignatures:validSignatures};
	}
	
	/**
	 * Verifies a message signature. This function can be called after read_message if the message was signed only.
	 * @param {openpgp_msg_publickey} pubkey Array of public keys to check signature against. If not provided, checks local keystore.
	 * @return {boolean} true if the signature was correct; otherwise false
	 */
	function verifySignature(pubkey) {
		var result = false;
		if (this.signature.tagType == 2) {
		    if(!pubkey || pubkey.length == 0){
			    var pubkey;
			    if (this.signature.version == 4) {
				    pubkey = openpgp.keyring.getPublicKeysForKeyId(this.signature.issuerKeyId);
			    } else if (this.signature.version == 3) {
				    pubkey = openpgp.keyring.getPublicKeysForKeyId(this.signature.keyId);
			    } else {
				    util.print_error("unknown signature type on message!");
				    return false;
			    }
			}
			if (pubkey.length == 0)
				util.print_warning("Unable to verify signature of issuer: "+util.hexstrdump(this.signature.issuerKeyId)+". Public key not found in keyring.");
			else {
				for (var i = 0 ; i < pubkey.length; i++) {
					var tohash = this.text.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n");
					if (this.signature.verify(tohash, pubkey[i])) {
						util.print_info("Found Good Signature from "+pubkey[i].obj.userIds[0].text+" (0x"+util.hexstrdump(pubkey[i].obj.getKeyId()).substring(8)+")");
						result = true;
					} else {
						util.print_error("Signature verification failed: Bad Signature from "+pubkey[i].obj.userIds[0].text+" (0x"+util.hexstrdump(pubkey[0].obj.getKeyId()).substring(8)+")");
					}
				}
			}
		}
		return result;
	}
	
	function toString() {
		var result = "Session Keys:\n";
		if (this.sessionKeys !=null)
		for (var i = 0; i < this.sessionKeys.length; i++) {
			result += this.sessionKeys[i].toString();
		}
		result += "\n\n EncryptedData:\n";
		if(this.encryptedData != null)
		result += this.encryptedData.toString();
		
		result += "\n\n Signature:\n";
		if(this.signature != null)
		result += this.signature.toString();
		
		result += "\n\n Text:\n"
		if(this.signature != null)
			result += this.text;
		return result;
	}
	this.decrypt = decrypt;
	this.decryptAndVerifySignature = decryptAndVerifySignature;
	this.verifySignature = verifySignature;
	this.toString = toString;
}