diff --git a/resources/openpgp.js b/resources/openpgp.js index efb58345..6bf9af93 100644 --- a/resources/openpgp.js +++ b/resources/openpgp.js @@ -9818,161 +9818,6 @@ function openpgp_packet_one_pass_signature() { // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -/** - * @class - * @classdesc Implementation of the User Attribute Packet (Tag 17) - * The User Attribute packet is a variation of the User ID packet. It - * is capable of storing more types of data than the User ID packet, - * which is limited to text. Like the User ID packet, a User Attribute - * packet may be certified by the key owner ("self-signed") or any other - * key owner who cares to certify it. Except as noted, a User Attribute - * packet may be used anywhere that a User ID packet may be used. - * - * While User Attribute packets are not a required part of the OpenPGP - * standard, implementations SHOULD provide at least enough - * compatibility to properly handle a certification signature on the - * User Attribute packet. A simple way to do this is by treating the - * User Attribute packet as a User ID packet with opaque contents, but - * an implementation may use any method desired. - */ -function openpgp_packet_userattribute() { - this.tagType = 17; - this.certificationSignatures = []; - this.certificationRevocationSignatures = []; - this.revocationSignatures = []; - this.userattributes = []; - - /** - * parsing function for a user attribute packet (tag 17). - * @param {String} input payload of a tag 17 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) { - var count = 0; - var mypos = 0; - var packet_len = 0; - - while (mypos != bytes.length) { - var current_len = 0; - // 4.2.2.1. One-Octet Lengths - if (bytes[mypos].charCodeAt() < 192) { - packet_length = bytes[mypos++].charCodeAt(); - current_len = 1; - // 4.2.2.2. Two-Octet Lengths - } else if (bytes[mypos].charCodeAt() >= 192 && bytes[mypos].charCodeAt() < 224) { - packet_length = ((bytes[mypos++].charCodeAt() - 192) << 8) - + (bytes[mypos++].charCodeAt()) + 192; - current_len = 2; - // 4.2.2.4. Partial Body Lengths - } else if (bytes[mypos].charCodeAt() > 223 && bytes[mypos].charCodeAt() < 255) { - packet_length = 1 << (bytes[mypos++].charCodeAt() & 0x1F); - current_len = 1; - // 4.2.2.3. Five-Octet Lengths - } else { - current_len = 5; - mypos++; - packet_length = (bytes[mypos++].charCodeAt() << 24) | - (bytes[mypos++].charCodeAt() << 16) - | (bytes[mypos++].charCodeAt() << 8) | bytes[mypos++].charCodeAt(); - } - - var subpackettype = bytes[mypos++].charCodeAt(); - packet_length--; - current_len++; - this.userattributes[count] = []; - this.userattributes[count] = bytes.substring(mypos, mypos + packet_len); - mypos += packet_length; - total_len += current_len+packet_len; - } - - return this; - } - - /** - * generates debug output (pretty print) - * @return {String} String which gives some information about the user attribute packet - */ - function toString() { - var result = '5.12. User Attribute Packet (Tag 17)\n'+ - ' AttributePackets: (count = '+this.userattributes.length+')\n'; - for (var i = 0; i < this.userattributes.length; i++) { - result += ' ('+this.userattributes[i].length+') bytes: ['+util.hexidump(this.userattributes[i])+']\n'; - } - return result; - } - - /** - * Continue parsing packets belonging to the user attribute packet such as signatures - * @param {Object} parent_node the parent object - * @param {String} input input string to read the packet(s) from - * @param {Integer} position start position for the parser - * @param {Integer} len length of the packet(s) or remaining length of input - * @return {Integer} length of nodes read - */ - function read_nodes(parent_node, input, position, len) { - - this.parentNode = parent_node; - var exit = false; - var pos = position; - var l = len; - while (input.length != pos) { - var result = openpgp_packet.read_packet(input, pos, l); - if (result == null) { - util.print_error("openpgp.packet.userattribute.js\n"+'[user_attr] parsing ends here @:' + pos + " l:" + l); - break; - } else { - switch (result.tagType) { - case 2: // Signature Packet - if (result.signatureType > 15 - && result.signatureType < 20) // certification - // // - // signature - this.certificationSignatures[this.certificationSignatures.length] = result; - else if (result.signatureType == 32) // certification revocation signature - this.certificationRevocationSignatures[this.certificationRevocationSignatures.length] = result; - pos += result.packetLength + result.headerLength; - l = len - (pos - position); - break; - default: - this.data = input; - this.position = position - parent_node.packetLength; - this.len = pos - position; - return this.len; - break; - } - } - } - this.data = input; - this.position = position - parent_node.packetLength; - this.len = pos - position; - return this.len; - - } - - this.read_packet = read_packet; - this.read_nodes = read_nodes; - this.toString = toString; - -}; -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - /** * @class * @classdesc Parent openpgp packet class. Operations focus on determining @@ -10036,7 +9881,7 @@ function _openpgp_packet() { * @param {Integer} length Length of the payload * @return {String} String of the header */ - function write_packet_header(tag_type, length) { + this.write_packet_header = function(tag_type, length) { /* we're only generating v4 packet headers here */ var result = ""; result += String.fromCharCode(0xC0 | tag_type); @@ -10052,7 +9897,7 @@ function _openpgp_packet() { * @param {Integer} length Length of the payload * @return {String} String of the header */ - function write_old_packet_header(tag_type, length) { + this.write_old_packet_header = function(tag_type, length) { var result = ""; if (length < 256) { result += String.fromCharCode(0x80 | (tag_type << 2)); @@ -10070,8 +9915,7 @@ function _openpgp_packet() { } return result; } - this.write_old_packet_header = write_old_packet_header; - this.write_packet_header = write_packet_header; + /** * Generic static Packet Parser function * @@ -11685,164 +11529,189 @@ function openpgp_packet_signature() { * @param {openpgp_msg_privatekey} key the public key to verify the signature * @return {boolean} True if message is verified, else false. */ - this.verify = function(data, key) { + this.verify = function(key, data) { + + var bytes = + + (function(type, data) { + switch(type) { + case 0: // 0x00: Signature of a binary document. + return data.literal.data; + break; + + case 1: // 0x01: Signature of a canonical text document. + return data.replace(/\r\n/g, '\n').replace(/\n/g, '\r\n'); + + case 2: // 0x02: Standalone signature. + return '' + case 16: + // 0x10: Generic certification of a User ID and Public-Key packet. + case 17: + // 0x11: Persona certification of a User ID and Public-Key packet. + case 18: + // 0x12: Casual certification of a User ID and Public-Key packet. + case 19: + // 0x13: Positive certification of a User ID and Public-Key packet. + case 48: + // 0x30: Certification revocation signature + + if(data.userid != undefined) { + return String.fromCharCode(0xB4) + + openpgp_packet_number_write(data.userid.userid.length, 4) + + data; + } + else if(data.userattribute != undefined) { + return String.fromCharCode(0xB4) + + openpgp_packet_number_write(data.userattribute.userid.length, 4) + + data; + } + else return; + case 24: + // 0x18: Subkey Binding Signature + break; + case 25: + // 0x19: Primary Key Binding Signature + case 31: + // 0x1F: Signature directly on a key + case 32: + // 0x20: Key revocation signature + case 40: + // 0x28: Subkey revocation signature + return; + case 64: + // 0x40: Timestamp signature. + break; + case 80: + // 0x50: Third-Party Confirmation signature. + break; + default: + util.print_error("openpgp.packet.signature.js\n"+ + "signature verification for type"+ + this.signatureType+" not implemented"); + return false; + }})(this.signatureType, data); + // calculating the trailer var trailer = ''; trailer += String.fromCharCode(this.version); trailer += String.fromCharCode(0xFF); trailer += openpgp_packet_number_write(this.signatureData.length, 4); - switch(this.signatureType) { - case 0: // 0x00: Signature of a binary document. - if (this.version == 4) { - this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, - this.hashAlgorithm, this.mpi, key.mpi, - data+this.signatureData+trailer); - } - break; - - case 1: // 0x01: Signature of a canonical text document. - if (this.version == 4) { - this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, - this.hashAlgorithm, this.mpi, key.mpi, - data+this.signatureData+trailer); - return this.verified; - } - break; - - case 2: // 0x02: Standalone signature. - // This signature is a signature of only its own subpacket contents. - // It is calculated identically to a signature over a zero-lengh - // binary document. Note that it doesn't make sense to have a V3 - // standalone signature. - if (this.version == 3) { - this.verified = false; - break; - } - - this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, - this.hashAlgorithm, this.mpi, key.mpi, - this.signatureData+trailer); - break; - case 16: - // 0x10: Generic certification of a User ID and Public-Key packet. - // The issuer of this certification does not make any particular - // assertion as to how well the certifier has checked that the owner - // of the key is in fact the person described by the User ID. - case 17: - // 0x11: Persona certification of a User ID and Public-Key packet. - // The issuer of this certification has not done any verification of - // the claim that the owner of this key is the User ID specified. - case 18: - // 0x12: Casual certification of a User ID and Public-Key packet. - // The issuer of this certification has done some casual - // verification of the claim of identity. - case 19: - // 0x13: Positive certification of a User ID and Public-Key packet. - // The issuer of this certification has done substantial - // verification of the claim of identity. - // - // Most OpenPGP implementations make their "key signatures" as 0x10 - // certifications. Some implementations can issue 0x11-0x13 - // certifications, but few differentiate between the types. - case 48: - // 0x30: Certification revocation signature - // This signature revokes an earlier User ID certification signature - // (signature class 0x10 through 0x13) or direct-key signature - // (0x1F). It should be issued by the same key that issued the - // revoked signature or an authorized revocation key. The signature - // is computed over the same data as the certificate that it - // revokes, and should have a later creation date than that - // certificate. - - this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, - this.hashAlgorithm, this.mpi, key.mpi, - String.fromCharCode(0xB4) + - openpgp_packet_number_write(data.length, 4) + - data + this.signatureData + trailer); - break; - - case 24: - // 0x18: Subkey Binding Signature - // This signature is a statement by the top-level signing key that - // indicates that it owns the subkey. This signature is calculated - // directly on the primary key and subkey, and not on any User ID or - // other packets. A signature that binds a signing subkey MUST have - // an Embedded Signature subpacket in this binding signature that - // contains a 0x19 signature made by the signing subkey on the - // primary key and subkey. - if (this.version == 3) { - this.verified = false; - break; - } - - this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, - this.hashAlgorithm, this.mpi, key.mpi, data+this.signatureData+trailer); - break; - case 25: - // 0x19: Primary Key Binding Signature - // This signature is a statement by a signing subkey, indicating - // that it is owned by the primary key and subkey. This signature - // is calculated the same way as a 0x18 signature: directly on the - // primary key and subkey, and not on any User ID or other packets. - - // When a signature is made over a key, the hash data starts with the - // octet 0x99, followed by a two-octet length of the key, and then body - // of the key packet. (Note that this is an old-style packet header for - // a key packet with two-octet length.) A subkey binding signature - // (type 0x18) or primary key binding signature (type 0x19) then hashes - // the subkey using the same format as the main key (also using 0x99 as - // the first octet). - case 31: - // 0x1F: Signature directly on a key - // This signature is calculated directly on a key. It binds the - // information in the Signature subpackets to the key, and is - // appropriate to be used for subpackets that provide information - // about the key, such as the Revocation Key subpacket. It is also - // appropriate for statements that non-self certifiers want to make - // about the key itself, rather than the binding between a key and a - // name. - case 32: - // 0x20: Key revocation signature - // The signature is calculated directly on the key being revoked. A - // revoked key is not to be used. Only revocation signatures by the - // key being revoked, or by an authorized revocation key, should be - // considered valid revocation signatures. - case 40: - // 0x28: Subkey revocation signature - // The signature is calculated directly on the subkey being revoked. - // A revoked subkey is not to be used. Only revocation signatures - // by the top-level signature key that is bound to this subkey, or - // by an authorized revocation key, should be considered valid - // revocation signatures. - this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, - this.hashAlgorithm, this.mpi, key.mpi, data+this.signatureData+trailer); - break; - - // Key revocation signatures (types 0x20 and 0x28) - // hash only the key being revoked. - case 64: - // 0x40: Timestamp signature. - // This signature is only meaningful for the timestamp contained in - // it. - case 80: - // 0x50: Third-Party Confirmation signature. - // This signature is a signature over some other OpenPGP Signature - // packet(s). It is analogous to a notary seal on the signed data. - // A third-party signature SHOULD include Signature Target - // subpacket(s) to give easy identification. Note that we really do - // mean SHOULD. There are plausible uses for this (such as a blind - // party that only sees the signature, not the key or source - // document) that cannot include a target subpacket. - default: - util.print_error("openpgp.packet.signature.js\n"+ - "signature verification for type"+ this.signatureType+" not implemented"); - break; - } + this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, + this.hashAlgorithm, this.mpi, key.mpi, + bytes + this.signatureData + trailer); return this.verified; } } + + +/* One pass signature packet type + * @enum {Integer} */ +openpgp_packet_signature.type = { + /** 0x00: Signature of a binary document. */ + binary: 0, + /** 0x01: Signature of a canonical text document. + * Canonicalyzing the document by converting line endings. */ + text: 1, + /** 0x02: Standalone signature. + * This signature is a signature of only its own subpacket contents. + * It is calculated identically to a signature over a zero-lengh + * binary document. Note that it doesn't make sense to have a V3 + * standalone signature. */ + standalone: 2, + /** 0x10: Generic certification of a User ID and Public-Key packet. + * The issuer of this certification does not make any particular + * assertion as to how well the certifier has checked that the owner + * of the key is in fact the person described by the User ID. */ + cert_generic: 16, + /** 0x11: Persona certification of a User ID and Public-Key packet. + * The issuer of this certification has not done any verification of + * the claim that the owner of this key is the User ID specified. */ + cert_persona: 17, + /** 0x12: Casual certification of a User ID and Public-Key packet. + * The issuer of this certification has done some casual + * verification of the claim of identity. */ + cert_casual: 18, + /** 0x13: Positive certification of a User ID and Public-Key packet. + * The issuer of this certification has done substantial + * verification of the claim of identity. + * + * Most OpenPGP implementations make their "key signatures" as 0x10 + * certifications. Some implementations can issue 0x11-0x13 + * certifications, but few differentiate between the types. */ + cert_positive: 19, + /** 0x30: Certification revocation signature + * This signature revokes an earlier User ID certification signature + * (signature class 0x10 through 0x13) or direct-key signature + * (0x1F). It should be issued by the same key that issued the + * revoked signature or an authorized revocation key. The signature + * is computed over the same data as the certificate that it + * revokes, and should have a later creation date than that + * certificate. */ + cert_revocation: 48, + /** 0x18: Subkey Binding Signature + * This signature is a statement by the top-level signing key that + * indicates that it owns the subkey. This signature is calculated + * directly on the primary key and subkey, and not on any User ID or + * other packets. A signature that binds a signing subkey MUST have + * an Embedded Signature subpacket in this binding signature that + * contains a 0x19 signature made by the signing subkey on the + * primary key and subkey. */ + subkey_binding: 24, + /** 0x19: Primary Key Binding Signature + * This signature is a statement by a signing subkey, indicating + * that it is owned by the primary key and subkey. This signature + * is calculated the same way as a 0x18 signature: directly on the + * primary key and subkey, and not on any User ID or other packets. + + * When a signature is made over a key, the hash data starts with the + * octet 0x99, followed by a two-octet length of the key, and then body + * of the key packet. (Note that this is an old-style packet header for + * a key packet with two-octet length.) A subkey binding signature + * (type 0x18) or primary key binding signature (type 0x19) then hashes + * the subkey using the same format as the main key (also using 0x99 as + * the first octet). */ + key_binding: 25, + /** 0x1F: Signature directly on a key + * This signature is calculated directly on a key. It binds the + * information in the Signature subpackets to the key, and is + * appropriate to be used for subpackets that provide information + * about the key, such as the Revocation Key subpacket. It is also + * appropriate for statements that non-self certifiers want to make + * about the key itself, rather than the binding between a key and a + * name. */ + key: 31, + /** 0x20: Key revocation signature + * The signature is calculated directly on the key being revoked. A + * revoked key is not to be used. Only revocation signatures by the + * key being revoked, or by an authorized revocation key, should be + * considered valid revocation signatures.a */ + key_revocation: 32, + /** 0x28: Subkey revocation signature + * The signature is calculated directly on the subkey being revoked. + * A revoked subkey is not to be used. Only revocation signatures + * by the top-level signature key that is bound to this subkey, or + * by an authorized revocation key, should be considered valid + * revocation signatures. + * Key revocation signatures (types 0x20 and 0x28) + * hash only the key being revoked. */ + subkey_revocation: 40, + /** 0x40: Timestamp signature. + * This signature is only meaningful for the timestamp contained in + * it. */ + timestamp: 64, + /** 0x50: Third-Party Confirmation signature. + * This signature is a signature over some other OpenPGP Signature + * packet(s). It is analogous to a notary seal on the signed data. + * A third-party signature SHOULD include Signature Target + * subpacket(s) to give easy identification. Note that we really do + * mean SHOULD. There are plausible uses for this (such as a blind + * party that only sees the signature, not the key or source + * document) that cannot include a target subpacket. */ + third_party: 80 +} + // GPG4Browsers - An OpenPGP implementation in javascript // Copyright (C) 2011 Recurity Labs GmbH // @@ -12262,6 +12131,62 @@ function openpgp_packet_time_write(time) { // 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 User Attribute Packet (Tag 17) + * The User Attribute packet is a variation of the User ID packet. It + * is capable of storing more types of data than the User ID packet, + * which is limited to text. Like the User ID packet, a User Attribute + * packet may be certified by the key owner ("self-signed") or any other + * key owner who cares to certify it. Except as noted, a User Attribute + * packet may be used anywhere that a User ID packet may be used. + * + * While User Attribute packets are not a required part of the OpenPGP + * standard, implementations SHOULD provide at least enough + * compatibility to properly handle a certification signature on the + * User Attribute packet. A simple way to do this is by treating the + * User Attribute packet as a User ID packet with opaque contents, but + * an implementation may use any method desired. + */ +function openpgp_packet_user_attribute() { + this.tag = 17; + this.attributes = []; + + /** + * parsing function for a user attribute packet (tag 17). + * @param {String} input payload of a tag 17 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) { + var i = 0; + while(i < bytes.length) { + var len = openpgp_packet.read_simple_length(bytes); + + i += len.offset; + this.attributes.push(bytes.substr(i, len.len)); + i += len.len; + } + } +}; +// 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 User ID Packet (Tag 13) diff --git a/resources/openpgp.min.js b/resources/openpgp.min.js index a0a6fedc..9799818f 100644 --- a/resources/openpgp.min.js +++ b/resources/openpgp.min.js @@ -80,9 +80,9 @@ var jsSHA=function(){var a=function(a,b){this.highOrder=a;this.lowOrder=b},b=fun c|b.lowOrder<<32-c,b.lowOrder>>>c|b.highOrder<<32-c):new a(b.lowOrder>>>c|b.highOrder<<32-c,b.highOrder>>>c|b.lowOrder<<32-c)},k=function(b,c){return 32>=c?new a(b.highOrder>>>c,b.lowOrder>>>c|b.highOrder<<32-c):new a(0,b.highOrder<<32-c)},l=function(a,b,c){return a&b^~a&c},m=function(b,c,d){return new a(b.highOrder&c.highOrder^~b.highOrder&d.highOrder,b.lowOrder&c.lowOrder^~b.lowOrder&d.lowOrder)},r=function(a,b,c){return a&b^a&c^b&c},p=function(b,c,d){return new a(b.highOrder&c.highOrder^b.highOrder& d.highOrder^c.highOrder&d.highOrder,b.lowOrder&c.lowOrder^b.lowOrder&d.lowOrder^c.lowOrder&d.lowOrder)},o=function(a){return g(a,2)^g(a,13)^g(a,22)},y=function(b){var c=j(b,28),d=j(b,34),b=j(b,39);return new a(c.highOrder^d.highOrder^b.highOrder,c.lowOrder^d.lowOrder^b.lowOrder)},x=function(a){return g(a,6)^g(a,11)^g(a,25)},v=function(b){var c=j(b,14),d=j(b,18),b=j(b,41);return new a(c.highOrder^d.highOrder^b.highOrder,c.lowOrder^d.lowOrder^b.lowOrder)},u=function(a){return g(a,7)^g(a,18)^a>>>3}, t=function(b){var c=j(b,1),d=j(b,8),b=k(b,7);return new a(c.highOrder^d.highOrder^b.highOrder,c.lowOrder^d.lowOrder^b.lowOrder)},E=function(a){return g(a,17)^g(a,19)^a>>>10},Q=function(b){var c=j(b,19),d=j(b,61),b=k(b,6);return new a(c.highOrder^d.highOrder^b.highOrder,c.lowOrder^d.lowOrder^b.lowOrder)},D=function(a,b){var c=(a&65535)+(b&65535);return((a>>>16)+(b>>>16)+(c>>>16)&65535)<<16|c&65535},M=function(a,b,c,d){var e=(a&65535)+(b&65535)+(c&65535)+(d&65535);return((a>>>16)+(b>>>16)+(c>>>16)+ -(d>>>16)+(e>>>16)&65535)<<16|e&65535},K=function(a,b,c,d,e){var f=(a&65535)+(b&65535)+(c&65535)+(d&65535)+(e&65535);return((a>>>16)+(b>>>16)+(c>>>16)+(d>>>16)+(e>>>16)+(f>>>16)&65535)<<16|f&65535},w=function(b,c){var d,e,f;d=(b.lowOrder&65535)+(c.lowOrder&65535);e=(b.lowOrder>>>16)+(c.lowOrder>>>16)+(d>>>16);f=(e&65535)<<16|d&65535;d=(b.highOrder&65535)+(c.highOrder&65535)+(e>>>16);e=(b.highOrder>>>16)+(c.highOrder>>>16)+(d>>>16);return new a((e&65535)<<16|d&65535,f)},z=function(b,c,d,e){var f,h, -g;f=(b.lowOrder&65535)+(c.lowOrder&65535)+(d.lowOrder&65535)+(e.lowOrder&65535);h=(b.lowOrder>>>16)+(c.lowOrder>>>16)+(d.lowOrder>>>16)+(e.lowOrder>>>16)+(f>>>16);g=(h&65535)<<16|f&65535;f=(b.highOrder&65535)+(c.highOrder&65535)+(d.highOrder&65535)+(e.highOrder&65535)+(h>>>16);h=(b.highOrder>>>16)+(c.highOrder>>>16)+(d.highOrder>>>16)+(e.highOrder>>>16)+(f>>>16);return new a((h&65535)<<16|f&65535,g)},T=function(b,c,d,e,f){var h,g,j;h=(b.lowOrder&65535)+(c.lowOrder&65535)+(d.lowOrder&65535)+(e.lowOrder& -65535)+(f.lowOrder&65535);g=(b.lowOrder>>>16)+(c.lowOrder>>>16)+(d.lowOrder>>>16)+(e.lowOrder>>>16)+(f.lowOrder>>>16)+(h>>>16);j=(g&65535)<<16|h&65535;h=(b.highOrder&65535)+(c.highOrder&65535)+(d.highOrder&65535)+(e.highOrder&65535)+(f.highOrder&65535)+(g>>>16);g=(b.highOrder>>>16)+(c.highOrder>>>16)+(d.highOrder>>>16)+(e.highOrder>>>16)+(f.highOrder>>>16)+(h>>>16);return new a((g&65535)<<16|h&65535,j)},A=function(a,b){var c=[],d,e,f,g,j,k,l,m,o,s=[1732584193,4023233417,2562383102,271733878,3285377520], +(d>>>16)+(e>>>16)&65535)<<16|e&65535},K=function(a,b,c,d,e){var f=(a&65535)+(b&65535)+(c&65535)+(d&65535)+(e&65535);return((a>>>16)+(b>>>16)+(c>>>16)+(d>>>16)+(e>>>16)+(f>>>16)&65535)<<16|f&65535},w=function(b,c){var d,e,f;d=(b.lowOrder&65535)+(c.lowOrder&65535);e=(b.lowOrder>>>16)+(c.lowOrder>>>16)+(d>>>16);f=(e&65535)<<16|d&65535;d=(b.highOrder&65535)+(c.highOrder&65535)+(e>>>16);e=(b.highOrder>>>16)+(c.highOrder>>>16)+(d>>>16);return new a((e&65535)<<16|d&65535,f)},z=function(b,c,d,e){var f,g, +h;f=(b.lowOrder&65535)+(c.lowOrder&65535)+(d.lowOrder&65535)+(e.lowOrder&65535);g=(b.lowOrder>>>16)+(c.lowOrder>>>16)+(d.lowOrder>>>16)+(e.lowOrder>>>16)+(f>>>16);h=(g&65535)<<16|f&65535;f=(b.highOrder&65535)+(c.highOrder&65535)+(d.highOrder&65535)+(e.highOrder&65535)+(g>>>16);g=(b.highOrder>>>16)+(c.highOrder>>>16)+(d.highOrder>>>16)+(e.highOrder>>>16)+(f>>>16);return new a((g&65535)<<16|f&65535,h)},T=function(b,c,d,e,f){var g,h,j;g=(b.lowOrder&65535)+(c.lowOrder&65535)+(d.lowOrder&65535)+(e.lowOrder& +65535)+(f.lowOrder&65535);h=(b.lowOrder>>>16)+(c.lowOrder>>>16)+(d.lowOrder>>>16)+(e.lowOrder>>>16)+(f.lowOrder>>>16)+(g>>>16);j=(h&65535)<<16|g&65535;g=(b.highOrder&65535)+(c.highOrder&65535)+(d.highOrder&65535)+(e.highOrder&65535)+(f.highOrder&65535)+(h>>>16);h=(b.highOrder>>>16)+(c.highOrder>>>16)+(d.highOrder>>>16)+(e.highOrder>>>16)+(f.highOrder>>>16)+(g>>>16);return new a((h&65535)<<16|g&65535,j)},A=function(a,b){var c=[],d,e,f,g,j,k,l,m,o,s=[1732584193,4023233417,2562383102,271733878,3285377520], p=[1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1518500249,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,1859775393,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708, 2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,2400959708,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782,3395469782];a[b>>5]|=128<<24-b%32;a[(b+65>>9<<4)+15]=b;o=a.length;for(l=0;lm;m+=1)c[m]= 16>m?a[m+l]:h(c[m-3]^c[m-8]^c[m-14]^c[m-16],1),k=20>m?K(h(d,5),e&f^~e&g,j,p[m],c[m]):40>m?K(h(d,5),e^f^g,j,p[m],c[m]):60>m?K(h(d,5),r(e,f,g),j,p[m],c[m]):K(h(d,5),e^f^g,j,p[m],c[m]),j=g,g=f,f=h(e,30),e=d,d=k;s[0]=D(d,s[0]);s[1]=D(e,s[1]);s[2]=D(f,s[2]);s[3]=D(g,s[3]);s[4]=D(j,s[4])}return s},B=function(b,c,d){var e,f,g,h,j,k,A,B,C,s,ca,Y,L,da,ba,O,ea,fa,ga,ha,ia,ja,ka,la,q,ma,Z=[],ra;if("SHA-224"===d||"SHA-256"===d)ca=64,e=(c+65>>9<<4)+15,da=16,ba=1,q=Number,O=D,ea=M,fa=K,ga=u,ha=E,ia=o,ja=x,la=r, @@ -361,13 +361,9 @@ c));this.date=openpgp_packet_time_read(a.substr(2+c,4));this.set_data_bytes(a.su this.real_data+"|\n"}}openpgp_packet_literal.format={binary:"b",text:"t",utf8:"u"};function openpgp_packet_marker(){this.tag=10;this.read=function(a){return 80==a[0].charCodeAt()&&71==a[1].charCodeAt()&&80==a[2].charCodeAt()?!0:!1}} function openpgp_packet_one_pass_signature(){this.tag=4;this.flags=this.signingKeyId=this.publicKeyAlgorithm=this.hashAlgorithm=this.type=this.version=null;this.read=function(a){var b=0;this.version=a.charCodeAt(b++);this.type=a.charCodeAt(b++);this.hashAlgorithm=a.charCodeAt(b++);this.publicKeyAlgorithm=a.charCodeAt(b++);this.signingKeyId=new openpgp_type_keyid;this.signingKeyId.read_packet(a,b);b+=8;this.flags=a.charCodeAt(b++);return this};this.write=function(a,b,c,d,e){b=""+String.fromCharCode(3); b+=String.fromCharCode(a);b+=String.fromCharCode(this.hashAlgorithm);b+=String.fromCharCode(c.privateKeyPacket.publicKey.publicKeyAlgorithm);b+=c.getKeyId();return b=e?b+String.fromCharCode(0):b+String.fromCharCode(1)}} -function openpgp_packet_userattribute(){this.tagType=17;this.certificationSignatures=[];this.certificationRevocationSignatures=[];this.revocationSignatures=[];this.userattributes=[];this.read=function(a){for(var b=0;b!=a.length;){var c=0;192>a[b].charCodeAt()?(packet_length=a[b++].charCodeAt(),c=1):192<=a[b].charCodeAt()&&224>a[b].charCodeAt()?(packet_length=(a[b++].charCodeAt()-192<<8)+a[b++].charCodeAt()+192,c=2):223a[b].charCodeAt()?(packet_length=1<<(a[b++].charCodeAt()& -31),c=1):(c=5,b++,packet_length=a[b++].charCodeAt()<<24|a[b++].charCodeAt()<<16|a[b++].charCodeAt()<<8|a[b++].charCodeAt());a[b++].charCodeAt();packet_length--;c++;this.userattributes[0]=[];this.userattributes[0]=a.substring(b,b+0);b+=packet_length;total_len+=c+0}return this};this.read_packet=read_packet;this.read_nodes=function(a,b,c,d){this.parentNode=a;for(var e=c,f=d;b.length!=e;){var h=openpgp_packet.read_packet(b,e,f);if(null==h){util.print_error("openpgp.packet.userattribute.js\n[user_attr] parsing ends here @:"+ -e+" l:"+f);break}else switch(h.tagType){case 2:15h.signatureType?this.certificationSignatures[this.certificationSignatures.length]=h:32==h.signatureType&&(this.certificationRevocationSignatures[this.certificationRevocationSignatures.length]=h);e+=h.packetLength+h.headerLength;f=d-(e-c);break;default:return this.data=b,this.position=c-a.packetLength,this.len=e-c}}this.data=b;this.position=c-a.packetLength;return this.len=e-c};this.toString=function(){for(var a="5.12. User Attribute Packet (Tag 17)\n AttributePackets: (count = "+ -this.userattributes.length+")\n",b=0;bd?(b=a[0].charCodeAt(),c=1):255>d?(b=(a[0].charCodeAt()-192<<8)+a[1].charCodeAt()+192,c=2):255==d&&(b=openpgp_packet_integer_read(a.substr(1,4)),c=5);return{len:b,offset:c}};this.encode_length=function(a){var b="";192>a?b+=String.fromCharCode(a):191a?(b+=String.fromCharCode((a-192>>8)+192),b+=String.fromCharCode(a-192&255)):(b+=String.fromCharCode(255),b+=String.fromCharCode(a>>24&255),b+=String.fromCharCode(a>> -16&255),b+=String.fromCharCode(a>>8&255),b+=String.fromCharCode(a&255));return b};this.write_old_packet_header=function(a,b){var c="";256>b?(c+=String.fromCharCode(128|a<<2),c+=String.fromCharCode(b)):(65536>b?(c+=String.fromCharCode(a<<2|129),c+=String.fromCharCode(b>>8)):(c+=String.fromCharCode(a<<2|130),c+=String.fromCharCode(b>>24&255),c+=String.fromCharCode(b>>16&255),c+=String.fromCharCode(b>>8&255)),c+=String.fromCharCode(b&255));return c};this.write_packet_header=function(a,b){var c;c=""+ -String.fromCharCode(192|a);return c+=this.encode_length(b)};this.read_packet=function(a,b,c){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 d=-1,e=-1,e=0;0!=(a[b].charCodeAt()&64)&&(e=1);var f;e?d=a[b].charCodeAt()&63:(d=(a[b].charCodeAt()&63)>>2,f=a[b].charCodeAt()&3);b++;var h=null,g=-1;if(e)if(192>a[b].charCodeAt())c=a[b++].charCodeAt(),util.print_debug("1 byte length:"+ +16&255),b+=String.fromCharCode(a>>8&255),b+=String.fromCharCode(a&255));return b};this.write_packet_header=function(a,b){var c;c=""+String.fromCharCode(192|a);return c+=this.encode_length(b)};this.write_old_packet_header=function(a,b){var c="";256>b?(c+=String.fromCharCode(128|a<<2),c+=String.fromCharCode(b)):(65536>b?(c+=String.fromCharCode(a<<2|129),c+=String.fromCharCode(b>>8)):(c+=String.fromCharCode(a<<2|130),c+=String.fromCharCode(b>>24&255),c+=String.fromCharCode(b>>16&255),c+=String.fromCharCode(b>> +8&255)),c+=String.fromCharCode(b&255));return c};this.read_packet=function(a,b,c){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 d=-1,e=-1,e=0;0!=(a[b].charCodeAt()&64)&&(e=1);var f;e?d=a[b].charCodeAt()&63:(d=(a[b].charCodeAt()&63)>>2,f=a[b].charCodeAt()&3);b++;var h=null,g=-1;if(e)if(192>a[b].charCodeAt())c=a[b++].charCodeAt(),util.print_debug("1 byte length:"+ c);else if(192<=a[b].charCodeAt()&&224>a[b].charCodeAt())c=(a[b++].charCodeAt()-192<<8)+a[b++].charCodeAt()+192,util.print_debug("2 byte length:"+c);else if(223a[b].charCodeAt()){c=1<<(a[b++].charCodeAt()&31);util.print_debug("4 byte length:"+c);g=b+c;for(h=a.substring(b,b+c);;)if(192>a[g].charCodeAt()){f=a[g++].charCodeAt();c+=f;h+=a.substring(g,g+f);g+=f;break}else if(192<=a[g].charCodeAt()&&224>a[g].charCodeAt()){f=(a[g++].charCodeAt()-192<<8)+a[g++].charCodeAt()+192;c+= f;h+=a.substring(g,g+f);g+=f;break}else if(223a[g].charCodeAt())f=1<<(a[g++].charCodeAt()&31),c+=f,h+=a.substring(g,g+f),g+=f;else{g++;f=a[g++].charCodeAt()<<24|a[g++].charCodeAt()<<16|a[g++].charCodeAt()<<8|a[g++].charCodeAt();h+=a.substring(g,g+f);c+=f;g+=f;break}}else b++,c=a[b++].charCodeAt()<<24|a[b++].charCodeAt()<<16|a[b++].charCodeAt()<<8|a[b++].charCodeAt();else switch(f){case 0:c=a[b++].charCodeAt();break;case 1:c=a[b++].charCodeAt()<<8|a[b++].charCodeAt();break; case 2:c=a[b++].charCodeAt()<<24|a[b++].charCodeAt()<<16|a[b++].charCodeAt()<<8|a[b++].charCodeAt();break}-1==g&&(g=c);null==h&&(h=a.substring(b,b+g));var a={},j;for(j in this.type)a[this.type[j]]=j;j="openpgp_packet_"+a[d];a=window[j];if(void 0==a)throw j;j=new a;j.read(h);return{packet:j,offset:b+g}};this.type={reserved:0,public_key_encrypted_session_key:1,signature:2,sym_encrypted_session_key:3,one_pass_signature:4,secret_key:5,public_key:6,secret_subkey:7,compressed:8,symmetrically_encrypted:9, @@ -398,10 +394,10 @@ a[b++].charCodeAt();var c=function(a,b){for(var c=openpgp_packet_number_read(a.s 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.verify=function(a,b){var c;c=""+String.fromCharCode(this.version);c+=String.fromCharCode(255); -c+=openpgp_packet_number_write(this.signatureData.length,4);switch(this.signatureType){case 0:if(4==this.version)this.verified=openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.mpi,b.mpi,a+this.signatureData+c);break;case 1:if(4==this.version){this.verified=openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.mpi,b.mpi,a+this.signatureData+c);break}break;case 2:if(3==this.version){this.verified=!1;break}this.verified=openpgp_crypto_verifySignature(this.publicKeyAlgorithm, -this.hashAlgorithm,this.mpi,b.mpi,this.signatureData+c);break;case 16:case 17:case 18:case 19:case 48:this.verified=openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.mpi,b.mpi,String.fromCharCode(180)+openpgp_packet_number_write(a.length,4)+a+this.signatureData+c);break;case 24:if(3==this.version){this.verified=!1;break}this.verified=openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.mpi,b.mpi,a+this.signatureData+c);break;case 25:case 31:case 32:case 40:this.verified= -openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.mpi,b.mpi,a+this.signatureData+c);break;default:util.print_error("openpgp.packet.signature.js\nsignature verification for type"+this.signatureType+" not implemented")}return this.verified}} +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.verify=function(a,b){var c=function(a,b){switch(a){case 0:return b.literal.data;case 1:return b.replace(/\r\n/g, +"\n").replace(/\n/g,"\r\n");case 2:return"";case 16:case 17:case 18:case 19:case 48:if(void 0!=b.userid)return String.fromCharCode(180)+openpgp_packet_number_write(b.userid.userid.length,4)+b;if(void 0!=b.userattribute)return String.fromCharCode(180)+openpgp_packet_number_write(b.userattribute.userid.length,4)+b;break;case 24:break;case 25:case 31:case 32:case 40:break;case 64:break;case 80:break;default:return util.print_error("openpgp.packet.signature.js\nsignature verification for type"+this.signatureType+ +" not implemented"),!1}}(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)}} +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, b,this.encrypted,!1);this.hash=str_sha1(openpgp_crypto_MDCSystemBytes(a,b,this.encrypted)+c.substring(0,c.length-20));util.print_debug_hexstr_dump("calc hash = ",this.hash);this.hash!=c.substr(c.length-20,20)?(this.packets=new openpgp_packetlist,util.print_error("Decryption stopped: discovered a modification of encrypted data.")):this.packets.read(c.substr(0,c.length-22))};this.toString=function(){var a="";openpgp.config.debug&&(a=" data: Bytes ["+util.hexstrdump(this.encrypted)+"]");return"5.13. Sym. Encrypted Integrity Protected Data Packet (Tag 18)\n\n version: "+ @@ -412,7 +408,8 @@ b=String.fromCharCode(this.algorithm)+openpgp_crypto_getRandomBytes(openpgp_cryp this.s2k+"\n"}} function openpgp_packet_symmetrically_encrypted(){this.tag=9;this.encrypted=null;this.packets=new openpgp_packetlist;this.read=function(a){this.encrypted=a};this.write=function(){return this.encrypted};this.decrypt=function(a,b){this.packets.read(openpgp_crypto_symmetricDecrypt(a,b,this.encrypted,!0))};this.encrypt=function(a,b){var c=this.packets.write();this.encrypted=openpgp_crypto_symmetricEncrypt(openpgp_crypto_getPrefixRandom(a),a,b,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_number_read(a){for(var b=0,c=0;c>8*(b-d-1)&255);return c}function openpgp_packet_time_read(a){var a=openpgp_packet_number_read(a),b=new Date;b.setTime(1E3*a);return b} -function openpgp_packet_time_write(a){a=Math.round(a.getTime()/1E3);return openpgp_packet_number_write(a,4)}function openpgp_packet_userid(){this.userid="";this.tag=13;this.read=function(a){this.userid=util.decode_utf8(a)};this.write=function(){return util.encode_utf8(this.userid)}} +function openpgp_packet_time_write(a){a=Math.round(a.getTime()/1E3);return openpgp_packet_number_write(a,4)}function openpgp_packet_user_attribute(){this.tag=17;this.attributes=[];this.read=function(a){for(var b=0;bb;b++)a+=String.fromCharCode(0);this.read_packet=function(a,b){this.bytes=a.substring(b,b+8);return this};this.toString=function(){return util.hexstrdump(this.bytes)}} function openpgp_type_s2k(){this.read=function(a,b){var c=b;this.type=a[c++].charCodeAt();switch(this.type){case 0:this.hashAlgorithm=a[c++].charCodeAt();this.s2kLength=1;break;case 1:this.hashAlgorithm=a[c++].charCodeAt();this.saltValue=a.substring(c,c+8);c+=8;this.s2kLength=9;break;case 3:this.hashAlgorithm=a[c++].charCodeAt();this.saltValue=a.substring(c,c+8);c+=8;this.EXPBIAS=6;var d=a[c++].charCodeAt();this.count=16+(d&15)<<(d>>4)+this.EXPBIAS;this.s2kLength=10;break;case 101:"GNU"==a.substring(c+ diff --git a/src/packet/openpgp.packet.userattribute.js b/src/packet/openpgp.packet.userattribute.js deleted file mode 100644 index bbe539d9..00000000 --- a/src/packet/openpgp.packet.userattribute.js +++ /dev/null @@ -1,155 +0,0 @@ -// 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 User Attribute Packet (Tag 17) - * The User Attribute packet is a variation of the User ID packet. It - * is capable of storing more types of data than the User ID packet, - * which is limited to text. Like the User ID packet, a User Attribute - * packet may be certified by the key owner ("self-signed") or any other - * key owner who cares to certify it. Except as noted, a User Attribute - * packet may be used anywhere that a User ID packet may be used. - * - * While User Attribute packets are not a required part of the OpenPGP - * standard, implementations SHOULD provide at least enough - * compatibility to properly handle a certification signature on the - * User Attribute packet. A simple way to do this is by treating the - * User Attribute packet as a User ID packet with opaque contents, but - * an implementation may use any method desired. - */ -function openpgp_packet_userattribute() { - this.tagType = 17; - this.certificationSignatures = []; - this.certificationRevocationSignatures = []; - this.revocationSignatures = []; - this.userattributes = []; - - /** - * parsing function for a user attribute packet (tag 17). - * @param {String} input payload of a tag 17 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) { - var count = 0; - var mypos = 0; - var packet_len = 0; - - while (mypos != bytes.length) { - var current_len = 0; - // 4.2.2.1. One-Octet Lengths - if (bytes[mypos].charCodeAt() < 192) { - packet_length = bytes[mypos++].charCodeAt(); - current_len = 1; - // 4.2.2.2. Two-Octet Lengths - } else if (bytes[mypos].charCodeAt() >= 192 && bytes[mypos].charCodeAt() < 224) { - packet_length = ((bytes[mypos++].charCodeAt() - 192) << 8) - + (bytes[mypos++].charCodeAt()) + 192; - current_len = 2; - // 4.2.2.4. Partial Body Lengths - } else if (bytes[mypos].charCodeAt() > 223 && bytes[mypos].charCodeAt() < 255) { - packet_length = 1 << (bytes[mypos++].charCodeAt() & 0x1F); - current_len = 1; - // 4.2.2.3. Five-Octet Lengths - } else { - current_len = 5; - mypos++; - packet_length = (bytes[mypos++].charCodeAt() << 24) | - (bytes[mypos++].charCodeAt() << 16) - | (bytes[mypos++].charCodeAt() << 8) | bytes[mypos++].charCodeAt(); - } - - var subpackettype = bytes[mypos++].charCodeAt(); - packet_length--; - current_len++; - this.userattributes[count] = []; - this.userattributes[count] = bytes.substring(mypos, mypos + packet_len); - mypos += packet_length; - total_len += current_len+packet_len; - } - - return this; - } - - /** - * generates debug output (pretty print) - * @return {String} String which gives some information about the user attribute packet - */ - function toString() { - var result = '5.12. User Attribute Packet (Tag 17)\n'+ - ' AttributePackets: (count = '+this.userattributes.length+')\n'; - for (var i = 0; i < this.userattributes.length; i++) { - result += ' ('+this.userattributes[i].length+') bytes: ['+util.hexidump(this.userattributes[i])+']\n'; - } - return result; - } - - /** - * Continue parsing packets belonging to the user attribute packet such as signatures - * @param {Object} parent_node the parent object - * @param {String} input input string to read the packet(s) from - * @param {Integer} position start position for the parser - * @param {Integer} len length of the packet(s) or remaining length of input - * @return {Integer} length of nodes read - */ - function read_nodes(parent_node, input, position, len) { - - this.parentNode = parent_node; - var exit = false; - var pos = position; - var l = len; - while (input.length != pos) { - var result = openpgp_packet.read_packet(input, pos, l); - if (result == null) { - util.print_error("openpgp.packet.userattribute.js\n"+'[user_attr] parsing ends here @:' + pos + " l:" + l); - break; - } else { - switch (result.tagType) { - case 2: // Signature Packet - if (result.signatureType > 15 - && result.signatureType < 20) // certification - // // - // signature - this.certificationSignatures[this.certificationSignatures.length] = result; - else if (result.signatureType == 32) // certification revocation signature - this.certificationRevocationSignatures[this.certificationRevocationSignatures.length] = result; - pos += result.packetLength + result.headerLength; - l = len - (pos - position); - break; - default: - this.data = input; - this.position = position - parent_node.packetLength; - this.len = pos - position; - return this.len; - break; - } - } - } - this.data = input; - this.position = position - parent_node.packetLength; - this.len = pos - position; - return this.len; - - } - - this.read_packet = read_packet; - this.read_nodes = read_nodes; - this.toString = toString; - -}; diff --git a/src/packet/packet.js b/src/packet/packet.js index 443e8790..fa740453 100644 --- a/src/packet/packet.js +++ b/src/packet/packet.js @@ -78,7 +78,7 @@ function _openpgp_packet() { * @param {Integer} length Length of the payload * @return {String} String of the header */ - function write_packet_header(tag_type, length) { + this.write_packet_header = function(tag_type, length) { /* we're only generating v4 packet headers here */ var result = ""; result += String.fromCharCode(0xC0 | tag_type); @@ -94,7 +94,7 @@ function _openpgp_packet() { * @param {Integer} length Length of the payload * @return {String} String of the header */ - function write_old_packet_header(tag_type, length) { + this.write_old_packet_header = function(tag_type, length) { var result = ""; if (length < 256) { result += String.fromCharCode(0x80 | (tag_type << 2)); @@ -112,8 +112,7 @@ function _openpgp_packet() { } return result; } - this.write_old_packet_header = write_old_packet_header; - this.write_packet_header = write_packet_header; + /** * Generic static Packet Parser function * diff --git a/src/packet/signature.js b/src/packet/signature.js index 33b5e845..87d3862e 100644 --- a/src/packet/signature.js +++ b/src/packet/signature.js @@ -384,161 +384,186 @@ function openpgp_packet_signature() { * @param {openpgp_msg_privatekey} key the public key to verify the signature * @return {boolean} True if message is verified, else false. */ - this.verify = function(data, key) { + this.verify = function(key, data) { + + var bytes = + + (function(type, data) { + switch(type) { + case 0: // 0x00: Signature of a binary document. + return data.literal.data; + break; + + case 1: // 0x01: Signature of a canonical text document. + return data.replace(/\r\n/g, '\n').replace(/\n/g, '\r\n'); + + case 2: // 0x02: Standalone signature. + return '' + case 16: + // 0x10: Generic certification of a User ID and Public-Key packet. + case 17: + // 0x11: Persona certification of a User ID and Public-Key packet. + case 18: + // 0x12: Casual certification of a User ID and Public-Key packet. + case 19: + // 0x13: Positive certification of a User ID and Public-Key packet. + case 48: + // 0x30: Certification revocation signature + + if(data.userid != undefined) { + return String.fromCharCode(0xB4) + + openpgp_packet_number_write(data.userid.userid.length, 4) + + data; + } + else if(data.userattribute != undefined) { + return String.fromCharCode(0xB4) + + openpgp_packet_number_write(data.userattribute.userid.length, 4) + + data; + } + else return; + case 24: + // 0x18: Subkey Binding Signature + break; + case 25: + // 0x19: Primary Key Binding Signature + case 31: + // 0x1F: Signature directly on a key + case 32: + // 0x20: Key revocation signature + case 40: + // 0x28: Subkey revocation signature + return; + case 64: + // 0x40: Timestamp signature. + break; + case 80: + // 0x50: Third-Party Confirmation signature. + break; + default: + util.print_error("openpgp.packet.signature.js\n"+ + "signature verification for type"+ + this.signatureType+" not implemented"); + return false; + }})(this.signatureType, data); + // calculating the trailer var trailer = ''; trailer += String.fromCharCode(this.version); trailer += String.fromCharCode(0xFF); trailer += openpgp_packet_number_write(this.signatureData.length, 4); - switch(this.signatureType) { - case 0: // 0x00: Signature of a binary document. - if (this.version == 4) { - this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, - this.hashAlgorithm, this.mpi, key.mpi, - data+this.signatureData+trailer); - } - break; - - case 1: // 0x01: Signature of a canonical text document. - if (this.version == 4) { - this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, - this.hashAlgorithm, this.mpi, key.mpi, - data+this.signatureData+trailer); - return this.verified; - } - break; - - case 2: // 0x02: Standalone signature. - // This signature is a signature of only its own subpacket contents. - // It is calculated identically to a signature over a zero-lengh - // binary document. Note that it doesn't make sense to have a V3 - // standalone signature. - if (this.version == 3) { - this.verified = false; - break; - } - - this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, - this.hashAlgorithm, this.mpi, key.mpi, - this.signatureData+trailer); - break; - case 16: - // 0x10: Generic certification of a User ID and Public-Key packet. - // The issuer of this certification does not make any particular - // assertion as to how well the certifier has checked that the owner - // of the key is in fact the person described by the User ID. - case 17: - // 0x11: Persona certification of a User ID and Public-Key packet. - // The issuer of this certification has not done any verification of - // the claim that the owner of this key is the User ID specified. - case 18: - // 0x12: Casual certification of a User ID and Public-Key packet. - // The issuer of this certification has done some casual - // verification of the claim of identity. - case 19: - // 0x13: Positive certification of a User ID and Public-Key packet. - // The issuer of this certification has done substantial - // verification of the claim of identity. - // - // Most OpenPGP implementations make their "key signatures" as 0x10 - // certifications. Some implementations can issue 0x11-0x13 - // certifications, but few differentiate between the types. - case 48: - // 0x30: Certification revocation signature - // This signature revokes an earlier User ID certification signature - // (signature class 0x10 through 0x13) or direct-key signature - // (0x1F). It should be issued by the same key that issued the - // revoked signature or an authorized revocation key. The signature - // is computed over the same data as the certificate that it - // revokes, and should have a later creation date than that - // certificate. - - this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, - this.hashAlgorithm, this.mpi, key.mpi, - String.fromCharCode(0xB4) + - openpgp_packet_number_write(data.length, 4) + - data + this.signatureData + trailer); - break; - - case 24: - // 0x18: Subkey Binding Signature - // This signature is a statement by the top-level signing key that - // indicates that it owns the subkey. This signature is calculated - // directly on the primary key and subkey, and not on any User ID or - // other packets. A signature that binds a signing subkey MUST have - // an Embedded Signature subpacket in this binding signature that - // contains a 0x19 signature made by the signing subkey on the - // primary key and subkey. - if (this.version == 3) { - this.verified = false; - break; - } - - this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, - this.hashAlgorithm, this.mpi, key.mpi, data+this.signatureData+trailer); - break; - case 25: - // 0x19: Primary Key Binding Signature - // This signature is a statement by a signing subkey, indicating - // that it is owned by the primary key and subkey. This signature - // is calculated the same way as a 0x18 signature: directly on the - // primary key and subkey, and not on any User ID or other packets. - - // When a signature is made over a key, the hash data starts with the - // octet 0x99, followed by a two-octet length of the key, and then body - // of the key packet. (Note that this is an old-style packet header for - // a key packet with two-octet length.) A subkey binding signature - // (type 0x18) or primary key binding signature (type 0x19) then hashes - // the subkey using the same format as the main key (also using 0x99 as - // the first octet). - case 31: - // 0x1F: Signature directly on a key - // This signature is calculated directly on a key. It binds the - // information in the Signature subpackets to the key, and is - // appropriate to be used for subpackets that provide information - // about the key, such as the Revocation Key subpacket. It is also - // appropriate for statements that non-self certifiers want to make - // about the key itself, rather than the binding between a key and a - // name. - case 32: - // 0x20: Key revocation signature - // The signature is calculated directly on the key being revoked. A - // revoked key is not to be used. Only revocation signatures by the - // key being revoked, or by an authorized revocation key, should be - // considered valid revocation signatures. - case 40: - // 0x28: Subkey revocation signature - // The signature is calculated directly on the subkey being revoked. - // A revoked subkey is not to be used. Only revocation signatures - // by the top-level signature key that is bound to this subkey, or - // by an authorized revocation key, should be considered valid - // revocation signatures. - this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, - this.hashAlgorithm, this.mpi, key.mpi, data+this.signatureData+trailer); - break; - - // Key revocation signatures (types 0x20 and 0x28) - // hash only the key being revoked. - case 64: - // 0x40: Timestamp signature. - // This signature is only meaningful for the timestamp contained in - // it. - case 80: - // 0x50: Third-Party Confirmation signature. - // This signature is a signature over some other OpenPGP Signature - // packet(s). It is analogous to a notary seal on the signed data. - // A third-party signature SHOULD include Signature Target - // subpacket(s) to give easy identification. Note that we really do - // mean SHOULD. There are plausible uses for this (such as a blind - // party that only sees the signature, not the key or source - // document) that cannot include a target subpacket. - default: - util.print_error("openpgp.packet.signature.js\n"+ - "signature verification for type"+ this.signatureType+" not implemented"); - break; - } + this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, + this.hashAlgorithm, this.mpi, key.mpi, + bytes + this.signatureData + trailer); return this.verified; } } + + +/** One pass signature packet type + * @enum {Integer} */ +openpgp_packet_signature.type = { + /** 0x00: Signature of a binary document. */ + binary: 0, + /** 0x01: Signature of a canonical text document. + * Canonicalyzing the document by converting line endings. */ + text: 1, + /** 0x02: Standalone signature. + * This signature is a signature of only its own subpacket contents. + * It is calculated identically to a signature over a zero-lengh + * binary document. Note that it doesn't make sense to have a V3 + * standalone signature. */ + standalone: 2, + /** 0x10: Generic certification of a User ID and Public-Key packet. + * The issuer of this certification does not make any particular + * assertion as to how well the certifier has checked that the owner + * of the key is in fact the person described by the User ID. */ + cert_generic: 16, + /** 0x11: Persona certification of a User ID and Public-Key packet. + * The issuer of this certification has not done any verification of + * the claim that the owner of this key is the User ID specified. */ + cert_persona: 17, + /** 0x12: Casual certification of a User ID and Public-Key packet. + * The issuer of this certification has done some casual + * verification of the claim of identity. */ + cert_casual: 18, + /** 0x13: Positive certification of a User ID and Public-Key packet. + * The issuer of this certification has done substantial + * verification of the claim of identity. + * + * Most OpenPGP implementations make their "key signatures" as 0x10 + * certifications. Some implementations can issue 0x11-0x13 + * certifications, but few differentiate between the types. */ + cert_positive: 19, + /** 0x30: Certification revocation signature + * This signature revokes an earlier User ID certification signature + * (signature class 0x10 through 0x13) or direct-key signature + * (0x1F). It should be issued by the same key that issued the + * revoked signature or an authorized revocation key. The signature + * is computed over the same data as the certificate that it + * revokes, and should have a later creation date than that + * certificate. */ + cert_revocation: 48, + /** 0x18: Subkey Binding Signature + * This signature is a statement by the top-level signing key that + * indicates that it owns the subkey. This signature is calculated + * directly on the primary key and subkey, and not on any User ID or + * other packets. A signature that binds a signing subkey MUST have + * an Embedded Signature subpacket in this binding signature that + * contains a 0x19 signature made by the signing subkey on the + * primary key and subkey. */ + subkey_binding: 24, + /** 0x19: Primary Key Binding Signature + * This signature is a statement by a signing subkey, indicating + * that it is owned by the primary key and subkey. This signature + * is calculated the same way as a 0x18 signature: directly on the + * primary key and subkey, and not on any User ID or other packets. + + * When a signature is made over a key, the hash data starts with the + * octet 0x99, followed by a two-octet length of the key, and then body + * of the key packet. (Note that this is an old-style packet header for + * a key packet with two-octet length.) A subkey binding signature + * (type 0x18) or primary key binding signature (type 0x19) then hashes + * the subkey using the same format as the main key (also using 0x99 as + * the first octet). */ + key_binding: 25, + /** 0x1F: Signature directly on a key + * This signature is calculated directly on a key. It binds the + * information in the Signature subpackets to the key, and is + * appropriate to be used for subpackets that provide information + * about the key, such as the Revocation Key subpacket. It is also + * appropriate for statements that non-self certifiers want to make + * about the key itself, rather than the binding between a key and a + * name. */ + key: 31, + /** 0x20: Key revocation signature + * The signature is calculated directly on the key being revoked. A + * revoked key is not to be used. Only revocation signatures by the + * key being revoked, or by an authorized revocation key, should be + * considered valid revocation signatures.a */ + key_revocation: 32, + /** 0x28: Subkey revocation signature + * The signature is calculated directly on the subkey being revoked. + * A revoked subkey is not to be used. Only revocation signatures + * by the top-level signature key that is bound to this subkey, or + * by an authorized revocation key, should be considered valid + * revocation signatures. + * Key revocation signatures (types 0x20 and 0x28) + * hash only the key being revoked. */ + subkey_revocation: 40, + /** 0x40: Timestamp signature. + * This signature is only meaningful for the timestamp contained in + * it. */ + timestamp: 64, + /** 0x50: Third-Party Confirmation signature. + * This signature is a signature over some other OpenPGP Signature + * packet(s). It is analogous to a notary seal on the signed data. + * A third-party signature SHOULD include Signature Target + * subpacket(s) to give easy identification. Note that we really do + * mean SHOULD. There are plausible uses for this (such as a blind + * party that only sees the signature, not the key or source + * document) that cannot include a target subpacket. */ + third_party: 80 +} + diff --git a/src/packet/user_attribute.js b/src/packet/user_attribute.js new file mode 100644 index 00000000..0891eafd --- /dev/null +++ b/src/packet/user_attribute.js @@ -0,0 +1,56 @@ +// 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 User Attribute Packet (Tag 17) + * The User Attribute packet is a variation of the User ID packet. It + * is capable of storing more types of data than the User ID packet, + * which is limited to text. Like the User ID packet, a User Attribute + * packet may be certified by the key owner ("self-signed") or any other + * key owner who cares to certify it. Except as noted, a User Attribute + * packet may be used anywhere that a User ID packet may be used. + * + * While User Attribute packets are not a required part of the OpenPGP + * standard, implementations SHOULD provide at least enough + * compatibility to properly handle a certification signature on the + * User Attribute packet. A simple way to do this is by treating the + * User Attribute packet as a User ID packet with opaque contents, but + * an implementation may use any method desired. + */ +function openpgp_packet_user_attribute() { + this.tag = 17; + this.attributes = []; + + /** + * parsing function for a user attribute packet (tag 17). + * @param {String} input payload of a tag 17 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) { + var i = 0; + while(i < bytes.length) { + var len = openpgp_packet.read_simple_length(bytes); + + i += len.offset; + this.attributes.push(bytes.substr(i, len.len)); + i += len.len; + } + } +}; diff --git a/test/general/packet.js b/test/general/packet.js index 7555b6cb..df1d7917 100644 --- a/test/general/packet.js +++ b/test/general/packet.js @@ -333,7 +333,10 @@ unittests.register("Packet testing", function() { key.read(openpgp_encoding_deArmor(armored_key).openpgp); - var verified = key[2].verify(key[1].userid, key[0].public_key); + var verified = key[2].verify(key[0].public_key, + { + userid: key[1] + }); @@ -372,7 +375,10 @@ unittests.register("Packet testing", function() { - var verified = payload[2].verify(payload[1].data, key[0].public_key); + var verified = payload[2].verify(key[0].public_key, + { + literal: payload[1] + });