From 968dca94362b8cabd7a0121f28cbcd8238724dd0 Mon Sep 17 00:00:00 2001 From: Sean Colyer Date: Sun, 7 Oct 2012 23:44:58 -0400 Subject: [PATCH] Initial work with refactor. Everything should still be functional, but more cleanup can still be done. --- resources/openpgp.js | 216 +++++++++-------------- resources/openpgp.min.js | 113 ++++++------ src/openpgp.js | 34 +++- src/openpgp.msg.message.js | 50 ++---- src/openpgp.msg.publickey.js | 1 - src/packet/openpgp.packet.compressed.js | 18 +- src/packet/openpgp.packet.keymaterial.js | 22 ++- src/packet/openpgp.packet.signature.js | 89 ++++------ 8 files changed, 223 insertions(+), 320 deletions(-) diff --git a/resources/openpgp.js b/resources/openpgp.js index 2e793443..276a98d6 100644 --- a/resources/openpgp.js +++ b/resources/openpgp.js @@ -248,6 +248,7 @@ function openpgp_packet_signature() { this.signatureTargetHashAlgorithm = null; this.signatureTargetHash = null; this.embeddedSignature = null; + this.verified = false; /** @@ -666,55 +667,43 @@ function openpgp_packet_signature() { * @return {boolean} True if message is verified, else false. */ function verify(data, key) { - switch(this.signatureType) { // calculating the trailer + var trailer = ''; + trailer += String.fromCharCode(this.version); + trailer += String.fromCharCode(0xFF); + trailer += String.fromCharCode(this.signatureData.length >> 24); + trailer += String.fromCharCode((this.signatureData.length >> 16) &0xFF); + trailer += String.fromCharCode((this.signatureData.length >> 8) &0xFF); + trailer += String.fromCharCode(this.signatureData.length & 0xFF); + switch(this.signatureType) { case 0: // 0x00: Signature of a binary document. if (this.version == 4) { - var trailer = ''; - trailer += String.fromCharCode(this.version); - trailer += String.fromCharCode(0xFF); - trailer += String.fromCharCode(this.signatureData.length >> 24); - trailer += String.fromCharCode((this.signatureData.length >> 16) &0xFF); - trailer += String.fromCharCode((this.signatureData.length >> 8) &0xFF); - trailer += String.fromCharCode(this.signatureData.length & 0xFF); - return openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, + this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, this.MPIs, key.obj.publicKeyPacket.MPIs, data.substring(i)+this.signatureData+trailer); - } else if (this.version == 3) { - return false; } + break; case 1: // 0x01: Signature of a canonical text document. if (this.version == 4) { - var trailer = ''; - trailer += String.fromCharCode(this.version); - trailer += String.fromCharCode(0xFF); - trailer += String.fromCharCode(this.signatureData.length >> 24); - trailer += String.fromCharCode((this.signatureData.length >> 16) &0xFF); - trailer += String.fromCharCode((this.signatureData.length >> 8) &0xFF); - trailer += String.fromCharCode(this.signatureData.length &0xFF); - return openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, + this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, this.MPIs, key.obj.publicKeyPacket.MPIs, data+this.signatureData+trailer); - } else if (this.version == 3) { - return false; + 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-length // binary document. Note that it doesn't make sense to have a V3 // standalone signature. - if (this.version == 3) - return false; + if (this.version == 3) { + this.verified = false; + break; + } - var trailer = ''; - trailer += String.fromCharCode(this.version); - trailer += String.fromCharCode(0xFF); - trailer += String.fromCharCode(this.signatureData.length >> 24); - trailer += String.fromCharCode((this.signatureData.length >> 16) &0xFF); - trailer += String.fromCharCode((this.signatureData.length >> 8) &0xFF); - trailer += String.fromCharCode(this.signatureData.length &0xFF); - return openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, + this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, this.MPIs, key.obj.publicKeyPacket.MPIs, 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 @@ -746,15 +735,9 @@ function openpgp_packet_signature() { // revokes, and should have a later creation date than that // certificate. - var trailer = ''; - trailer += String.fromCharCode(this.version); - trailer += String.fromCharCode(0xFF); - trailer += String.fromCharCode(this.signatureData.length >> 24); - trailer += String.fromCharCode((this.signatureData.length >> 16) &0xFF); - trailer += String.fromCharCode((this.signatureData.length >> 8) &0xFF); - trailer += String.fromCharCode(this.signatureData.length &0xFF); - return openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, + this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, this.MPIs, key.MPIs, data+this.signatureData+trailer); + break; case 24: // 0x18: Subkey Binding Signature @@ -765,18 +748,14 @@ function openpgp_packet_signature() { // 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) - return false; + if (this.version == 3) { + this.verified = false; + break; + } - var trailer = ''; - trailer += String.fromCharCode(this.version); - trailer += String.fromCharCode(0xFF); - trailer += String.fromCharCode(this.signatureData.length >> 24); - trailer += String.fromCharCode((this.signatureData.length >> 16) &0xFF); - trailer += String.fromCharCode((this.signatureData.length >> 8) &0xFF); - trailer += String.fromCharCode(this.signatureData.length &0xFF); - return openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, + this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, this.MPIs, key.MPIs, data+this.signatureData+trailer); + break; case 25: // 0x19: Primary Key Binding Signature // This signature is a statement by a signing subkey, indicating @@ -813,16 +792,9 @@ function openpgp_packet_signature() { // by the top-level signature key that is bound to this subkey, or // by an authorized revocation key, should be considered valid // revocation signatures. - var trailer = ''; - trailer += String.fromCharCode(this.version); - trailer += String.fromCharCode(0xFF); - trailer += String.fromCharCode(this.signatureData.length >> 24); - trailer += String.fromCharCode((this.signatureData.length >> 16) &0xFF); - trailer += String.fromCharCode((this.signatureData.length >> 8) &0xFF); - trailer += String.fromCharCode(this.signatureData.length &0xFF); - return openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, + this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, this.MPIs, key.MPIs, data+this.signatureData+trailer); - + break; // Key revocation signatures (types 0x20 and 0x28) // hash only the key being revoked. @@ -843,6 +815,7 @@ function openpgp_packet_signature() { util.print_error("openpgp.packet.signature.js\n"+"signature verification for type"+ this.signatureType+" not implemented"); break; } + return this.verified; } /** * generates debug output (pretty print) @@ -2519,6 +2492,7 @@ var openpgp_packet = new _openpgp_packet(); */ function openpgp_packet_compressed() { this.tagType = 8; + this.decompressedData = null; /** * parsing function for the packet. @@ -2553,16 +2527,15 @@ function openpgp_packet_compressed() { 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)); - var outputString = unescape(jxg_obj.deflate()[0][0]); - var packet = openpgp_packet.read_packet(outputString, 0, outputString.length); - util.print_info('Decompressed packet [Type 1-ZIP]: ' + packet); - this.decompressedData = packet.data; + 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. @@ -2570,15 +2543,9 @@ function openpgp_packet_compressed() { // 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,""); - var outputString = JXG.decompress(radix); //TODO check ADLER32 checksum - var dearmored = {type: 3, text: outputString, openpgp: outputString}; - var messages = openpgp.read_messages_dearmored(dearmored); - for(var m in messages){ - if(messages[m].data){ - this.decompressedData = messages[m].data; - } - } + this.decompressedData = JXG.decompress(radix); + break; } else { util.print_error("Compression algorithm ZLIB only supports DEFLATE compression method."); } @@ -3233,7 +3200,7 @@ function openpgp_packet_keymaterial() { pos += result.packetLength + result.headerLength; break; } else if (result.signatureType == 40) { // subkey revocation signature - this.subKeyRevocationSignature = result; + this.subKeyRevocationSignature[this.subKeyRevocationSignature.length] = result; pos += result.packetLength + result.headerLength; break; } else { @@ -3266,7 +3233,7 @@ function openpgp_packet_keymaterial() { if (result.signatureType == 24) // subkey embedded signature this.subKeySignature = result; else if (result.signatureType == 40) // subkey revocation signature - this.subKeyRevocationSignature[this.subKeyRevocationSignature] = result; + this.subKeyRevocationSignature[this.subKeyRevocationSignature.length] = result; pos += result.packetLength + result.headerLength; break; default: @@ -3292,26 +3259,24 @@ function openpgp_packet_keymaterial() { */ function verifyKey() { if (this.tagType == 14) { - if (this.subKeySignature == null) + if (this.subKeySignature == null) { return 0; + } if (this.subKeySignature.version == 4 && this.subKeySignature.keyNeverExpires != null && !this.subKeySignature.keyNeverExpires && - new Date((this.subKeySignature.keyExpirationTime*1000)+ this.creationTime.getTime()) < new Date()) - return 1; + new Date((this.subKeySignature.keyExpirationTime*1000)+ this.creationTime.getTime()) < new Date()) { + return 1; + } var hashdata = String.fromCharCode(0x99)+this.parentNode.header.substring(1)+this.parentNode.data+ String.fromCharCode(0x99)+this.header.substring(1)+this.packetdata; if (!this.subKeySignature.verify(hashdata,this.parentNode)) { return 0; } for (var i = 0; i < this.subKeyRevocationSignature.length; i++) { - if (this.subKeyRevocationSignature[i]) - var hashdata = String.fromCharCode(0x99)+this.parentNode.header.substring(1)+this.parentNode.data+ - String.fromCharCode(0x99)+this.header.substring(1)+this.packetdata; - if (this.subKeyRevocationSignature[i].verify(hashdata, this.parentNode)) - return 2; - else - return 0; + if (this.getKeyId() == this.subKeyRevocationSignature[i].keyId){ + return 2; + } } } return 3; @@ -9692,8 +9657,18 @@ function _openpgp () { return read_messages_dearmored(dearmored); } + /** + * reads message packets out of an OpenPGP armored text and + * returns an array of message objects. Can be called externally or internally. + * External call will parse a de-armored messaged and return messages found. + * Internal will be called to read packets wrapped in other packets (i.e. compressed) + * @param {String} input dearmored text of OpenPGP packets, to be parsed + * @return {Array[openpgp_msg_message]} on error the function + * returns null + */ function read_messages_dearmored(input){ var messageString = input.openpgp; + var signatureText = input.text; //text to verify signatures against. Modified by Tag11. var messages = new Array(); var messageCount = 0; var mypos = 0; @@ -9777,11 +9752,13 @@ function _openpgp () { break; } } else - // Signed Message if (first_packet.tagType == 2 && first_packet.signatureType < 3) { - messages[messageCount].text = input.text; + // Signed Message + mypos += first_packet.packetLength + first_packet.headerLength; + l -= (first_packet.packetLength + first_packet.headerLength); + messages[messageCount].text = signatureText; messages[messageCount].signature = first_packet; - break; + messageCount++; } else // Signed Message if (first_packet.tagType == 4) { @@ -9789,12 +9766,12 @@ function _openpgp () { mypos += first_packet.packetLength + first_packet.headerLength; l -= (first_packet.packetLength + first_packet.headerLength); } else - // Compressed Message - // TODO: needs to be implemented. From a security perspective: this message is plaintext anyway. - // This has been implemented as part of processing. Check openpgp.packet. if (first_packet.tagType == 8) { - util.print_error("A directly compressed message is currently not supported"); - break; + // Compressed Message + mypos += first_packet.packetLength + first_packet.headerLength; + l -= (first_packet.packetLength + first_packet.headerLength); + var decompressedText = first_packet.decompress(); + messages = messages.concat(openpgp.read_messages_dearmored({text: decompressedText, openpgp: decompressedText})); } else // Marker Packet (Obsolete Literal Packet) (Tag 10) // "Such a packet MUST be ignored when received." see http://tools.ietf.org/html/rfc4880#section-5.8 @@ -9809,8 +9786,14 @@ function _openpgp () { // Literal Message -- work is already done in read_packet mypos += first_packet.packetLength + first_packet.headerLength; l -= (first_packet.packetLength + first_packet.headerLength); + signatureText = first_packet.data; messages[messageCount].data = first_packet.data; messageCount++; + } else + if (first_packet.tagType == 19) { + // Modification Detect Code + mypos += first_packet.packetLength + first_packet.headerLength; + l -= (first_packet.packetLength + first_packet.headerLength); } } else { util.print_error('no message found!'); @@ -10148,7 +10131,6 @@ function openpgp_msg_publickey() { var tohash = this.publicKeyPacket.header+this.publicKeyPacket.data; if (this.revocationSignatures[i].verify(tohash, this.publicKeyPacket)) return false; - else return false; } if (this.subKeys.length != 0) { @@ -10287,7 +10269,7 @@ function openpgp_config() { keyserver: "keyserver.linux.it" // "pgp.mit.edu:11371" }; - this.versionstring ="OpenPGP.js v.1.20121006"; + this.versionstring ="OpenPGP.js v.1.20121007"; this.commentstring ="http://openpgpjs.org"; /** * reads the config out of the HTML5 local storage @@ -12226,6 +12208,8 @@ function openpgp_msg_message() { // -3 = decryption error // text = valid decryption this.text = ""; + this.messagePacket = null; + this.type = null; /** * Decrypts a message and generates user interface message out of the found. @@ -12257,45 +12241,15 @@ function openpgp_msg_message() { var len = decrypted.length; var validSignatures = new Array(); util.print_debug_hexstr_dump("openpgp.msg.messge decrypt:\n",decrypted); - - while (position != decrypted.length && (packet = openpgp_packet.read_packet(decrypted, position, len)) != null) { - if (packet.tagType == 8) { - this.text = packet.decompress(); - decrypted = packet.decompress(); + + var messages = openpgp.read_messages_dearmored({text: decrypted, openpgp: decrypted}); + for(var m in messages){ + if(messages[m].data){ + this.text = messages[m].data; } - util.print_debug(packet.toString()); - position += packet.headerLength+packet.packetLength; - if (position > 38) - util.print_debug_hexstr_dump("openpgp.msg.messge decrypt:\n",decrypted.substring(position)); - len = decrypted.length - position; - if (packet.tagType == 11) { - this.text = packet.data; - util.print_info("message successfully decrypted"); + if(messages[m].signature){ + validSignatures.push(messages[m].verifySignature(pubkey)); } - if (packet.tagType == 19) - // ignore.. we checked that already in a more strict way. - continue; - if (packet.tagType == 2 && packet.signatureType < 3) { - if(!pubkey || pubkey.length == 0 ){ - var pubkey = openpgp.keyring.getPublicKeysForKeyId(packet.issuerKeyId); - } - if (pubkey.length == 0) { - util.print_warning("Unable to verify signature of issuer: "+util.hexstrdump(packet.issuerKeyId)+". Public key not found in keyring."); - validSignatures[validSignatures.length] = false; - } else { - if(packet.verify(this.text.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"),pubkey[0]) && pubkey[0].obj.validate()){ - util.print_info("Found Good Signature from "+pubkey[0].obj.userIds[0].text+" (0x"+util.hexstrdump(pubkey[0].obj.getKeyId()).substring(8)+")"); - validSignatures[validSignatures.length] = true; - } - else{ - util.print_error("Signature verification failed: Bad Signature from "+pubkey[0].obj.userIds[0].text+" (0x"+util.hexstrdump(pubkey[0].obj.getKeyId()).substring(8)+")"); - validSignatures[validSignatures.length] = false; - } - } - } - } - if (this.text == "") { - this.text = decrypted; } return {text:this.text, validSignatures:validSignatures}; } @@ -12307,7 +12261,7 @@ function openpgp_msg_message() { */ function verifySignature(pubkey) { var result = false; - if (this.type == 2) { + if (this.signature.tagType == 2) { if(!pubkey || pubkey.length == 0){ var pubkey; if (this.signature.version == 4) { @@ -12324,7 +12278,7 @@ function openpgp_msg_message() { else { for (var i = 0 ; i < pubkey.length; i++) { var tohash = this.text.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"); - if (this.signature.verify(tohash.substring(0, tohash.length -2), pubkey[i])) { + if (this.signature.verify(tohash, pubkey[i])) { util.print_info("Found Good Signature from "+pubkey[i].obj.userIds[i].text+" (0x"+util.hexstrdump(pubkey[i].obj.getKeyId()).substring(8)+")"); result = true; } else { diff --git a/resources/openpgp.min.js b/resources/openpgp.min.js index e777e032..b809e3ba 100644 --- a/resources/openpgp.min.js +++ b/resources/openpgp.min.js @@ -3,33 +3,30 @@ this.packetLength+"\n type: "+this.type+"\n keyID: "+this.signingKeyId. d+String.fromCharCode(1)}}function openpgp_packet_marker(){this.tagType=10;this.read_packet=function(b,a){this.packetLength=3;return 80==b[a].charCodeAt()&&71==b[a+1].charCodeAt()&&80==b[a+2].charCodeAt()?this:null};this.toString=function(){return'5.8. Marker Packet (Obsolete Literal Packet) (Tag 10)\n packet reads: "PGP"\n'}} function openpgp_packet_signature(){function b(a,b){var d;d=""+openpgp_packet.encode_length(b.length+1);d+=String.fromCharCode(a);return d+b}this.tagType=2;this.embeddedSignature=this.signatureTargetHash=this.signatureTargetHashAlgorithm=this.signatureTargetPublicKeyAlgorithm=this.reasonForRevocationString=this.reasonForRevocationFlag=this.signersUserId=this.keyFlags=this.policyURI=this.isPrimaryUserID=this.preferredKeyServer=this.keyServerPreferences=this.preferredCompressionAlgorithms=this.preferredHashAlgorithms= this.notationValue=this.notationName=this.notationFlags=this.issuerKeyId=this.revocationKeyFingerprint=this.revocationKeyAlgorithm=this.revocationKeyClass=this.preferredSymmetricAlgorithms=this.keyNeverExpires=this.keyExpirationTime=this.revocable=this.regular_expression=this.trustAmount=this.trustLevel=this.exportable=this.hashAlgorithm=this.publicKeyAlgorithm=this.MPIs=this.signedHashValue=this.signatureNeverExpires=this.signatureExpirationTime=this.signatureData=this.keyId=this.creationTime=this.signatureType= -null;this._raw_read_signature_sub_packet=function(a,b,d){0>d&&util.print_debug("openpgp.packet.signature.js\n_raw_read_signature_sub_packet length < 0 @:"+b);var e=b,f=0;192>a[e].charCodeAt()?f=a[e++].charCodeAt():192<=a[e].charCodeAt()&&224>a[e].charCodeAt()?f=(a[e++].charCodeAt()-192<<8)+a[e++].charCodeAt()+192:223a[e].charCodeAt()?f=1<<(a[e++].charCodeAt()&31):255>a[e].charCodeAt()&&(e++,f=a[e++].charCodeAt()<<24|a[e++].charCodeAt()<<16|a[e++].charCodeAt()<<8|a[e++].charCodeAt()); -var g=a[e++].charCodeAt()&127;switch(g){case 2:this.creationTime=new Date(1E3*(a[e++].charCodeAt()<<24|a[e++].charCodeAt()<<16|a[e++].charCodeAt()<<8|a[e++].charCodeAt()));break;case 3:this.signatureExpirationTime=a[e++].charCodeAt()<<24|a[e++].charCodeAt()<<16|a[e++].charCodeAt()<<8|a[e++].charCodeAt();this.signatureNeverExpires=0==this.signature_expiration_time;break;case 4:this.exportable=1==a[e++].charCodeAt();break;case 5:this.trustLevel=a[e++].charCodeAt();this.trustAmount=a[e++].charCodeAt(); -break;case 6:this.regular_expression=new String;for(g=0;gg;g++)this.revocationKeyFingerprint=a[e++].charCodeAt();break;case 16:this.issuerKeyId=a.substring(e,e+8);e+=8;break;case 20:this.notationFlags=a[e++].charCodeAt()<<24|a[e++].charCodeAt()<<16|a[e++].charCodeAt()<<8|a[e++].charCodeAt();d=a[e++].charCodeAt()<<8|a[e++].charCodeAt();f=a[e++].charCodeAt()<<8|a[e++].charCodeAt();this.notationName="";for(g=0;gd&&util.print_debug("openpgp.packet.signature.js\n_raw_read_signature_sub_packet length < 0 @:"+b);var e=b,f=0;192>a[e].charCodeAt()?f=a[e++].charCodeAt():192<=a[e].charCodeAt()&&224>a[e].charCodeAt()?f=(a[e++].charCodeAt()-192<<8)+a[e++].charCodeAt()+192:223a[e].charCodeAt()?f=1<<(a[e++].charCodeAt()&31):255>a[e].charCodeAt()&&(e++,f=a[e++].charCodeAt()<<24|a[e++].charCodeAt()<<16|a[e++].charCodeAt()<< +8|a[e++].charCodeAt());var g=a[e++].charCodeAt()&127;switch(g){case 2:this.creationTime=new Date(1E3*(a[e++].charCodeAt()<<24|a[e++].charCodeAt()<<16|a[e++].charCodeAt()<<8|a[e++].charCodeAt()));break;case 3:this.signatureExpirationTime=a[e++].charCodeAt()<<24|a[e++].charCodeAt()<<16|a[e++].charCodeAt()<<8|a[e++].charCodeAt();this.signatureNeverExpires=0==this.signature_expiration_time;break;case 4:this.exportable=1==a[e++].charCodeAt();break;case 5:this.trustLevel=a[e++].charCodeAt();this.trustAmount= +a[e++].charCodeAt();break;case 6:this.regular_expression=new String;for(g=0;gg;g++)this.revocationKeyFingerprint=a[e++].charCodeAt();break;case 16:this.issuerKeyId=a.substring(e,e+8);e+=8;break;case 20:this.notationFlags=a[e++].charCodeAt()<<24|a[e++].charCodeAt()<<16|a[e++].charCodeAt()<<8|a[e++].charCodeAt();d=a[e++].charCodeAt()<<8|a[e++].charCodeAt();f=a[e++].charCodeAt()<<8|a[e++].charCodeAt();this.notationName="";for(g=0;g>24&255)+String.fromCharCode(a>>16&255)+String.fromCharCode(a>>8&255)+String.fromCharCode(a&255)),h=b(16,d.getKeyId()),g=g+String.fromCharCode(a.length+h.length>>8&255),g=g+String.fromCharCode(a.length+h.length&255),g=g+a+h,a=""+String.fromCharCode(4),a=a+String.fromCharCode(255),a=a+String.fromCharCode(g.length>>24),a=a+String.fromCharCode(g.length>>16&255),a=a+String.fromCharCode(g.length>>8&255),a=a+String.fromCharCode(g.length&255),h=String.fromCharCode(0), -h=h+String.fromCharCode(0),k=openpgp_crypto_hashData(f,c+g+a);util.print_debug("DSA Signature is calculated with:|"+c+g+a+"|\n"+util.hexstrdump(c+g+a)+"\n hash:"+util.hexstrdump(k));h+=k.charAt(0);h+=k.charAt(1);h+=openpgp_crypto_signData(f,d.privateKeyPacket.publicKey.publicKeyAlgorithm,e.MPIs,d.privateKeyPacket.secMPIs,c+g+a);return{openpgp:openpgp_packet.write_packet_header(2,(g+h).length)+g+h,hash:util.get_hashAlgorithmString(f)}};this.verify=function(a,b){switch(this.signatureType){case 0:if(4== -this.version){var d;d=""+String.fromCharCode(this.version);d+=String.fromCharCode(255);d+=String.fromCharCode(this.signatureData.length>>24);d+=String.fromCharCode(this.signatureData.length>>16&255);d+=String.fromCharCode(this.signatureData.length>>8&255);d+=String.fromCharCode(this.signatureData.length&255);return openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.MPIs,b.obj.publicKeyPacket.MPIs,a.substring(i)+this.signatureData+d)}if(3==this.version)return!1;case 1:if(4== -this.version)return d=""+String.fromCharCode(this.version),d+=String.fromCharCode(255),d+=String.fromCharCode(this.signatureData.length>>24),d+=String.fromCharCode(this.signatureData.length>>16&255),d+=String.fromCharCode(this.signatureData.length>>8&255),d+=String.fromCharCode(this.signatureData.length&255),openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.MPIs,b.obj.publicKeyPacket.MPIs,a+this.signatureData+d);if(3==this.version)return!1;case 2:if(3==this.version)return!1; -d=""+String.fromCharCode(this.version);d+=String.fromCharCode(255);d+=String.fromCharCode(this.signatureData.length>>24);d+=String.fromCharCode(this.signatureData.length>>16&255);d+=String.fromCharCode(this.signatureData.length>>8&255);d+=String.fromCharCode(this.signatureData.length&255);return openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.MPIs,b.obj.publicKeyPacket.MPIs,this.signatureData+d);case 16:case 17:case 18:case 19:case 48:return d=""+String.fromCharCode(this.version), -d+=String.fromCharCode(255),d+=String.fromCharCode(this.signatureData.length>>24),d+=String.fromCharCode(this.signatureData.length>>16&255),d+=String.fromCharCode(this.signatureData.length>>8&255),d+=String.fromCharCode(this.signatureData.length&255),openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.MPIs,b.MPIs,a+this.signatureData+d);case 24:if(3==this.version)return!1;d=""+String.fromCharCode(this.version);d+=String.fromCharCode(255);d+=String.fromCharCode(this.signatureData.length>> -24);d+=String.fromCharCode(this.signatureData.length>>16&255);d+=String.fromCharCode(this.signatureData.length>>8&255);d+=String.fromCharCode(this.signatureData.length&255);return openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.MPIs,b.MPIs,a+this.signatureData+d);case 25:case 31:case 32:case 40:return d=""+String.fromCharCode(this.version),d+=String.fromCharCode(255),d+=String.fromCharCode(this.signatureData.length>>24),d+=String.fromCharCode(this.signatureData.length>> -16&255),d+=String.fromCharCode(this.signatureData.length>>8&255),d+=String.fromCharCode(this.signatureData.length&255),openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.MPIs,b.MPIs,a+this.signatureData+d);default:util.print_error("openpgp.packet.signature.js\nsignature verification for type"+this.signatureType+" not implemented")}};this.read_packet=function(a,b,d){this.data=a.substring(b,b+d);if(0>d)return util.print_debug("openpgp.packet.signature.js\nopenpgp_packet_signature read_packet length < 0 @:"+ -b),null;var e=b;this.packetLength=d;this.version=a[e++].charCodeAt();switch(this.version){case 3:5!=a[e++].charCodeAt()&&util.print_debug("openpgp.packet.signature.js\ninvalid One-octet length of following hashed material. MUST be 5. @:"+(e-1));this.signatureType=a[e++].charCodeAt();this.creationTime=new Date(1E3*(a[e++].charCodeAt()<<24|a[e++].charCodeAt()<<16|a[e++].charCodeAt()<<8|a[e++].charCodeAt()));this.signatureData=a.substring(b,e);this.keyId=a.substring(e,e+8);e+=8;this.publicKeyAlgorithm= -a[e++].charCodeAt();this.hashAlgorithm=a[e++].charCodeAt();this.signedHashValue=a[e++].charCodeAt()<<8|a[e++].charCodeAt();d=0;0this.publicKeyAlgorithm?d=1:17==this.publicKeyAlgorithm&&(d=2);this.MPIs=[];for(var f=0;fthis.publicKeyAlgorithm?d=1:17==this.publicKeyAlgorithm&&(d=2);this.MPIs=[];for(f=0;f>24);d+=String.fromCharCode(this.signatureData.length>>16&255);d+=String.fromCharCode(this.signatureData.length>>8&255);d+=String.fromCharCode(this.signatureData.length&255);switch(this.signatureType){case 0:if(4==this.version)this.verified=openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.MPIs,b.obj.publicKeyPacket.MPIs,a.substring(i)+this.signatureData+d);break;case 1:if(4==this.version){this.verified= +openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.MPIs,b.obj.publicKeyPacket.MPIs,a+this.signatureData+d);break}break;case 2:if(3==this.version){this.verified=!1;break}this.verified=openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.MPIs,b.obj.publicKeyPacket.MPIs,this.signatureData+d);break;case 16:case 17:case 18:case 19:case 48:this.verified=openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.MPIs,b.MPIs,a+this.signatureData+ +d);break;case 24:if(3==this.version){this.verified=!1;break}this.verified=openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.MPIs,b.MPIs,a+this.signatureData+d);break;case 25:case 31:case 32:case 40:this.verified=openpgp_crypto_verifySignature(this.publicKeyAlgorithm,this.hashAlgorithm,this.MPIs,b.MPIs,a+this.signatureData+d);break;default:util.print_error("openpgp.packet.signature.js\nsignature verification for type"+this.signatureType+" not implemented")}return this.verified}; +this.read_packet=function(a,b,d){this.data=a.substring(b,b+d);if(0>d)return util.print_debug("openpgp.packet.signature.js\nopenpgp_packet_signature read_packet length < 0 @:"+b),null;var e=b;this.packetLength=d;this.version=a[e++].charCodeAt();switch(this.version){case 3:5!=a[e++].charCodeAt()&&util.print_debug("openpgp.packet.signature.js\ninvalid One-octet length of following hashed material. MUST be 5. @:"+(e-1));this.signatureType=a[e++].charCodeAt();this.creationTime=new Date(1E3*(a[e++].charCodeAt()<< +24|a[e++].charCodeAt()<<16|a[e++].charCodeAt()<<8|a[e++].charCodeAt()));this.signatureData=a.substring(b,e);this.keyId=a.substring(e,e+8);e+=8;this.publicKeyAlgorithm=a[e++].charCodeAt();this.hashAlgorithm=a[e++].charCodeAt();this.signedHashValue=a[e++].charCodeAt()<<8|a[e++].charCodeAt();d=0;0this.publicKeyAlgorithm?d=1:17==this.publicKeyAlgorithm&&(d=2);this.MPIs=[];for(var f=0;fthis.publicKeyAlgorithm?d=1:17==this.publicKeyAlgorithm&&(d=2);this.MPIs=[];for(f=0;fthis.publicKey.publicKeyAlgorithm)a=0,this.secMPIs=[],this.secMPIs[0]=new openpgp_type_mpi, this.secMPIs[0].read(c,0,b),a+=this.secMPIs[0].packetLength,this.secMPIs[1]=new openpgp_type_mpi,this.secMPIs[1].read(c,a,b-a),a+=this.secMPIs[1].packetLength,this.secMPIs[2]=new openpgp_type_mpi,this.secMPIs[2].read(c,a,b-a),a+=this.secMPIs[2].packetLength,this.secMPIs[3]=new openpgp_type_mpi,this.secMPIs[3].read(c,a,b-a),a+=this.secMPIs[3].packetLength;else if(16==this.publicKey.publicKeyAlgorithm)this.secMPIs=[],this.secMPIs[0]=new openpgp_type_mpi,this.secMPIs[0].read(c,0,c);else if(17==this.publicKey.publicKeyAlgorithm)this.secMPIs= -[],this.secMPIs[0]=new openpgp_type_mpi,this.secMPIs[0].read(c,0,b);return!0};this.read_nodes=function(b,a,c,d){this.parentNode=b;if(14==this.tagType){for(var b=c,e=null;a.length!=b;)if(d=a.length-b,e=openpgp_packet.read_packet(a,b,d),null==e){util.print_error("openpgp.packet.keymaterial.js\n[user_keymat_pub]parsing ends here @:"+b+" l:"+d);break}else switch(e.tagType){case 2:if(24==e.signatureType){this.subKeySignature=e;b+=e.packetLength+e.headerLength;break}else if(40==e.signatureType){this.subKeyRevocationSignature= +[],this.secMPIs[0]=new openpgp_type_mpi,this.secMPIs[0].read(c,0,b);return!0};this.read_nodes=function(b,a,c,d){this.parentNode=b;if(14==this.tagType){for(var b=c,e=null;a.length!=b;)if(d=a.length-b,e=openpgp_packet.read_packet(a,b,d),null==e){util.print_error("openpgp.packet.keymaterial.js\n[user_keymat_pub]parsing ends here @:"+b+" l:"+d);break}else switch(e.tagType){case 2:if(24==e.signatureType){this.subKeySignature=e;b+=e.packetLength+e.headerLength;break}else if(40==e.signatureType){this.subKeyRevocationSignature[this.subKeyRevocationSignature.length]= e;b+=e.packetLength+e.headerLength;break}else util.print_error("openpgp.packet.keymaterial.js\nunknown signature:"+e.toString());default:return this.data=a,this.position=c-this.parentNode.packetLength,this.len=b-c}this.data=a;this.position=c-this.parentNode.packetLength;return this.len=b-c}if(7==this.tagType){for(b=c;a.length!=b;)if(e=openpgp_packet.read_packet(a,b,d-(b-c)),null==e){util.print_error("openpgp.packet.keymaterial.js\n[user_keymat_priv] parsing ends here @:"+b);break}else switch(e.tagType){case 2:24== -e.signatureType?this.subKeySignature=e:40==e.signatureType&&(this.subKeyRevocationSignature[this.subKeyRevocationSignature]=e);b+=e.packetLength+e.headerLength;break;default:return this.data=a,this.position=c-this.parentNode.packetLength,this.len=b-c}this.data=a;this.position=c-this.parentNode.packetLength;return this.len=b-c}util.print_error("openpgp.packet.keymaterial.js\nunknown parent node for a key material packet "+b.tagType)};this.verifyKey=function(){if(14==this.tagType){if(null==this.subKeySignature)return 0; -if(4==this.subKeySignature.version&&null!=this.subKeySignature.keyNeverExpires&&!this.subKeySignature.keyNeverExpires&&new Date(1E3*this.subKeySignature.keyExpirationTime+this.creationTime.getTime())this.publicKeyAlgorithm){var b=this.MPIs[0].substring(this.MPIs[0].mpiByteLength-8);util.print_debug("openpgp.msg.publickey read_nodes:\nV3 key ID: "+ -b);return b}};this.getFingerprint=function(){if(4==this.version)return tohash=String.fromCharCode(153)+String.fromCharCode(this.packetdata.length>>8&255)+String.fromCharCode(this.packetdata.length&255)+this.packetdata,util.print_debug("openpgp.msg.publickey creating subkey fingerprint by hashing:"+util.hexstrdump(tohash)+"\npublickeyalgorithm: "+this.publicKeyAlgorithm),str_sha1(tohash,tohash.length);if(3==this.version&&0this.publicKeyAlgorithm)return MD5(this.MPIs[0].MPI)}; -this.write_private_key=function(b,a,c,d,e,f){this.symmetricEncryptionAlgorithm=e;e=String.fromCharCode(4);e+=f;switch(b){case 1:e+=String.fromCharCode(b);e+=a.n.toMPI();e+=a.ee.toMPI();if(c)switch(e+=String.fromCharCode(254),e+=String.fromCharCode(this.symmetricEncryptionAlgorithm),e+=String.fromCharCode(3),e+=String.fromCharCode(d),b=a.d.toMPI()+a.p.toMPI()+a.q.toMPI()+a.u.toMPI(),a=str_sha1(b),util.print_debug_hexstr_dump("write_private_key sha1: ",a),f=openpgp_crypto_getRandomBytes(8),util.print_debug_hexstr_dump("write_private_key Salt: ", -f),e=e+f+String.fromCharCode(96),util.print_debug("write_private_key c: 96"),c=(new openpgp_type_s2k).write(3,d,c,f,96),this.symmetricEncryptionAlgorithm){case 3:this.IVLength=8;this.IV=openpgp_crypto_getRandomBytes(this.IVLength);ciphertextMPIs=normal_cfb_encrypt(function(a,b){var c=new openpgp_symenc_cast5;c.setKey(b);return c.encrypt(util.str2bin(a))},this.IVLength,util.str2bin(c.substring(0,16)),b+a,this.IV);e+=this.IV+ciphertextMPIs;break;case 7:case 8:case 9:this.IVLength=16,this.IV=openpgp_crypto_getRandomBytes(this.IVLength), -ciphertextMPIs=normal_cfb_encrypt(AESencrypt,this.IVLength,c,b+a,this.IV),e+=this.IV+ciphertextMPIs}else e+=String.fromCharCode(0),e+=a.d.toMPI()+a.p.toMPI()+a.q.toMPI()+a.u.toMPI(),c=util.calc_checksum(a.d.toMPI()+a.p.toMPI()+a.q.toMPI()+a.u.toMPI()),e+=String.fromCharCode(c/256)+String.fromCharCode(c%256),util.print_debug_hexstr_dump("write_private_key basic checksum: "+c);break;default:e="",util.print_error("openpgp.packet.keymaterial.js\nerror writing private key, unknown type :"+b)}c=openpgp_packet.write_packet_header(5, -e.length);return{string:c+e,header:c,body:e}};this.write_public_key=function(b,a,c){var d=String.fromCharCode(4),d=d+c;switch(b){case 1:d+=String.fromCharCode(1);d+=a.n.toMPI();d+=a.ee.toMPI();break;default:util.print_error("openpgp.packet.keymaterial.js\nerror writing private key, unknown type :"+b)}b=openpgp_packet.write_packet_header(6,d.length);return{string:b+d,header:b,body:d}}}function MD5(b){b=md5(b);return util.hex2bin(b)} +e.signatureType?this.subKeySignature=e:40==e.signatureType&&(this.subKeyRevocationSignature[this.subKeyRevocationSignature.length]=e);b+=e.packetLength+e.headerLength;break;default:return this.data=a,this.position=c-this.parentNode.packetLength,this.len=b-c}this.data=a;this.position=c-this.parentNode.packetLength;return this.len=b-c}util.print_error("openpgp.packet.keymaterial.js\nunknown parent node for a key material packet "+b.tagType)};this.verifyKey=function(){if(14==this.tagType){if(null==this.subKeySignature)return 0; +if(4==this.subKeySignature.version&&null!=this.subKeySignature.keyNeverExpires&&!this.subKeySignature.keyNeverExpires&&new Date(1E3*this.subKeySignature.keyExpirationTime+this.creationTime.getTime())this.publicKeyAlgorithm){var b=this.MPIs[0].substring(this.MPIs[0].mpiByteLength-8);util.print_debug("openpgp.msg.publickey read_nodes:\nV3 key ID: "+b);return b}};this.getFingerprint=function(){if(4==this.version)return tohash=String.fromCharCode(153)+String.fromCharCode(this.packetdata.length>>8&255)+String.fromCharCode(this.packetdata.length&255)+this.packetdata, +util.print_debug("openpgp.msg.publickey creating subkey fingerprint by hashing:"+util.hexstrdump(tohash)+"\npublickeyalgorithm: "+this.publicKeyAlgorithm),str_sha1(tohash,tohash.length);if(3==this.version&&0this.publicKeyAlgorithm)return MD5(this.MPIs[0].MPI)};this.write_private_key=function(b,a,c,d,e,f){this.symmetricEncryptionAlgorithm=e;e=String.fromCharCode(4);e+=f;switch(b){case 1:e+=String.fromCharCode(b);e+=a.n.toMPI();e+=a.ee.toMPI();if(c)switch(e+=String.fromCharCode(254), +e+=String.fromCharCode(this.symmetricEncryptionAlgorithm),e+=String.fromCharCode(3),e+=String.fromCharCode(d),b=a.d.toMPI()+a.p.toMPI()+a.q.toMPI()+a.u.toMPI(),a=str_sha1(b),util.print_debug_hexstr_dump("write_private_key sha1: ",a),f=openpgp_crypto_getRandomBytes(8),util.print_debug_hexstr_dump("write_private_key Salt: ",f),e=e+f+String.fromCharCode(96),util.print_debug("write_private_key c: 96"),c=(new openpgp_type_s2k).write(3,d,c,f,96),this.symmetricEncryptionAlgorithm){case 3:this.IVLength=8; +this.IV=openpgp_crypto_getRandomBytes(this.IVLength);ciphertextMPIs=normal_cfb_encrypt(function(a,b){var c=new openpgp_symenc_cast5;c.setKey(b);return c.encrypt(util.str2bin(a))},this.IVLength,util.str2bin(c.substring(0,16)),b+a,this.IV);e+=this.IV+ciphertextMPIs;break;case 7:case 8:case 9:this.IVLength=16,this.IV=openpgp_crypto_getRandomBytes(this.IVLength),ciphertextMPIs=normal_cfb_encrypt(AESencrypt,this.IVLength,c,b+a,this.IV),e+=this.IV+ciphertextMPIs}else e+=String.fromCharCode(0),e+=a.d.toMPI()+ +a.p.toMPI()+a.q.toMPI()+a.u.toMPI(),c=util.calc_checksum(a.d.toMPI()+a.p.toMPI()+a.q.toMPI()+a.u.toMPI()),e+=String.fromCharCode(c/256)+String.fromCharCode(c%256),util.print_debug_hexstr_dump("write_private_key basic checksum: "+c);break;default:e="",util.print_error("openpgp.packet.keymaterial.js\nerror writing private key, unknown type :"+b)}c=openpgp_packet.write_packet_header(5,e.length);return{string:c+e,header:c,body:e}};this.write_public_key=function(b,a,c){var d=String.fromCharCode(4),d=d+ +c;switch(b){case 1:d+=String.fromCharCode(1);d+=a.n.toMPI();d+=a.ee.toMPI();break;default:util.print_error("openpgp.packet.keymaterial.js\nerror writing private key, unknown type :"+b)}b=openpgp_packet.write_packet_header(6,d.length);return{string:b+d,header:b,body:d}}}function MD5(b){b=md5(b);return util.hex2bin(b)} function md5cycle(b,a){var c=b[0],d=b[1],e=b[2],f=b[3],c=ff(c,d,e,f,a[0],7,-680876936),f=ff(f,c,d,e,a[1],12,-389564586),e=ff(e,f,c,d,a[2],17,606105819),d=ff(d,e,f,c,a[3],22,-1044525330),c=ff(c,d,e,f,a[4],7,-176418897),f=ff(f,c,d,e,a[5],12,1200080426),e=ff(e,f,c,d,a[6],17,-1473231341),d=ff(d,e,f,c,a[7],22,-45705983),c=ff(c,d,e,f,a[8],7,1770035416),f=ff(f,c,d,e,a[9],12,-1958414417),e=ff(e,f,c,d,a[10],17,-42063),d=ff(d,e,f,c,a[11],22,-1990404162),c=ff(c,d,e,f,a[12],7,1804603682),f=ff(f,c,d,e,a[13],12, -40341101),e=ff(e,f,c,d,a[14],17,-1502002290),d=ff(d,e,f,c,a[15],22,1236535329),c=gg(c,d,e,f,a[1],5,-165796510),f=gg(f,c,d,e,a[6],9,-1069501632),e=gg(e,f,c,d,a[11],14,643717713),d=gg(d,e,f,c,a[0],20,-373897302),c=gg(c,d,e,f,a[5],5,-701558691),f=gg(f,c,d,e,a[10],9,38016083),e=gg(e,f,c,d,a[15],14,-660478335),d=gg(d,e,f,c,a[4],20,-405537848),c=gg(c,d,e,f,a[9],5,568446438),f=gg(f,c,d,e,a[14],9,-1019803690),e=gg(e,f,c,d,a[3],14,-187363961),d=gg(d,e,f,c,a[8],20,1163531501),c=gg(c,d,e,f,a[13],5,-1444681467), f=gg(f,c,d,e,a[2],9,-51403784),e=gg(e,f,c,d,a[7],14,1735328473),d=gg(d,e,f,c,a[12],20,-1926607734),c=hh(c,d,e,f,a[5],4,-378558),f=hh(f,c,d,e,a[8],11,-2022574463),e=hh(e,f,c,d,a[11],16,1839030562),d=hh(d,e,f,c,a[14],23,-35309556),c=hh(c,d,e,f,a[1],4,-1530992060),f=hh(f,c,d,e,a[4],11,1272893353),e=hh(e,f,c,d,a[7],16,-155497632),d=hh(d,e,f,c,a[10],23,-1094730640),c=hh(c,d,e,f,a[13],4,681279174),f=hh(f,c,d,e,a[0],11,-358537222),e=hh(e,f,c,d,a[3],16,-722521979),d=hh(d,e,f,c,a[6],23,76029189),c=hh(c,d, @@ -369,30 +366,30 @@ function openpgp_crypto_getRandomBigInteger(b){if(0>b)return null;var a=openpgp_ function openpgp_crypto_testRSA(b){debugger;var a=new RSA,c=new openpgp_type_mpi;c.create(openpgp_encoding_eme_pkcs1_encode("ABABABAB",128));c=a.encrypt(c.toBigInteger(),b.ee,b.n);a.decrypt(c,b.d,b.p,b.q,b.u)} function openpgp_crypto_generateKeyPair(b,a,c,d,e){var f,g,h=new Date,h=h.getTime()/1E3,h=String.fromCharCode(Math.floor(h/16777216%256))+String.fromCharCode(Math.floor(h/65536%256))+String.fromCharCode(Math.floor(h/256%256))+String.fromCharCode(Math.floor(h%256));switch(b){case 1:a=(new RSA).generate(a,"10001");f=(new openpgp_packet_keymaterial).write_private_key(b,a,c,d,e,h);g=(new openpgp_packet_keymaterial).write_public_key(b,a,h);break;default:util.print_error("Unknown keytype "+b)}return{privateKey:f, publicKey:g}} -function _openpgp(){function b(a){for(var b=a.openpgp,d=[],e=0,f=0,g=b.length;fh.signatureType||3==h.tagType||4==h.tagType||8==h.tagType||9==h.tagType||10==h.tagType||11==h.tagType||18==h.tagType||19==h.tagType)if(d[d.length]=new openpgp_msg_message,d[e].messagePacket=h,d[e].type=a.type,9==h.tagType||1==h.tagType||3==h.tagType||18==h.tagType)if(9==h.tagType){util.print_error("unexpected openpgp packet");break}else if(1== -h.tagType){util.print_debug("session key found:\n "+h.toString());var k=!0;d[e].sessionKeys=[];for(var j=0;k;)d[e].sessionKeys[j]=h,f+=h.packetLength+h.headerLength,g-=h.packetLength+h.headerLength,h=openpgp_packet.read_packet(b,f,g),1!=h.tagType&&3!=h.tagType&&(k=!1),j++;18==h.tagType||9==h.tagType?(util.print_debug("encrypted data found:\n "+h.toString()),d[e].encryptedData=h,f+=h.packetLength+h.headerLength,g-=h.packetLength+h.headerLength,e++):util.print_debug("something is wrong: "+h.tagType)}else{if(18== -h.tagType){util.print_debug("symmetric encrypted data");break}}else if(2==h.tagType&&3>h.signatureType){d[e].text=a.text;d[e].signature=h;break}else if(4==h.tagType)f+=h.packetLength+h.headerLength,g-=h.packetLength+h.headerLength;else if(8==h.tagType){util.print_error("A directly compressed message is currently not supported");break}else if(10==h.tagType)d.length=0,f+=h.packetLength+h.headerLength,g-=h.packetLength+h.headerLength;else{if(11==h.tagType)f+=h.packetLength+h.headerLength,g-=h.packetLength+ -h.headerLength,d[e].data=h.data,e++}else return util.print_error("no message found!"),null}return d}this.tostring="";this.generate_key_pair=function(a,b,d,e){var f=(new openpgp_packet_userid).write_packet(d),b=openpgp_crypto_generateKeyPair(a,b,e,openpgp.config.config.prefer_hash_algorithm,3),a=b.privateKey,g=(new openpgp_packet_keymaterial).read_priv_key(a.string,3,a.string.length);g.decryptSecretMPIs(e)||util.print_error("Issue creating key. Unable to read resulting private key");e=new openpgp_msg_privatekey; -e.privateKeyPacket=g;e.getPreferredSignatureHashAlgorithm=function(){return openpgp.config.config.prefer_hash_algorithm};g=e.privateKeyPacket.publicKey.data;g=String.fromCharCode(153)+String.fromCharCode(g.length>>8&255)+String.fromCharCode(g.length&255)+g+String.fromCharCode(180)+String.fromCharCode(d.length>>24)+String.fromCharCode(d.length>>16&255)+String.fromCharCode(d.length>>8&255)+String.fromCharCode(d.length&255)+d;d=new openpgp_packet_signature;d=d.write_message_signature(16,g,e);b=openpgp_encoding_armor(4, -b.publicKey.string+f+d.openpgp);f=openpgp_encoding_armor(5,a.string+f+d.openpgp);return{privateKey:e,privateKeyArmored:f,publicKeyArmored:b}};this.write_signed_message=function(a,b){var d=(new openpgp_packet_signature).write_message_signature(1,b.replace(/\r\n/g,"\n").replace(/\n/,"\r\n"),a),d={text:b.replace(/\r\n/g,"\n").replace(/\n/,"\r\n"),openpgp:d.openpgp,hash:d.hash};return openpgp_encoding_armor(2,d,null,null)};this.write_signed_and_encrypted_message=function(a,b,d){var e="",f=(new openpgp_packet_literaldata).write_packet(d.replace(/\r\n/g, -"\n").replace(/\n/g,"\r\n"));util.print_debug_hexstr_dump("literal_packet: |"+f+"|\n",f);for(var g=0;gk.signatureType||3==k.tagType||4==k.tagType||8==k.tagType||9==k.tagType||10==k.tagType||11==k.tagType||18==k.tagType||19==k.tagType)if(e[e.length]=new openpgp_msg_message,e[f].messagePacket=k,e[f].type=a.type,9==k.tagType||1==k.tagType||3==k.tagType||18==k.tagType)if(9==k.tagType){util.print_error("unexpected openpgp packet");break}else if(1== +k.tagType){util.print_debug("session key found:\n "+k.toString());var j=!0;e[f].sessionKeys=[];for(var l=0;j;)e[f].sessionKeys[l]=k,g+=k.packetLength+k.headerLength,h-=k.packetLength+k.headerLength,k=openpgp_packet.read_packet(b,g,h),1!=k.tagType&&3!=k.tagType&&(j=!1),l++;18==k.tagType||9==k.tagType?(util.print_debug("encrypted data found:\n "+k.toString()),e[f].encryptedData=k,g+=k.packetLength+k.headerLength,h-=k.packetLength+k.headerLength,f++):util.print_debug("something is wrong: "+k.tagType)}else{if(18== +k.tagType){util.print_debug("symmetric encrypted data");break}}else 2==k.tagType&&3>k.signatureType?(g+=k.packetLength+k.headerLength,h-=k.packetLength+k.headerLength,e[f].text=d,e[f].signature=k,f++):4==k.tagType?(g+=k.packetLength+k.headerLength,h-=k.packetLength+k.headerLength):8==k.tagType?(g+=k.packetLength+k.headerLength,h-=k.packetLength+k.headerLength,k=k.decompress(),e=e.concat(openpgp.read_messages_dearmored({text:k,openpgp:k}))):10==k.tagType?(e.length=0,g+=k.packetLength+k.headerLength, +h-=k.packetLength+k.headerLength):11==k.tagType?(g+=k.packetLength+k.headerLength,h-=k.packetLength+k.headerLength,d=k.data,e[f].data=k.data,f++):19==k.tagType&&(g+=k.packetLength+k.headerLength,h-=k.packetLength+k.headerLength);else return util.print_error("no message found!"),null}return e}this.tostring="";this.generate_key_pair=function(a,b,d,e){var f=(new openpgp_packet_userid).write_packet(d),b=openpgp_crypto_generateKeyPair(a,b,e,openpgp.config.config.prefer_hash_algorithm,3),a=b.privateKey, +g=(new openpgp_packet_keymaterial).read_priv_key(a.string,3,a.string.length);g.decryptSecretMPIs(e)||util.print_error("Issue creating key. Unable to read resulting private key");e=new openpgp_msg_privatekey;e.privateKeyPacket=g;e.getPreferredSignatureHashAlgorithm=function(){return openpgp.config.config.prefer_hash_algorithm};g=e.privateKeyPacket.publicKey.data;g=String.fromCharCode(153)+String.fromCharCode(g.length>>8&255)+String.fromCharCode(g.length&255)+g+String.fromCharCode(180)+String.fromCharCode(d.length>> +24)+String.fromCharCode(d.length>>16&255)+String.fromCharCode(d.length>>8&255)+String.fromCharCode(d.length&255)+d;d=new openpgp_packet_signature;d=d.write_message_signature(16,g,e);b=openpgp_encoding_armor(4,b.publicKey.string+f+d.openpgp);f=openpgp_encoding_armor(5,a.string+f+d.openpgp);return{privateKey:e,privateKeyArmored:f,publicKeyArmored:b}};this.write_signed_message=function(a,b){var d=(new openpgp_packet_signature).write_message_signature(1,b.replace(/\r\n/g,"\n").replace(/\n/,"\r\n"),a), +d={text:b.replace(/\r\n/g,"\n").replace(/\n/,"\r\n"),openpgp:d.openpgp,hash:d.hash};return openpgp_encoding_armor(2,d,null,null)};this.write_signed_and_encrypted_message=function(a,b,d){var e="",f=(new openpgp_packet_literaldata).write_packet(d.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"));util.print_debug_hexstr_dump("literal_packet: |"+f+"|\n",f);for(var g=0;gd?(a.push(String.fromCharCode(d)),c++):191d?(e=b.charCodeAt(c+1),a.push(String.fromCharCode((d&31)<<6|e&63)),c+=2):(e=b.charCodeAt(c+1),f=b.charCodeAt(c+2),a.push(String.fromCharCode((d&15)<<12|(e&63)<<6|f&63)),c+=3);return a.join("")}; JXG.Util.genUUID=function(){for(var b="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),a=Array(36),c=0,d,e=0;36>e;e++)8==e||13==e||18==e||23==e?a[e]="-":14==e?a[e]="4":(2>=c&&(c=33554432+16777216*Math.random()|0),d=c&15,c>>=4,a[e]=b[19==e?d&3|8:d]);return a.join("")}; -function openpgp_msg_message(){this.text="";this.decrypt=function(b,a){return this.decryptAndVerifySignature(b,a).text};this.decryptAndVerifySignature=function(b,a,c){if(null==b||null==a||""==a)return null;b=a.decrypt(this,b.keymaterial);if(null==b)return null;var d,a=0,e=b.length,f=[];for(util.print_debug_hexstr_dump("openpgp.msg.messge decrypt:\n",b);a!=b.length&&null!=(d=openpgp_packet.read_packet(b,a,e));){if(8==d.tagType)this.text=d.decompress(),b=d.decompress();util.print_debug(d.toString()); -a+=d.headerLength+d.packetLength;38d.signatureType){if(!c||0==c.length)c=openpgp.keyring.getPublicKeysForKeyId(d.issuerKeyId);0==c.length?(util.print_warning("Unable to verify signature of issuer: "+util.hexstrdump(d.issuerKeyId)+". Public key not found in keyring."),f[f.length]=!1):d.verify(this.text.replace(/\r\n/g, -"\n").replace(/\n/g,"\r\n"),c[0])&&c[0].obj.validate()?(util.print_info("Found Good Signature from "+c[0].obj.userIds[0].text+" (0x"+util.hexstrdump(c[0].obj.getKeyId()).substring(8)+")"),f[f.length]=!0):(util.print_error("Signature verification failed: Bad Signature from "+c[0].obj.userIds[0].text+" (0x"+util.hexstrdump(c[0].obj.getKeyId()).substring(8)+")"),f[f.length]=!1)}}if(""==this.text)this.text=b;return{text:this.text,validSignatures:f}};this.verifySignature=function(b){var a=!1;if(2==this.type){if(!b|| -0==b.length)if(4==this.signature.version)b=openpgp.keyring.getPublicKeysForKeyId(this.signature.issuerKeyId);else if(3==this.signature.version)b=openpgp.keyring.getPublicKeysForKeyId(this.signature.keyId);else return util.print_error("unknown signature type on message!"),!1;if(0==b.length)util.print_warning("Unable to verify signature of issuer: "+util.hexstrdump(this.signature.issuerKeyId)+". Public key not found in keyring.");else for(var c=0;ce;e++)if(0==d>>e){c=e;break a}this.mpiBitLength=a+c;this.mpiByteLength=b.length;return this};this.toBin=function(){var b=String.fromCharCode(this.mpiBitLength>>8&255),b=b+String.fromCharCode(this.mpiBitLength&255);return b+=this.MPI};this.getByteLength=function(){return this.mpiByteLength}} function openpgp_type_keyid(){this.read_packet=function(b,a){this.bytes=b.substring(a,a+8);return this};this.toString=function(){return util.hexstrdump(this.bytes)}} diff --git a/src/openpgp.js b/src/openpgp.js index 52f62538..b5a56286 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -140,8 +140,18 @@ function _openpgp () { return read_messages_dearmored(dearmored); } + /** + * reads message packets out of an OpenPGP armored text and + * returns an array of message objects. Can be called externally or internally. + * External call will parse a de-armored messaged and return messages found. + * Internal will be called to read packets wrapped in other packets (i.e. compressed) + * @param {String} input dearmored text of OpenPGP packets, to be parsed + * @return {Array[openpgp_msg_message]} on error the function + * returns null + */ function read_messages_dearmored(input){ var messageString = input.openpgp; + var signatureText = input.text; //text to verify signatures against. Modified by Tag11. var messages = new Array(); var messageCount = 0; var mypos = 0; @@ -225,11 +235,13 @@ function _openpgp () { break; } } else - // Signed Message if (first_packet.tagType == 2 && first_packet.signatureType < 3) { - messages[messageCount].text = input.text; + // Signed Message + mypos += first_packet.packetLength + first_packet.headerLength; + l -= (first_packet.packetLength + first_packet.headerLength); + messages[messageCount].text = signatureText; messages[messageCount].signature = first_packet; - break; + messageCount++; } else // Signed Message if (first_packet.tagType == 4) { @@ -237,12 +249,12 @@ function _openpgp () { mypos += first_packet.packetLength + first_packet.headerLength; l -= (first_packet.packetLength + first_packet.headerLength); } else - // Compressed Message - // TODO: needs to be implemented. From a security perspective: this message is plaintext anyway. - // This has been implemented as part of processing. Check openpgp.packet. if (first_packet.tagType == 8) { - util.print_error("A directly compressed message is currently not supported"); - break; + // Compressed Message + mypos += first_packet.packetLength + first_packet.headerLength; + l -= (first_packet.packetLength + first_packet.headerLength); + var decompressedText = first_packet.decompress(); + messages = messages.concat(openpgp.read_messages_dearmored({text: decompressedText, openpgp: decompressedText})); } else // Marker Packet (Obsolete Literal Packet) (Tag 10) // "Such a packet MUST be ignored when received." see http://tools.ietf.org/html/rfc4880#section-5.8 @@ -257,8 +269,14 @@ function _openpgp () { // Literal Message -- work is already done in read_packet mypos += first_packet.packetLength + first_packet.headerLength; l -= (first_packet.packetLength + first_packet.headerLength); + signatureText = first_packet.data; messages[messageCount].data = first_packet.data; messageCount++; + } else + if (first_packet.tagType == 19) { + // Modification Detect Code + mypos += first_packet.packetLength + first_packet.headerLength; + l -= (first_packet.packetLength + first_packet.headerLength); } } else { util.print_error('no message found!'); diff --git a/src/openpgp.msg.message.js b/src/openpgp.msg.message.js index dbe76fe0..bea69499 100644 --- a/src/openpgp.msg.message.js +++ b/src/openpgp.msg.message.js @@ -28,6 +28,8 @@ function openpgp_msg_message() { // -3 = decryption error // text = valid decryption this.text = ""; + this.messagePacket = null; + this.type = null; /** * Decrypts a message and generates user interface message out of the found. @@ -59,45 +61,15 @@ function openpgp_msg_message() { var len = decrypted.length; var validSignatures = new Array(); util.print_debug_hexstr_dump("openpgp.msg.messge decrypt:\n",decrypted); - - while (position != decrypted.length && (packet = openpgp_packet.read_packet(decrypted, position, len)) != null) { - if (packet.tagType == 8) { - this.text = packet.decompress(); - decrypted = packet.decompress(); + + var messages = openpgp.read_messages_dearmored({text: decrypted, openpgp: decrypted}); + for(var m in messages){ + if(messages[m].data){ + this.text = messages[m].data; } - util.print_debug(packet.toString()); - position += packet.headerLength+packet.packetLength; - if (position > 38) - util.print_debug_hexstr_dump("openpgp.msg.messge decrypt:\n",decrypted.substring(position)); - len = decrypted.length - position; - if (packet.tagType == 11) { - this.text = packet.data; - util.print_info("message successfully decrypted"); + if(messages[m].signature){ + validSignatures.push(messages[m].verifySignature(pubkey)); } - if (packet.tagType == 19) - // ignore.. we checked that already in a more strict way. - continue; - if (packet.tagType == 2 && packet.signatureType < 3) { - if(!pubkey || pubkey.length == 0 ){ - var pubkey = openpgp.keyring.getPublicKeysForKeyId(packet.issuerKeyId); - } - if (pubkey.length == 0) { - util.print_warning("Unable to verify signature of issuer: "+util.hexstrdump(packet.issuerKeyId)+". Public key not found in keyring."); - validSignatures[validSignatures.length] = false; - } else { - if(packet.verify(this.text.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"),pubkey[0]) && pubkey[0].obj.validate()){ - util.print_info("Found Good Signature from "+pubkey[0].obj.userIds[0].text+" (0x"+util.hexstrdump(pubkey[0].obj.getKeyId()).substring(8)+")"); - validSignatures[validSignatures.length] = true; - } - else{ - util.print_error("Signature verification failed: Bad Signature from "+pubkey[0].obj.userIds[0].text+" (0x"+util.hexstrdump(pubkey[0].obj.getKeyId()).substring(8)+")"); - validSignatures[validSignatures.length] = false; - } - } - } - } - if (this.text == "") { - this.text = decrypted; } return {text:this.text, validSignatures:validSignatures}; } @@ -109,7 +81,7 @@ function openpgp_msg_message() { */ function verifySignature(pubkey) { var result = false; - if (this.type == 2) { + if (this.signature.tagType == 2) { if(!pubkey || pubkey.length == 0){ var pubkey; if (this.signature.version == 4) { @@ -126,7 +98,7 @@ function openpgp_msg_message() { else { for (var i = 0 ; i < pubkey.length; i++) { var tohash = this.text.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"); - if (this.signature.verify(tohash.substring(0, tohash.length -2), pubkey[i])) { + if (this.signature.verify(tohash, pubkey[i])) { util.print_info("Found Good Signature from "+pubkey[i].obj.userIds[i].text+" (0x"+util.hexstrdump(pubkey[i].obj.getKeyId()).substring(8)+")"); result = true; } else { diff --git a/src/openpgp.msg.publickey.js b/src/openpgp.msg.publickey.js index df8697e6..ecd2b966 100644 --- a/src/openpgp.msg.publickey.js +++ b/src/openpgp.msg.publickey.js @@ -162,7 +162,6 @@ function openpgp_msg_publickey() { var tohash = this.publicKeyPacket.header+this.publicKeyPacket.data; if (this.revocationSignatures[i].verify(tohash, this.publicKeyPacket)) return false; - else return false; } if (this.subKeys.length != 0) { diff --git a/src/packet/openpgp.packet.compressed.js b/src/packet/openpgp.packet.compressed.js index b611ecfd..11fadb7d 100644 --- a/src/packet/openpgp.packet.compressed.js +++ b/src/packet/openpgp.packet.compressed.js @@ -27,6 +27,7 @@ */ function openpgp_packet_compressed() { this.tagType = 8; + this.decompressedData = null; /** * parsing function for the packet. @@ -61,16 +62,15 @@ function openpgp_packet_compressed() { 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)); - var outputString = unescape(jxg_obj.deflate()[0][0]); - var packet = openpgp_packet.read_packet(outputString, 0, outputString.length); - util.print_info('Decompressed packet [Type 1-ZIP]: ' + packet); - this.decompressedData = packet.data; + 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. @@ -78,15 +78,9 @@ function openpgp_packet_compressed() { // 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,""); - var outputString = JXG.decompress(radix); //TODO check ADLER32 checksum - var dearmored = {type: 3, text: outputString, openpgp: outputString}; - var messages = openpgp.read_messages_dearmored(dearmored); - for(var m in messages){ - if(messages[m].data){ - this.decompressedData = messages[m].data; - } - } + this.decompressedData = JXG.decompress(radix); + break; } else { util.print_error("Compression algorithm ZLIB only supports DEFLATE compression method."); } diff --git a/src/packet/openpgp.packet.keymaterial.js b/src/packet/openpgp.packet.keymaterial.js index 0e65d1e4..c9d62d82 100644 --- a/src/packet/openpgp.packet.keymaterial.js +++ b/src/packet/openpgp.packet.keymaterial.js @@ -572,7 +572,7 @@ function openpgp_packet_keymaterial() { pos += result.packetLength + result.headerLength; break; } else if (result.signatureType == 40) { // subkey revocation signature - this.subKeyRevocationSignature = result; + this.subKeyRevocationSignature[this.subKeyRevocationSignature.length] = result; pos += result.packetLength + result.headerLength; break; } else { @@ -605,7 +605,7 @@ function openpgp_packet_keymaterial() { if (result.signatureType == 24) // subkey embedded signature this.subKeySignature = result; else if (result.signatureType == 40) // subkey revocation signature - this.subKeyRevocationSignature[this.subKeyRevocationSignature] = result; + this.subKeyRevocationSignature[this.subKeyRevocationSignature.length] = result; pos += result.packetLength + result.headerLength; break; default: @@ -631,26 +631,24 @@ function openpgp_packet_keymaterial() { */ function verifyKey() { if (this.tagType == 14) { - if (this.subKeySignature == null) + if (this.subKeySignature == null) { return 0; + } if (this.subKeySignature.version == 4 && this.subKeySignature.keyNeverExpires != null && !this.subKeySignature.keyNeverExpires && - new Date((this.subKeySignature.keyExpirationTime*1000)+ this.creationTime.getTime()) < new Date()) - return 1; + new Date((this.subKeySignature.keyExpirationTime*1000)+ this.creationTime.getTime()) < new Date()) { + return 1; + } var hashdata = String.fromCharCode(0x99)+this.parentNode.header.substring(1)+this.parentNode.data+ String.fromCharCode(0x99)+this.header.substring(1)+this.packetdata; if (!this.subKeySignature.verify(hashdata,this.parentNode)) { return 0; } for (var i = 0; i < this.subKeyRevocationSignature.length; i++) { - if (this.subKeyRevocationSignature[i]) - var hashdata = String.fromCharCode(0x99)+this.parentNode.header.substring(1)+this.parentNode.data+ - String.fromCharCode(0x99)+this.header.substring(1)+this.packetdata; - if (this.subKeyRevocationSignature[i].verify(hashdata, this.parentNode)) - return 2; - else - return 0; + if (this.getKeyId() == this.subKeyRevocationSignature[i].keyId){ + return 2; + } } } return 3; diff --git a/src/packet/openpgp.packet.signature.js b/src/packet/openpgp.packet.signature.js index 1162199b..f4fbc9b2 100644 --- a/src/packet/openpgp.packet.signature.js +++ b/src/packet/openpgp.packet.signature.js @@ -65,6 +65,7 @@ function openpgp_packet_signature() { this.signatureTargetHashAlgorithm = null; this.signatureTargetHash = null; this.embeddedSignature = null; + this.verified = false; /** @@ -483,55 +484,43 @@ function openpgp_packet_signature() { * @return {boolean} True if message is verified, else false. */ function verify(data, key) { - switch(this.signatureType) { // calculating the trailer + var trailer = ''; + trailer += String.fromCharCode(this.version); + trailer += String.fromCharCode(0xFF); + trailer += String.fromCharCode(this.signatureData.length >> 24); + trailer += String.fromCharCode((this.signatureData.length >> 16) &0xFF); + trailer += String.fromCharCode((this.signatureData.length >> 8) &0xFF); + trailer += String.fromCharCode(this.signatureData.length & 0xFF); + switch(this.signatureType) { case 0: // 0x00: Signature of a binary document. if (this.version == 4) { - var trailer = ''; - trailer += String.fromCharCode(this.version); - trailer += String.fromCharCode(0xFF); - trailer += String.fromCharCode(this.signatureData.length >> 24); - trailer += String.fromCharCode((this.signatureData.length >> 16) &0xFF); - trailer += String.fromCharCode((this.signatureData.length >> 8) &0xFF); - trailer += String.fromCharCode(this.signatureData.length & 0xFF); - return openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, + this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, this.MPIs, key.obj.publicKeyPacket.MPIs, data.substring(i)+this.signatureData+trailer); - } else if (this.version == 3) { - return false; } + break; case 1: // 0x01: Signature of a canonical text document. if (this.version == 4) { - var trailer = ''; - trailer += String.fromCharCode(this.version); - trailer += String.fromCharCode(0xFF); - trailer += String.fromCharCode(this.signatureData.length >> 24); - trailer += String.fromCharCode((this.signatureData.length >> 16) &0xFF); - trailer += String.fromCharCode((this.signatureData.length >> 8) &0xFF); - trailer += String.fromCharCode(this.signatureData.length &0xFF); - return openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, + this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, this.MPIs, key.obj.publicKeyPacket.MPIs, data+this.signatureData+trailer); - } else if (this.version == 3) { - return false; + 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-length // binary document. Note that it doesn't make sense to have a V3 // standalone signature. - if (this.version == 3) - return false; + if (this.version == 3) { + this.verified = false; + break; + } - var trailer = ''; - trailer += String.fromCharCode(this.version); - trailer += String.fromCharCode(0xFF); - trailer += String.fromCharCode(this.signatureData.length >> 24); - trailer += String.fromCharCode((this.signatureData.length >> 16) &0xFF); - trailer += String.fromCharCode((this.signatureData.length >> 8) &0xFF); - trailer += String.fromCharCode(this.signatureData.length &0xFF); - return openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, + this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, this.MPIs, key.obj.publicKeyPacket.MPIs, 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 @@ -563,15 +552,9 @@ function openpgp_packet_signature() { // revokes, and should have a later creation date than that // certificate. - var trailer = ''; - trailer += String.fromCharCode(this.version); - trailer += String.fromCharCode(0xFF); - trailer += String.fromCharCode(this.signatureData.length >> 24); - trailer += String.fromCharCode((this.signatureData.length >> 16) &0xFF); - trailer += String.fromCharCode((this.signatureData.length >> 8) &0xFF); - trailer += String.fromCharCode(this.signatureData.length &0xFF); - return openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, + this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, this.MPIs, key.MPIs, data+this.signatureData+trailer); + break; case 24: // 0x18: Subkey Binding Signature @@ -582,18 +565,14 @@ function openpgp_packet_signature() { // 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) - return false; + if (this.version == 3) { + this.verified = false; + break; + } - var trailer = ''; - trailer += String.fromCharCode(this.version); - trailer += String.fromCharCode(0xFF); - trailer += String.fromCharCode(this.signatureData.length >> 24); - trailer += String.fromCharCode((this.signatureData.length >> 16) &0xFF); - trailer += String.fromCharCode((this.signatureData.length >> 8) &0xFF); - trailer += String.fromCharCode(this.signatureData.length &0xFF); - return openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, + this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, this.MPIs, key.MPIs, data+this.signatureData+trailer); + break; case 25: // 0x19: Primary Key Binding Signature // This signature is a statement by a signing subkey, indicating @@ -630,16 +609,9 @@ function openpgp_packet_signature() { // by the top-level signature key that is bound to this subkey, or // by an authorized revocation key, should be considered valid // revocation signatures. - var trailer = ''; - trailer += String.fromCharCode(this.version); - trailer += String.fromCharCode(0xFF); - trailer += String.fromCharCode(this.signatureData.length >> 24); - trailer += String.fromCharCode((this.signatureData.length >> 16) &0xFF); - trailer += String.fromCharCode((this.signatureData.length >> 8) &0xFF); - trailer += String.fromCharCode(this.signatureData.length &0xFF); - return openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, + this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm, this.MPIs, key.MPIs, data+this.signatureData+trailer); - + break; // Key revocation signatures (types 0x20 and 0x28) // hash only the key being revoked. @@ -660,6 +632,7 @@ function openpgp_packet_signature() { util.print_error("openpgp.packet.signature.js\n"+"signature verification for type"+ this.signatureType+" not implemented"); break; } + return this.verified; } /** * generates debug output (pretty print)