diff --git a/resources/openpgp.js b/resources/openpgp.js index c3ed8712..2b93c92d 100644 --- a/resources/openpgp.js +++ b/resources/openpgp.js @@ -8362,6 +8362,17 @@ function _openpgp () { var openpgp = new _openpgp(); +/** RFC4880, section 9.1 + * @enum {Integer} + */ +openpgp.publickey = { + rsa_encrypt_sign: 1, + rsa_encrypt: 2, + rsa_sign: 3, + elgamal: 16, + dsa: 17 +}; + /** RFC4880, section 9.2 * @enum {Integer} */ @@ -8378,7 +8389,30 @@ openpgp.symmetric = { twofish: 10 }; +/** RFC4880, section 9.3 + * @enum {Integer} + */ +openpgp.compression = { + uncompressed: 0, + /** RFC1951 */ + zip: 1, + /** RFC1950 */ + zlib: 2, + bzip2: 3 +}; +/** RFC4880, section 9.4 + * @enum {Integer} + */ +openpgp.hash = { + md5: 1, + sha1: 2, + ripemd: 3, + sha256: 8, + sha384: 9, + sha512: 10, + sha224: 11 +}; // GPG4Browsers - An OpenPGP implementation in javascript // Copyright (C) 2011 Recurity Labs GmbH // @@ -9257,6 +9291,173 @@ 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 Compressed Data Packet (Tag 8) + * + * RFC4880 5.6: + * The Compressed Data packet contains compressed data. Typically, this + * packet is found as the contents of an encrypted packet, or following + * a Signature or One-Pass Signature packet, and contains a literal data + * packet. + */ +function openpgp_packet_compressed() { + this.tag = 8; + this.packets = new openpgp_packetlist(); + this.algorithm = openpgp.compression.uncompressed; + this.compressed = null; + + + /** + * Parsing function for the packet. + * @param {String} input Payload of a tag 8 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_compressed} Object representation + */ + this.read = function(bytes) { + // One octet that gives the algorithm used to compress the packet. + this.algorithm = input.charCodeAt(0); + // Compressed data, which makes up the remainder of the packet. + this.compressed = input.substr(1); + + this.decompress(); + } + + + + this.write = function() { + if(this.compressed == null) + this.compress(); + + return String.fromCharCode(this.type) + this.compressed; + } + + + /** + * Decompression method for decompressing the compressed data + * read by read_packet + * @return {String} The decompressed data + */ + this.decompress = function() { + var bytes; + + switch (this.algorithm) { + case openpgp.compression.uncompressed: + decompressed = this.compressed; + break; + + case openpgp.compression.zip: + util.print_info('Decompressed packet [Type 1-ZIP]: ' + this.toString()); + var compData = this.compressed; + + var radix = s2r(compData).replace(/\n/g,""); + // no header in this case, directly call deflate + var jxg_obj = new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(radix)); + + decompressed = unescape(jxg_obj.deflate()[0][0]); + break; + + case openpgp.compression.zlib: + util.print_info('Decompressed packet [Type 2-ZLIB]: ' + this.toString()); + //RFC 1950. Bits 0-3 Compression Method + var compressionMethod = this.compressed.charCodeAt(0) % 0x10; + + //Bits 4-7 RFC 1950 are LZ77 Window. Generally this value is 7 == 32k window size. + // 2nd Byte in RFC 1950 is for "FLAGs" Allows for a Dictionary + // (how is this defined). Basic checksum, and compression level. + + if (compressionMethod == 8) { //CM 8 is for DEFLATE, RFC 1951 + // remove 4 bytes ADLER32 checksum from the end + var compData = this.compressed.substring(0, this.compressed.length - 4); + var radix = s2r(compData).replace(/\n/g,""); + //TODO check ADLER32 checksum + decompressed = JXG.decompress(radix); + break; + + } else { + util.print_error("Compression algorithm ZLIB only supports " + + "DEFLATE compression method."); + } + break; + + case openpgp.compression.bzip2: + // TODO: need to implement this + util.print_error("Compression algorithm BZip2 [BZ2] is not implemented."); + break; + + default: + util.print_error("Compression algorithm unknown :"+this.type); + break; + } + + util.print_debug("decompressed:"+util.hexstrdump(decompressed)); + + this.packets.read(decompressed); + } + + /** + * Compress the packet data (member decompressedData) + * @param {Integer} type Algorithm to be used // See RFC 4880 9.3 + * @param {String} data Data to be compressed + * @return {String} The compressed data stored in attribute compressedData + */ + this.compress = function() { + switch (this.type) { + + case openpgp.compression.uncompressed: // - Uncompressed + this.compressed = this.packets.write(); + break; + + case openpgp.compression.zip: // - ZIP [RFC1951] + util.print_error("Compression algorithm ZIP [RFC1951] is not implemented."); + break; + + case openpgp.compression.zlib: // - ZLIB [RFC1950] + // TODO: need to implement this + util.print_error("Compression algorithm ZLIB [RFC1950] is not implemented."); + break; + + case openpgp.compression.bzip2: // - BZip2 [BZ2] + // TODO: need to implement this + util.print_error("Compression algorithm BZip2 [BZ2] is not implemented."); + break; + + default: + util.print_error("Compression algorithm unknown :"+this.type); + break; + } + } + + + /** + * Pretty printing the packet (useful for debug purposes) + * @return {String} + */ + this.toString = function() { + return '5.6. Compressed Data Packet (Tag 8)\n'+ + ' Compression Algorithm = '+this.algorithm+'\n'+ + ' Compressed Data: Byte ['+util.hexstrdump(this.compressed)+']\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 Literal Data Packet (Tag 11) @@ -9410,343 +9611,6 @@ openpgp_packet_literal.format = { // 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) - * - * RFC4880 5.6: - * The Compressed Data packet contains compressed data. Typically, this - * packet is found as the contents of an encrypted packet, or following - * a Signature or One-Pass Signature packet, and contains a literal data - * packet. - */ -function openpgp_packet_compressed(bytes) { - this.tagType = 8; - this.decompressedData = null; - this.compressedData = null; - this.type = 0; - - if(bytes != undefined) - this.read(bytes); - - /** - * Parsing function for the packet. - * @param {String} input Payload of a tag 8 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_compressed} Object representation - */ - function read_packet (input, position, len) { - this.packetLength = len; - var mypos = position; - // One octet that gives the algorithm used to compress the packet. - this.type = input.charCodeAt(mypos++); - // Compressed data, which makes up the remainder of the packet. - this.compressedData = input.substring(position+1, position+len); - return this; - } - - this.read = function(bytes) { - this.type = input.charCodeAt(mypos++); - this.compressedData = input.substring(position+1, position+len); - this.decompressedData = null; - } - - this.write = function() { - if(this.compressedData == null) - this.compress(); - - return String.fromCharCode(this.type) + this.compress(); - } - - - /** - * Decompression method for decompressing the compressed data - * read by read_packet - * @return {String} The decompressed data - */ - function decompress() { - if (this.decompressedData != null) - return this.decompressedData; - - if (this.type == null) - return null; - - switch (this.type) { - case 0: // - Uncompressed - this.decompressedData = this.compressedData; - break; - case 1: // - ZIP [RFC1951] - util.print_info('Decompressed packet [Type 1-ZIP]: ' + this.toString()); - var compData = this.compressedData; - var radix = s2r(compData).replace(/\n/g,""); - // no header in this case, directly call deflate - var jxg_obj = new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(radix)); - this.decompressedData = unescape(jxg_obj.deflate()[0][0]); - break; - case 2: // - ZLIB [RFC1950] - util.print_info('Decompressed packet [Type 2-ZLIB]: ' + this.toString()); - var compressionMethod = this.compressedData.charCodeAt(0) % 0x10; //RFC 1950. Bits 0-3 Compression Method - //Bits 4-7 RFC 1950 are LZ77 Window. Generally this value is 7 == 32k window size. - //2nd Byte in RFC 1950 is for "FLAGs" Allows for a Dictionary (how is this defined). Basic checksum, and compression level. - if (compressionMethod == 8) { //CM 8 is for DEFLATE, RFC 1951 - // remove 4 bytes ADLER32 checksum from the end - var compData = this.compressedData.substring(0, this.compressedData.length - 4); - var radix = s2r(compData).replace(/\n/g,""); - //TODO check ADLER32 checksum - this.decompressedData = JXG.decompress(radix); - break; - } else { - util.print_error("Compression algorithm ZLIB only supports DEFLATE compression method."); - } - break; - case 3: // - BZip2 [BZ2] - // TODO: need to implement this - util.print_error("Compression algorithm BZip2 [BZ2] is not implemented."); - break; - default: - util.print_error("Compression algorithm unknown :"+this.type); - break; - } - util.print_debug("decompressed:"+util.hexstrdump(this.decompressedData)); - return this.decompressedData; - } - - /** - * Compress the packet data (member decompressedData) - * @param {Integer} type Algorithm to be used // See RFC 4880 9.3 - * @param {String} data Data to be compressed - * @return {String} The compressed data stored in attribute compressedData - */ - function compress() { - switch (this.type) { - case 0: // - Uncompressed - this.compressedData = this.decompressedData; - break; - case 1: // - ZIP [RFC1951] - util.print_error("Compression algorithm ZIP [RFC1951] is not implemented."); - break; - case 2: // - ZLIB [RFC1950] - // TODO: need to implement this - util.print_error("Compression algorithm ZLIB [RFC1950] is not implemented."); - break; - case 3: // - BZip2 [BZ2] - // TODO: need to implement this - util.print_error("Compression algorithm BZip2 [BZ2] is not implemented."); - break; - default: - util.print_error("Compression algorithm unknown :"+this.type); - break; - } - this.packetLength = this.compressedData.length +1; - return this.compressedData; - } - - /** - * Creates a string representation of the packet - * @param {Integer} algorithm Algorithm to be used // See RFC 4880 9.3 - * @param {String} data Data to be compressed - * @return {String} String-representation of the packet - */ - function write_packet(algorithm, data) { - this.decompressedData = data; - if (algorithm == null) { - this.type = 1; - } - var result = String.fromCharCode(this.type)+this.compress(this.type); - return openpgp_packet.write_packet_header(8, result.length)+result; - } - - /** - * Pretty printing the packet (useful for debug purposes) - * @return {String} - */ - function toString() { - return '5.6. Compressed Data Packet (Tag 8)\n'+ - ' length: '+this.packetLength+'\n'+ - ' Compression Algorithm = '+this.type+'\n'+ - ' Compressed Data: Byte ['+util.hexstrdump(this.compressedData)+']\n'; - } - - this.read_packet = read_packet; - this.toString = toString; - this.compress = compress; - this.decompress = decompress; - this.write_packet = write_packet; -}; -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @class - * @classdesc Implementation of the Sym. Encrypted Integrity Protected Data - * Packet (Tag 18) - * - * RFC4880 5.13: The Symmetrically Encrypted Integrity Protected Data packet is - * a variant of the Symmetrically Encrypted Data packet. It is a new feature - * created for OpenPGP that addresses the problem of detecting a modification to - * encrypted data. It is used in combination with a Modification Detection Code - * packet. - */ - -function openpgp_packet_encryptedintegrityprotecteddata() { - this.tagType = 18; - this.version = null; // integer == 1 - this.packetLength = null; // integer - this.encryptedData = null; // string - this.decrytpedData = null; // string - this.hash = null; // string - /** - * Parsing function for the packet. - * - * @param {String} input Payload of a tag 18 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_encryptedintegrityprotecteddata} object - * representation - */ - function read_packet(input, position, len) { - this.packetLength = len; - // - A one-octet version number. The only currently defined value is - // 1. - this.version = input[position].charCodeAt(); - if (this.version != 1) { - util - .print_error('openpgp.packet.encryptedintegrityprotecteddata.js\nunknown encrypted integrity protected data packet version: ' - + this.version - + " , @ " - + position - + "hex:" - + util.hexstrdump(input)); - return null; - } - // - Encrypted data, the output of the selected symmetric-key cipher - // operating in Cipher Feedback mode with shift amount equal to the - // block size of the cipher (CFB-n where n is the block size). - this.encryptedData = input.substring(position + 1, position + 1 + len); - util.print_debug("openpgp.packet.encryptedintegrityprotecteddata.js\n" - + this.toString()); - return this; - } - - /** - * Creates a string representation of a Sym. Encrypted Integrity Protected - * Data Packet (tag 18) (see RFC4880 5.13) - * - * @param {Integer} symmetric_algorithm - * The selected symmetric encryption algorithm to be used - * @param {String} key The key of cipher blocksize length to be used - * @param {String} data - * Plaintext data to be encrypted within the packet - * @return {String} A string representation of the packet - */ - function write_packet(symmetric_algorithm, key, data) { - - var prefixrandom = openpgp_crypto_getPrefixRandom(symmetric_algorithm); - var prefix = prefixrandom - + prefixrandom.charAt(prefixrandom.length - 2) - + prefixrandom.charAt(prefixrandom.length - 1); - var tohash = data; - tohash += String.fromCharCode(0xD3); - tohash += String.fromCharCode(0x14); - util.print_debug_hexstr_dump("data to be hashed:" - , prefix + tohash); - tohash += str_sha1(prefix + tohash); - util.print_debug_hexstr_dump("hash:" - , tohash.substring(tohash.length - 20, - tohash.length)); - var result = openpgp_crypto_symmetricEncrypt(prefixrandom, - symmetric_algorithm, key, tohash, false).substring(0, - prefix.length + tohash.length); - var header = openpgp_packet.write_packet_header(18, result.length + 1) - + String.fromCharCode(1); - this.encryptedData = result; - return header + result; - } - - /** - * Decrypts the encrypted data contained in this object read_packet must - * have been called before - * - * @param {Integer} symmetric_algorithm_type - * The selected symmetric encryption algorithm to be used - * @param {String} key The key of cipher blocksize length to be used - * @return {String} The decrypted data of this packet - */ - function decrypt(symmetric_algorithm_type, key) { - this.decryptedData = openpgp_crypto_symmetricDecrypt( - symmetric_algorithm_type, key, this.encryptedData, false); - // there must be a modification detection code packet as the - // last packet and everything gets hashed except the hash itself - this.hash = str_sha1(openpgp_crypto_MDCSystemBytes( - symmetric_algorithm_type, key, this.encryptedData) - + this.decryptedData.substring(0, - this.decryptedData.length - 20)); - util.print_debug_hexstr_dump("calc hash = ", this.hash); - if (this.hash == this.decryptedData.substring( - this.decryptedData.length - 20, this.decryptedData.length)) - return this.decryptedData; - else - util - .print_error("Decryption stopped: discovered a modification of encrypted data."); - return null; - } - - function toString() { - var data = ''; - if(openpgp.config.debug) - data = ' data: Bytes [' - + util.hexstrdump(this.encryptedData) + ']'; - - return '5.13. Sym. Encrypted Integrity Protected Data Packet (Tag 18)\n' - + ' length: ' - + this.packetLength - + '\n' - + ' version: ' - + this.version - + '\n' - + data; - } - - this.write_packet = write_packet; - this.read_packet = read_packet; - this.toString = toString; - this.decrypt = decrypt; -}; -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - /** * @class * @classdesc Public-Key Encrypted Session Key Packets (Tag 1) @@ -10857,85 +10721,6 @@ function openpgp_packet_marker() { // 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 Modification Detection Code Packet (Tag 19) - * - * RFC4880 5.14: The Modification Detection Code packet contains a SHA-1 hash of - * plaintext data, which is used to detect message modification. It is only used - * with a Symmetrically Encrypted Integrity Protected Data packet. The - * Modification Detection Code packet MUST be the last packet in the plaintext - * data that is encrypted in the Symmetrically Encrypted Integrity Protected - * Data packet, and MUST appear in no other place. - */ - -function openpgp_packet_modificationdetectioncode() { - this.tagType = 19; - this.hash = null; - /** - * parsing function for a modification detection code packet (tag 19). - * - * @param {String} input payload of a tag 19 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 - */ - function read_packet(input, position, len) { - this.packetLength = len; - - if (len != 20) { - util - .print_error("openpgp.packet.modificationdetectioncode.js\n" - + 'invalid length for a modification detection code packet!' - + len); - return null; - } - // - A 20-octet SHA-1 hash of the preceding plaintext data of the - // Symmetrically Encrypted Integrity Protected Data packet, - // including prefix data, the tag octet, and length octet of the - // Modification Detection Code packet. - this.hash = input.substring(position, position + 20); - return this; - } - - /* - * this packet is created within the encryptedintegrityprotected packet - * function write_packet(data) { } - */ - - /** - * generates debug output (pretty print) - * - * @return {String} String which gives some information about the - * modification detection code - */ - function toString() { - return '5.14 Modification detection code packet\n' + ' bytes (' - + this.hash.length + '): [' + util.hexstrdump(this.hash) + ']'; - } - this.read_packet = read_packet; - this.toString = toString; -}; -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - /** * @class * @classdesc Implementation of the One-Pass Signature Packets (Tag 4) @@ -12582,7 +12367,7 @@ function _openpgp_packet() { userid: 13, public_subkey: 14, user_attribute: 17, - sym_encrypted_and_integrity_protected: 18, + sym_encrypted_integrity_protected: 18, modification_detection_code: 19 }; } @@ -12656,6 +12441,171 @@ function openpgp_packetlist() { // 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 + * Packet (Tag 18) + * + * RFC4880 5.13: The Symmetrically Encrypted Integrity Protected Data packet is + * a variant of the Symmetrically Encrypted Data packet. It is a new feature + * created for OpenPGP that addresses the problem of detecting a modification to + * encrypted data. It is used in combination with a Modification Detection Code + * packet. + */ + +function openpgp_packet_sym_encrypted_integrity_protected() { + this.tag = 18; + this.version = 1; + this.encrypted = null; // string + this.hash = null; // string + this.data = new openpgp_packetlist(); + this.algorithm = openpgp.symmetric.plaintext; + + /** + * Parsing function for the packet. + * + * @param {String} input Payload of a tag 18 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_encryptedintegrityprotecteddata} object + * representation + */ + this.read = function(bytes) { + // - A one-octet version number. The only currently defined value is + // 1. + this.version = bytes[0].charCodeAt(); + if (this.version != 1) { + util.print_error('openpgp.packet.encryptedintegrityprotecteddata.js' + + '\nunknown encrypted integrity protected data packet version: ' + + this.version + + "hex:" + + util.hexstrdump(bytes)); + return null; + } + + // - Encrypted data, the output of the selected symmetric-key cipher + // operating in Cipher Feedback mode with shift amount equal to the + // block size of the cipher (CFB-n where n is the block size). + this.encrypted = bytes.substr(1); + } + + /** + * Creates a string representation of a Sym. Encrypted Integrity Protected + * Data Packet (tag 18) (see RFC4880 5.13) + * + * @param {Integer} symmetric_algorithm + * The selected symmetric encryption algorithm to be used + * @param {String} key The key of cipher blocksize length to be used + * @param {String} data + * Plaintext data to be encrypted within the packet + * @return {String} A string representation of the packet + */ + this.write = function(symmetric_algorithm, key, data) { + return String.fromCharCode(this.version) + this.encrypted; + } + + this.encrypt = function(symmetric_algorithm, key) { + var bytes = this.data.write() + + var prefixrandom = openpgp_crypto_getPrefixRandom(symmetric_algorithm); + var prefix = prefixrandom + + prefixrandom.charAt(prefixrandom.length - 2) + + prefixrandom.charAt(prefixrandom.length - 1) + + var tohash = bytes; + tohash += String.fromCharCode(0xD3); + tohash += String.fromCharCode(0x14); + + util.print_debug_hexstr_dump("data to be hashed:" + , prefix + tohash); + + tohash += str_sha1(prefix + tohash); + + util.print_debug_hexstr_dump("hash:" + , tohash.substring(tohash.length - 20, + tohash.length)); + + this.encrypted = openpgp_crypto_symmetricEncrypt(prefixrandom, + symmetric_algorithm, key, tohash, false).substring(0, + prefix.length + tohash.length); + } + + /** + * Decrypts the encrypted data contained in this object read_packet must + * have been called before + * + * @param {Integer} symmetric_algorithm_type + * The selected symmetric encryption algorithm to be used + * @param {String} key The key of cipher blocksize length to be used + * @return {String} The decrypted data of this packet + */ + this.decrypt = function(symmetric_algorithm_type, key) { + var decrypted = openpgp_crypto_symmetricDecrypt( + symmetric_algorithm_type, key, this.encrypted, false); + + + // there must be a modification detection code packet as the + // last packet and everything gets hashed except the hash itself + this.hash = str_sha1( + openpgp_crypto_MDCSystemBytes(symmetric_algorithm_type, key, this.encrypted) + + decrypted.substring(0, decrypted.length - 20)); + + util.print_debug_hexstr_dump("calc hash = ", this.hash); + + this.data.read(decrypted); + + // We pop the mandatory modification detection code packet. + var mdc = this.data.packets.pop(); + + if(this.hash != mdc.hash) { + this.data = null; + util.print_error("Decryption stopped: discovered a " + + "modification of encrypted data."); + return; + } + } + + this.toString = function() { + var data = ''; + if(openpgp.config.debug) + data = ' data: Bytes [' + + util.hexstrdump(this.encrypted) + ']'; + + return '5.13. Sym. Encrypted Integrity Protected Data Packet (Tag 18)\n' + + '\n' + + ' version: ' + + this.version + + '\n' + + data; + } + +}; + +function openpgp_packet_modification_detection_code() { + this.hash = null; + this.read = function(bytes) { + this.hash = bytes; + } +} +// 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) diff --git a/resources/openpgp.min.js b/resources/openpgp.min.js index 457ea4df..ecdcdd97 100644 --- a/resources/openpgp.min.js +++ b/resources/openpgp.min.js @@ -322,7 +322,8 @@ d=(new openpgp_packet_literaldata).write_packet(b.replace(/\r\n/g,"\n").replace( e)}f=openpgp.config.config.integrity_protect?f+(new openpgp_packet_encryptedintegrityprotecteddata).write_packet(openpgp.config.config.encryption_cipher,e,d):f+(new openpgp_packet_encrypteddata).write_packet(openpgp.config.config.encryption_cipher,e,d);return openpgp_encoding_armor(3,f,null,null)};this.read_message=function(a){var c;try{c=openpgp_encoding_deArmor(a.replace(/\r/g,""))}catch(d){return util.print_error("no message found!"),null}return b(c)};this.read_messages_dearmored=b;this.read_publicKey= function(a){for(var b=0,d=[],e=0,a=openpgp_encoding_deArmor(a.replace(/\r/g,"")).openpgp,f=a.length;b!=a.length;){var g=openpgp_packet.read_packet(a,b,f);if(153==a[b].charCodeAt()||6==g.tagType)d[e]=new openpgp_msg_publickey,d[e].header=a.substring(b,b+3),153==a[b].charCodeAt()?(b++,f=a[b++].charCodeAt()<<8|a[b++].charCodeAt(),d[e].publicKeyPacket=new openpgp_packet_keymaterial,d[e].publicKeyPacket.header=d[e].header,d[e].publicKeyPacket.read_tag6(a,b,f),b+=d[e].publicKeyPacket.packetLength,b+=d[e].read_nodes(d[e].publicKeyPacket, a,b,a.length-b)):(d[e]=new openpgp_msg_publickey,d[e].publicKeyPacket=g,b+=g.headerLength+g.packetLength,b+=d[e].read_nodes(g,a,b,a.length-b));else return util.print_error("no public key found!"),null;d[e].data=a.substring(0,b);e++}return d};this.read_privateKey=function(a){for(var b=[],d=0,e=0,a=openpgp_encoding_deArmor(a.replace(/\r/g,"")).openpgp,f=a.length;e!=a.length;){var g=openpgp_packet.read_packet(a,e,f);if(5==g.tagType)b[b.length]=new openpgp_msg_privatekey,e+=g.headerLength+g.packetLength, -e+=b[d].read_nodes(g,a,e,f);else return util.print_error("no block packet found!"),null;b[d].data=a.substring(0,e);d++}return b};this.init=function(){this.config=new openpgp_config;this.config.read();this.keyring=new openpgp_keyring;this.keyring.init()}}var openpgp=new _openpgp;openpgp.symmetric={plaintext:0,idea:1,tripledes:2,cast5:3,blowfish:4,aes128:7,aes192:8,aes256:9,twofish:10}; +e+=b[d].read_nodes(g,a,e,f);else return util.print_error("no block packet found!"),null;b[d].data=a.substring(0,e);d++}return b};this.init=function(){this.config=new openpgp_config;this.config.read();this.keyring=new openpgp_keyring;this.keyring.init()}}var openpgp=new _openpgp;openpgp.publickey={rsa_encrypt_sign:1,rsa_encrypt:2,rsa_sign:3,elgamal:16,dsa:17};openpgp.symmetric={plaintext:0,idea:1,tripledes:2,cast5:3,blowfish:4,aes128:7,aes192:8,aes256:9,twofish:10}; +openpgp.compression={uncompressed:0,zip:1,zlib:2,bzip2:3};openpgp.hash={md5:1,sha1:2,ripemd:3,sha256:8,sha384:9,sha512:10,sha224:11}; function openpgp_keyring(){this.init=function(){var b=JSON.parse(window.localStorage.getItem("privatekeys")),a=JSON.parse(window.localStorage.getItem("publickeys"));if(null==b||0==b.length)b=[];if(null==a||0==a.length)a=[];this.publicKeys=[];this.privateKeys=[];for(var c=0,d=0;d")[0]: b.trim(),d=d.toLowerCase();if(!util.emailRegEx.test(d))return a;for(b=0;b")[0]:b.trim(),d=d.toLowerCase();if(!util.emailRegEx.test(d))return a;for(b=0;b>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_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, -this.decryptedData.length-20));util.print_debug_hexstr_dump("calc hash = ",this.hash);if(this.hash==this.decryptedData.substring(this.decryptedData.length-20,this.decryptedData.length))return this.decryptedData;util.print_error("Decryption stopped: discovered a modification of encrypted data.");return null}} function openpgp_packet_encryptedsessionkey(){this.read_pub_key_packet=function(b,a,c){this.tagType=1;this.packetLength=c;var d=a;if(10>c)return util.print_error("openpgp.packet.encryptedsessionkey.js\ninvalid length"),null;this.version=b[d++].charCodeAt();this.keyId=new openpgp_type_keyid;this.keyId.read_packet(b,d);d+=8;this.publicKeyAlgorithmUsed=b[d++].charCodeAt();switch(this.publicKeyAlgorithmUsed){case 1:case 2:this.MPIs=[];this.MPIs[0]=new openpgp_type_mpi;this.MPIs[0].read(b,d,d-a);break; case 16:this.MPIs=[];this.MPIs[0]=new openpgp_type_mpi;this.MPIs[0].read(b,d,d-a);d+=this.MPIs[0].packetLength;this.MPIs[1]=new openpgp_type_mpi;this.MPIs[1].read(b,d,d-a);break;default:util.print_error("openpgp.packet.encryptedsessionkey.js\nunknown public key packet algorithm type "+this.publicKeyAlgorithmType)}return this};this.read_symmetric_key_packet=function(b,a,c){this.tagType=3;var d=a;this.version=b[d++];this.symmetricKeyAlgorithmUsed=b[d++];this.s2k=new openpgp_type_s2k;this.s2k.read(b, d);if(s2k.s2kLength+d>8&255),d=d+String.fromCharCode(e&255),f=f+b+String.fromCharCode(c),b=new openpgp_type_mpi,a=openpgp_crypto_asymetricEncrypt(c,a,b.create(openpgp_encoding_eme_pkcs1_encode(d,a[0].mpiByteLength))),c=0;ca[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(223a[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; +trust:12,userid:13,public_subkey:14,user_attribute:17,sym_encrypted_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