From a50c7a7f4d3260e117dd17705431242abd9d1ad2 Mon Sep 17 00:00:00 2001 From: Sean Colyer Date: Sat, 6 Oct 2012 11:39:07 -0400 Subject: [PATCH] Fix for ZLIB issue (endless loop), and dynamic header lengths. --- resources/openpgp.js | 60 ++++++++++++++------ resources/openpgp.min.js | 73 +++++++++++++------------ src/compression/zlib/jsxcompressor.js | 4 ++ src/openpgp.js | 41 ++++++++++---- src/packet/openpgp.packet.compressed.js | 10 +++- src/packet/openpgp.packet.js | 3 +- 6 files changed, 122 insertions(+), 69 deletions(-) diff --git a/resources/openpgp.js b/resources/openpgp.js index 3b65c0b3..2e793443 100644 --- a/resources/openpgp.js +++ b/resources/openpgp.js @@ -2219,7 +2219,6 @@ function _openpgp_packet() { mypos++; // parsed length from length field - var len = 0; var bodydata = null; // used for partial body lengths @@ -2254,6 +2253,8 @@ function _openpgp_packet() { // definite length, or a new format header. The new format // headers described below have a mechanism for precisely // encoding data of indeterminate length. + packet_length = len; + break; } } else // 4.2.2. New Format Packet Lengths @@ -2571,9 +2572,13 @@ function openpgp_packet_compressed() { var radix = s2r(compData).replace(/\n/g,""); var outputString = JXG.decompress(radix); //TODO check ADLER32 checksum - var packet = openpgp_packet.read_packet(outputString, 0, outputString.length); - util.print_info('Decompressed packet [Type 2-ZLIB]: ' + packet); - this.decompressedData = packet.data; + 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; + } + } } else { util.print_error("Compression algorithm ZLIB only supports DEFLATE compression method."); } @@ -9684,13 +9689,20 @@ function _openpgp () { util.print_error('no message found!'); return null; } - var input = dearmored.openpgp; + return read_messages_dearmored(dearmored); + } + + function read_messages_dearmored(input){ + var messageString = input.openpgp; var messages = new Array(); var messageCount = 0; var mypos = 0; - var l = input.length; - while (mypos < input.length) { - var first_packet = openpgp_packet.read_packet(input, mypos, l); + var l = messageString.length; + while (mypos < messageString.length) { + var first_packet = openpgp_packet.read_packet(messageString, mypos, l); + if (!first_packet) { + break; + } // public key parser (definition from the standard:) // OpenPGP Message :- Encrypted Message | Signed Message | // Compressed Message | Literal Message. @@ -9716,6 +9728,7 @@ function _openpgp () { if (first_packet.tagType == 1 || (first_packet.tagType == 2 && first_packet.signatureType < 16) || first_packet.tagType == 3 || + first_packet.tagType == 4 || first_packet.tagType == 8 || first_packet.tagType == 9 || first_packet.tagType == 10 || @@ -9724,7 +9737,7 @@ function _openpgp () { first_packet.tagType == 19) { messages[messages.length] = new openpgp_msg_message(); messages[messageCount].messagePacket = first_packet; - messages[messageCount].type = dearmored.type; + messages[messageCount].type = input.type; // Encrypted Message if (first_packet.tagType == 9 || first_packet.tagType == 1 || @@ -9742,7 +9755,7 @@ function _openpgp () { messages[messageCount].sessionKeys[sessionKeyCount] = first_packet; mypos += first_packet.packetLength + first_packet.headerLength; l -= (first_packet.packetLength + first_packet.headerLength); - first_packet = openpgp_packet.read_packet(input, mypos, l); + first_packet = openpgp_packet.read_packet(messageString, mypos, l); if (first_packet.tagType != 1 && first_packet.tagType != 3) issessionkey = false; @@ -9766,12 +9779,19 @@ function _openpgp () { } else // Signed Message if (first_packet.tagType == 2 && first_packet.signatureType < 3) { - messages[messageCount].text = dearmored.text; + messages[messageCount].text = input.text; messages[messageCount].signature = first_packet; break; + } else + // Signed Message + if (first_packet.tagType == 4) { + //TODO: Implement check + 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; @@ -9784,12 +9804,13 @@ function _openpgp () { // continue with next packet mypos += first_packet.packetLength + first_packet.headerLength; l -= (first_packet.packetLength + first_packet.headerLength); - } else - // Literal Message - // TODO: needs to be implemented. From a security perspective: this message is plaintext anyway. + } else if (first_packet.tagType == 11) { - util.print_error("A direct literal message is currently not supported."); - break; + // Literal Message -- work is already done in read_packet + mypos += first_packet.packetLength + first_packet.headerLength; + l -= (first_packet.packetLength + first_packet.headerLength); + messages[messageCount].data = first_packet.data; + messageCount++; } } else { util.print_error('no message found!'); @@ -9954,6 +9975,7 @@ function _openpgp () { this.write_signed_and_encrypted_message = write_signed_and_encrypted_message; this.write_encrypted_message = write_encrypted_message; this.read_message = read_message; + this.read_messages_dearmored = read_messages_dearmored; this.read_publicKey = read_publicKey; this.read_privateKey = read_privateKey; this.init = init; @@ -10265,7 +10287,7 @@ function openpgp_config() { keyserver: "keyserver.linux.it" // "pgp.mit.edu:11371" }; - this.versionstring ="OpenPGP.js v.1.20120911"; + this.versionstring ="OpenPGP.js v.1.20121006"; this.commentstring ="http://openpgpjs.org"; /** * reads the config out of the HTML5 local storage @@ -11525,6 +11547,7 @@ JXG.Util.Unzip = function (barray){ } if (debug) document.write("
literalTree"); + outer: while(1) { j = DecodeValue(literalTree); if(j >= 256) { // In C64: if carry set @@ -11546,6 +11569,9 @@ JXG.Util.Unzip = function (barray){ } dist += cpdist[j]; while(len--) { + if(bIdx - dist < 0) { + break outer; + } var c = buf32k[(bIdx - dist) & 0x7fff]; addBuffer(c); } diff --git a/resources/openpgp.min.js b/resources/openpgp.min.js index d0a05306..e777e032 100644 --- a/resources/openpgp.min.js +++ b/resources/openpgp.min.js @@ -62,20 +62,20 @@ function openpgp_packet_userattribute(){this.tagType=17;this.certificationSignat e+" l:"+f);break}else switch(g.tagType){case 2:15g.signatureType?this.certificationSignatures[this.certificationSignatures.length]=g:32==g.signatureType&&(this.certificationRevocationSignatures[this.certificationRevocationSignatures.length]=g);e+=g.packetLength+g.headerLength;f=d-(e-c);break;default:return this.data=a,this.position=c-b.packetLength,this.len=e-c}}this.data=a;this.position=c-b.packetLength;return this.len=e-c};this.toString=function(){for(var b="5.12. User Attribute Packet (Tag 17)\n AttributePackets: (count = "+ this.userattributes.length+")\n",a=0;aa?result+=String.fromCharCode(a):191a?(result+=String.fromCharCode((a-192>>8)+192),result+=String.fromCharCode(a-192&255)):(result+=String.fromCharCode(255),result+=String.fromCharCode(a>>24&255),result+=String.fromCharCode(a>>16&255),result+=String.fromCharCode(a>>8&255),result+=String.fromCharCode(a&255));return result}this.encode_length=b;this.write_old_packet_header=function(a,b){var d="";256>b?(d+=String.fromCharCode(128|a<<2),d+= -String.fromCharCode(b)):(65536>b?(d+=String.fromCharCode(a<<2|129),d+=String.fromCharCode(b>>8)):(d+=String.fromCharCode(a<<2|130),d+=String.fromCharCode(b>>24&255),d+=String.fromCharCode(b>>16&255),d+=String.fromCharCode(b>>8&255)),d+=String.fromCharCode(b&255));return d};this.write_packet_header=function(a,c){var d;d=""+String.fromCharCode(192|a);return d+=b(c)};this.read_packet=function(a,b){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 propably not containing a valid OpenPGP format."), -null;var d=b,e=-1,f=-1,f=0;0!=(a[d].charCodeAt()&64)&&(f=1);var g;f?e=a[d].charCodeAt()&63:(e=(a[d].charCodeAt()&63)>>2,g=a[d].charCodeAt()&3);d++;var h=null,k=-1;if(f)if(192>a[d].charCodeAt())packet_length=a[d++].charCodeAt(),util.print_debug("1 byte length:"+packet_length);else if(192<=a[d].charCodeAt()&&224>a[d].charCodeAt())packet_length=(a[d++].charCodeAt()-192<<8)+a[d++].charCodeAt()+192,util.print_debug("2 byte length:"+packet_length);else if(223a[d].charCodeAt()){packet_length= -1<<(a[d++].charCodeAt()&31);util.print_debug("4 byte length:"+packet_length);k=d+packet_length;for(h=a.substring(d,d+packet_length);;)if(192>a[k].charCodeAt()){f=a[k++].charCodeAt();packet_length+=f;h+=a.substring(k,k+f);k+=f;break}else if(192<=a[k].charCodeAt()&&224>a[k].charCodeAt()){f=(a[k++].charCodeAt()-192<<8)+a[k++].charCodeAt()+192;packet_length+=f;h+=a.substring(k,k+f);k+=f;break}else if(223a[k].charCodeAt())f=1<<(a[k++].charCodeAt()&31),packet_length+=f,h+=a.substring(k, -k+f),k+=f;else{k++;f=a[k++].charCodeAt()<<24|a[k++].charCodeAt()<<16|a[k++].charCodeAt()<<8|a[k++].charCodeAt();h+=a.substring(k,k+f);packet_length+=f;k+=f;break}}else d++,packet_length=a[d++].charCodeAt()<<24|a[d++].charCodeAt()<<16|a[d++].charCodeAt()<<8|a[d++].charCodeAt();else switch(g){case 0:packet_length=a[d++].charCodeAt();break;case 1:packet_length=a[d++].charCodeAt()<<8|a[d++].charCodeAt();break;case 2:packet_length=a[d++].charCodeAt()<<24|a[d++].charCodeAt()<<16|a[d++].charCodeAt()<<8| -a[d++].charCodeAt()}-1==k&&(k=packet_length);null==h&&(h=a.substring(d,d+k));switch(e){case 0:break;case 1:e=new openpgp_packet_encryptedsessionkey;if(null!=e.read_pub_key_packet(h,0,packet_length))return e.headerLength=d-b,e.packetLength=k,e;break;case 2:e=new openpgp_packet_signature;if(null!=e.read_packet(h,0,packet_length))return e.headerLength=d-b,e.packetLength=k,e;break;case 3:e=new openpgp_packet_encryptedsessionkey;if(null!=e.read_symmetric_key_packet(h,0,packet_length))return e.headerLength= -d-b,e.packetLength=k,e;break;case 4:e=new openpgp_packet_onepasssignature;if(e.read_packet(h,0,packet_length))return e.headerLength=d-b,e.packetLength=k,e;break;case 5:e=new openpgp_packet_keymaterial;e.header=a.substring(b,d);if(null!=e.read_tag5(h,0,packet_length))return e.headerLength=d-b,e.packetLength=k,e;break;case 6:e=new openpgp_packet_keymaterial;e.header=a.substring(b,d);if(null!=e.read_tag6(h,0,packet_length))return e.headerLength=d-b,e.packetLength=k,e;break;case 7:e=new openpgp_packet_keymaterial; -if(null!=e.read_tag7(h,0,packet_length))return e.headerLength=d-b,e.packetLength=k,e;break;case 8:e=new openpgp_packet_compressed;if(null!=e.read_packet(h,0,packet_length))return e.headerLength=d-b,e.packetLength=k,e;break;case 9:e=new openpgp_packet_encrypteddata;if(null!=e.read_packet(h,0,packet_length))return e.headerLength=d-b,e.packetLength=k,e;break;case 10:e=new openpgp_packet_marker;if(null!=e.read_packet(h,0,packet_length))return e.headerLength=d-b,e.packetLength=k,e;break;case 11:e=new openpgp_packet_literaldata; -if(null!=e.read_packet(h,0,packet_length))return e.headerLength=d-b,e.header=a.substring(b,d),e.packetLength=k,e;break;case 12:break;case 13:e=new openpgp_packet_userid;if(null!=e.read_packet(h,0,packet_length))return e.headerLength=d-b,e.packetLength=k,e;break;case 14:e=new openpgp_packet_keymaterial;e.header=a.substring(b,d);if(null!=e.read_tag14(h,0,packet_length))return e.headerLength=d-b,e.packetLength=k,e;break;case 17:e=new openpgp_packet_userattribute;if(null!=e.read_packet(h,0,packet_length))return e.headerLength= -d-b,e.packetLength=k,e;break;case 18:e=new openpgp_packet_encryptedintegrityprotecteddata;if(null!=e.read_packet(h,0,packet_length))return e.headerLength=d-b,e.packetLength=k,e;break;case 19:e=new openpgp_packet_modificationdetectioncode;if(null!=e.read_packet(h,0,packet_length))return e.headerLength=d-b,e.packetLength=k,e;break;default:return util.print_error("openpgp.packet.js\n[ERROR] openpgp_packet: failed to parse packet @:"+d+"\nchar:'"+util.hexstrdump(a.substring(d))+"'\ninput:"+util.hexstrdump(a)), +String.fromCharCode(b)):(65536>b?(d+=String.fromCharCode(a<<2|129),d+=String.fromCharCode(b>>8)):(d+=String.fromCharCode(a<<2|130),d+=String.fromCharCode(b>>24&255),d+=String.fromCharCode(b>>16&255),d+=String.fromCharCode(b>>8&255)),d+=String.fromCharCode(b&255));return d};this.write_packet_header=function(a,c){var d;d=""+String.fromCharCode(192|a);return d+=b(c)};this.read_packet=function(a,b,d){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 propably not containing a valid OpenPGP format."), +null;var e=b,f=-1,g=-1,g=0;0!=(a[e].charCodeAt()&64)&&(g=1);var h;g?f=a[e].charCodeAt()&63:(f=(a[e].charCodeAt()&63)>>2,h=a[e].charCodeAt()&3);e++;var k=null,j=-1;if(g)if(192>a[e].charCodeAt())packet_length=a[e++].charCodeAt(),util.print_debug("1 byte length:"+packet_length);else if(192<=a[e].charCodeAt()&&224>a[e].charCodeAt())packet_length=(a[e++].charCodeAt()-192<<8)+a[e++].charCodeAt()+192,util.print_debug("2 byte length:"+packet_length);else if(223a[e].charCodeAt()){packet_length= +1<<(a[e++].charCodeAt()&31);util.print_debug("4 byte length:"+packet_length);j=e+packet_length;for(k=a.substring(e,e+packet_length);;)if(192>a[j].charCodeAt()){d=a[j++].charCodeAt();packet_length+=d;k+=a.substring(j,j+d);j+=d;break}else if(192<=a[j].charCodeAt()&&224>a[j].charCodeAt()){d=(a[j++].charCodeAt()-192<<8)+a[j++].charCodeAt()+192;packet_length+=d;k+=a.substring(j,j+d);j+=d;break}else if(223a[j].charCodeAt())d=1<<(a[j++].charCodeAt()&31),packet_length+=d,k+=a.substring(j, +j+d),j+=d;else{j++;d=a[j++].charCodeAt()<<24|a[j++].charCodeAt()<<16|a[j++].charCodeAt()<<8|a[j++].charCodeAt();k+=a.substring(j,j+d);packet_length+=d;j+=d;break}}else e++,packet_length=a[e++].charCodeAt()<<24|a[e++].charCodeAt()<<16|a[e++].charCodeAt()<<8|a[e++].charCodeAt();else switch(h){case 0:packet_length=a[e++].charCodeAt();break;case 1:packet_length=a[e++].charCodeAt()<<8|a[e++].charCodeAt();break;case 2:packet_length=a[e++].charCodeAt()<<24|a[e++].charCodeAt()<<16|a[e++].charCodeAt()<<8| +a[e++].charCodeAt();break;default:packet_length=d}-1==j&&(j=packet_length);null==k&&(k=a.substring(e,e+j));switch(f){case 0:break;case 1:f=new openpgp_packet_encryptedsessionkey;if(null!=f.read_pub_key_packet(k,0,packet_length))return f.headerLength=e-b,f.packetLength=j,f;break;case 2:f=new openpgp_packet_signature;if(null!=f.read_packet(k,0,packet_length))return f.headerLength=e-b,f.packetLength=j,f;break;case 3:f=new openpgp_packet_encryptedsessionkey;if(null!=f.read_symmetric_key_packet(k,0,packet_length))return f.headerLength= +e-b,f.packetLength=j,f;break;case 4:f=new openpgp_packet_onepasssignature;if(f.read_packet(k,0,packet_length))return f.headerLength=e-b,f.packetLength=j,f;break;case 5:f=new openpgp_packet_keymaterial;f.header=a.substring(b,e);if(null!=f.read_tag5(k,0,packet_length))return f.headerLength=e-b,f.packetLength=j,f;break;case 6:f=new openpgp_packet_keymaterial;f.header=a.substring(b,e);if(null!=f.read_tag6(k,0,packet_length))return f.headerLength=e-b,f.packetLength=j,f;break;case 7:f=new openpgp_packet_keymaterial; +if(null!=f.read_tag7(k,0,packet_length))return f.headerLength=e-b,f.packetLength=j,f;break;case 8:f=new openpgp_packet_compressed;if(null!=f.read_packet(k,0,packet_length))return f.headerLength=e-b,f.packetLength=j,f;break;case 9:f=new openpgp_packet_encrypteddata;if(null!=f.read_packet(k,0,packet_length))return f.headerLength=e-b,f.packetLength=j,f;break;case 10:f=new openpgp_packet_marker;if(null!=f.read_packet(k,0,packet_length))return f.headerLength=e-b,f.packetLength=j,f;break;case 11:f=new openpgp_packet_literaldata; +if(null!=f.read_packet(k,0,packet_length))return f.headerLength=e-b,f.header=a.substring(b,e),f.packetLength=j,f;break;case 12:break;case 13:f=new openpgp_packet_userid;if(null!=f.read_packet(k,0,packet_length))return f.headerLength=e-b,f.packetLength=j,f;break;case 14:f=new openpgp_packet_keymaterial;f.header=a.substring(b,e);if(null!=f.read_tag14(k,0,packet_length))return f.headerLength=e-b,f.packetLength=j,f;break;case 17:f=new openpgp_packet_userattribute;if(null!=f.read_packet(k,0,packet_length))return f.headerLength= +e-b,f.packetLength=j,f;break;case 18:f=new openpgp_packet_encryptedintegrityprotecteddata;if(null!=f.read_packet(k,0,packet_length))return f.headerLength=e-b,f.packetLength=j,f;break;case 19:f=new openpgp_packet_modificationdetectioncode;if(null!=f.read_packet(k,0,packet_length))return f.headerLength=e-b,f.packetLength=j,f;break;default:return util.print_error("openpgp.packet.js\n[ERROR] openpgp_packet: failed to parse packet @:"+e+"\nchar:'"+util.hexstrdump(a.substring(e))+"'\ninput:"+util.hexstrdump(a)), null}}}var openpgp_packet=new _openpgp_packet; function openpgp_packet_compressed(){this.tagType=8;this.read_packet=function(b,a,c){this.packetLength=c;var d=a;this.type=b.charCodeAt(d++);this.compressedData=b.substring(a+1,a+c);return this};this.toString=function(){return"5.6. Compressed Data Packet (Tag 8)\n length: "+this.packetLength+"\n Compression Algorithm = "+this.type+"\n Compressed Data: Byte ["+util.hexstrdump(this.compressedData)+"]\n"};this.compress=function(b,a){this.type=b;this.decompressedData=a;switch(this.type){case 0:this.compressedData= this.decompressedData;break;case 1:util.print_error("Compression algorithm ZIP [RFC1951] is not implemented.");break;case 2:util.print_error("Compression algorithm ZLIB [RFC1950] is not implemented.");break;case 3:util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");break;default:util.print_error("Compression algorithm unknown :"+this.type)}this.packetLength=this.compressedData.length+1;return this.compressedData};this.decompress=function(){if(null!=this.decompressedData)return this.decompressedData; -if(null==this.type)return null;switch(this.type){case 0:this.decompressedData=this.compressedData;break;case 1:var b=this.compressedData,b=s2r(b).replace(/\n/g,""),b=new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(b)),b=unescape(b.deflate()[0][0]),b=openpgp_packet.read_packet(b,0,b.length);util.print_info("Decompressed packet [Type 1-ZIP]: "+b);this.decompressedData=b.data;break;case 2:8==this.compressedData.charCodeAt(0)%16?(b=this.compressedData.substring(0,this.compressedData.length-4),b=s2r(b).replace(/\n/g, -""),b=JXG.decompress(b),b=openpgp_packet.read_packet(b,0,b.length),util.print_info("Decompressed packet [Type 2-ZLIB]: "+b),this.decompressedData=b.data):util.print_error("Compression algorithm ZLIB only supports DEFLATE compression method.");break;case 3:util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");break;default:util.print_error("Compression algorithm unknown :"+this.type)}util.print_debug("decompressed:"+util.hexstrdump(this.decompressedData));return this.decompressedData}; +if(null==this.type)return null;switch(this.type){case 0:this.decompressedData=this.compressedData;break;case 1:var b=this.compressedData,b=s2r(b).replace(/\n/g,""),a=new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(b)),b=unescape(a.deflate()[0][0]),a=openpgp_packet.read_packet(b,0,b.length);util.print_info("Decompressed packet [Type 1-ZIP]: "+a);this.decompressedData=a.data;break;case 2:if(8==this.compressedData.charCodeAt(0)%16)for(a in b=this.compressedData.substring(0,this.compressedData.length- +4),b=s2r(b).replace(/\n/g,""),b=JXG.decompress(b),b=openpgp.read_messages_dearmored({type:3,text:b,openpgp:b}),b){if(b[a].data)this.decompressedData=b[a].data}else util.print_error("Compression algorithm ZLIB only supports DEFLATE compression method.");break;case 3:util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");break;default:util.print_error("Compression algorithm unknown :"+this.type)}util.print_debug("decompressed:"+util.hexstrdump(this.decompressedData));return this.decompressedData}; this.write_packet=function(b,a){this.decompressedData=a;if(null==b)this.type=1;var c=String.fromCharCode(this.type)+this.compress(this.type);return openpgp_packet.write_packet_header(8,c.length)+c}} function openpgp_packet_keymaterial(){this.subKeyRevocationSignature=this.subKeySignature=this.parentNode=this.checksum=this.hasUnencryptedSecretKeyData=this.encryptedMPIData=this.IVLength=this.s2kUsageConventions=this.symmetricEncryptionAlgorithm=this.publicKey=this.secMPIs=this.MPIs=this.expiration=this.version=this.creationTime=this.tagType=this.publicKeyAlgorithm=null;this.read_tag5=function(b,a,c){this.tagType=5;this.read_priv_key(b,a,c);return this};this.read_tag6=function(b,a,c){this.tagType= 6;this.packetLength=c;this.read_pub_key(b,a,c);return this};this.read_tag7=function(b,a,c){this.tagType=7;this.packetLength=c;return this.read_priv_key(b,a,c)};this.read_tag14=function(b,a,c){this.subKeySignature=null;this.subKeyRevocationSignature=[];this.tagType=14;this.packetLength=c;this.read_pub_key(b,a,c);return this};this.toString=function(){var b="";switch(this.tagType){case 6:b+="5.5.1.1. Public-Key Packet (Tag 6)\n length: "+this.packetLength+"\n version: "+ @@ -369,21 +369,22 @@ 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(){this.tostring="";this.generate_key_pair=function(b,a,c,d){var e=(new openpgp_packet_userid).write_packet(c),a=openpgp_crypto_generateKeyPair(b,a,d,openpgp.config.config.prefer_hash_algorithm,3),b=a.privateKey,f=(new openpgp_packet_keymaterial).read_priv_key(b.string,3,b.string.length);f.decryptSecretMPIs(d)||util.print_error("Issue creating key. Unable to read resulting private key");d=new openpgp_msg_privatekey;d.privateKeyPacket=f;d.getPreferredSignatureHashAlgorithm=function(){return openpgp.config.config.prefer_hash_algorithm}; -f=d.privateKeyPacket.publicKey.data;f=String.fromCharCode(153)+String.fromCharCode(f.length>>8&255)+String.fromCharCode(f.length&255)+f+String.fromCharCode(180)+String.fromCharCode(c.length>>24)+String.fromCharCode(c.length>>16&255)+String.fromCharCode(c.length>>8&255)+String.fromCharCode(c.length&255)+c;c=new openpgp_packet_signature;c=c.write_message_signature(16,f,d);a=openpgp_encoding_armor(4,a.publicKey.string+e+c.openpgp);e=openpgp_encoding_armor(5,b.string+e+c.openpgp);return{privateKey:d, -privateKeyArmored:e,publicKeyArmored:a}};this.write_signed_message=function(b,a){var c=(new openpgp_packet_signature).write_message_signature(1,a.replace(/\r\n/g,"\n").replace(/\n/,"\r\n"),b),c={text:a.replace(/\r\n/g,"\n").replace(/\n/,"\r\n"),openpgp:c.openpgp,hash:c.hash};return openpgp_encoding_armor(2,c,null,null)};this.write_signed_and_encrypted_message=function(b,a,c){var d="",e=(new openpgp_packet_literaldata).write_packet(c.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"));util.print_debug_hexstr_dump("literal_packet: |"+ -e+"|\n",e);for(var f=0;fh.signatureType||3==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(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){util.print_error("A direct literal message is currently not supported.");break}}else return util.print_error("no message found!"),null}return d};this.read_publicKey=function(b){for(var a= -0,c=[],d=0,b=openpgp_encoding_deArmor(b.replace(/\r/g,"")).openpgp,e=b.length;a!=b.length;){var f=openpgp_packet.read_packet(b,a,e);if(153==b[a].charCodeAt()||6==f.tagType)c[d]=new openpgp_msg_publickey,c[d].header=b.substring(a,a+3),153==b[a].charCodeAt()?(a++,e=b[a++].charCodeAt()<<8|b[a++].charCodeAt(),c[d].publicKeyPacket=new openpgp_packet_keymaterial,c[d].publicKeyPacket.header=c[d].header,c[d].publicKeyPacket.read_tag6(b,a,e),a+=c[d].publicKeyPacket.packetLength,a+=c[d].read_nodes(c[d].publicKeyPacket, -b,a,b.length-a)):(c[d]=new openpgp_msg_publickey,c[d].publicKeyPacket=f,a+=f.headerLength+f.packetLength,a+=c[d].read_nodes(f,b,a,b.length-a));else return util.print_error("no public key found!"),null;c[d].data=b.substring(0,a);d++}return c};this.read_privateKey=function(b){for(var a=[],c=0,d=0,b=openpgp_encoding_deArmor(b.replace(/\r/g,"")).openpgp,e=b.length;d!=b.length;){var f=openpgp_packet.read_packet(b,d,e);if(5==f.tagType)a[a.length]=new openpgp_msg_privatekey,d+=f.headerLength+f.packetLength, -d+=a[c].read_nodes(f,b,d,e);else return util.print_error("no block packet found!"),null;a[c].data=b.substring(0,d);c++}return a};this.init=function(){this.config=new openpgp_config;this.config.read();this.keyring=new openpgp_keyring;this.keyring.init()}}var openpgp=new _openpgp; -function openpgp_msg_publickey(){this.tostring="OPENPGP PUBLIC KEY\n";this.publicKeyPacket=this.bindingSignature=null;this.userIds=[];this.userAttributes=[];this.revocationSignatures=[];this.subKeys=[];this.arbitraryPacket=[];this.directSignatures=[];this.verifyCertificationSignatures=function(){for(var b=[],a=0;ah.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;gIsPat "+b);if(0<=b)a.b alert("invalid huffman tree\n"),-1;if(m){document.write("
Tree: "+V.length);for(a=0;32>a;a++)document.write("Places["+a+"].b0="+V[a].b0+"
"),document.write("Places["+a+"].b1="+V[a].b1+"
")}return 0}function j(a){for(var b,d,e=0,f=a[e];;)if(b=c(),m&&document.write("b="+b),b){if(!(f.b1&32768))return m&&document.write("ret1"),f.b1;f=f.jump;b=a.length;for(d=0;d>1,23h)e(h);else if(256==h)break;else{var o;h-=257;p=d(K[h])+M[h];h=D[d(5)]>>3;8h;h++)r[h]=0;for(h=0;hdistanceTree");for(h=0;h"+P[h].b0+" "+P[h].b1+" "+P[h].jump+" "+P[h].jumppos)}p=g+o;l=0;var v= --1;for(m&&document.write("
n="+p+" bits: "+aa+"
");l"+v+" i:"+l+" decode: "+h+" bits "+aa+"
"),16>h)r[l++]=h;else if(16==h){var x;h=3+d(2);if(l+h>p)return t=0,1;for(x=l?r[l-1]:0;h--;)r[l++]=x}else{h=17==h?3+d(3):11+d(7);if(l+h>p)return t=0,1;for(;h--;)r[l++]=0}p=ba.length;for(l=0;lliteralTree");;)if(h= -j(ba),256<=h){h-=256;if(0==h)break;h--;p=d(K[h])+M[h];h=j(P);8n="+p+" bits: "+aa+"
");l"+v+" i:"+l+" decode: "+h+" bits "+aa+"
"),16>h)r[l++]=h;else if(16==h){var x;h=3+d(2);if(l+h>p)return t=0,1;for(x=l?r[l-1]:0;h--;)r[l++]=x}else{h=17==h?3+d(3):11+d(7);if(l+h>p)return t=0,1;for(;h--;)r[l++]=0}p=ba.length;for(l=0;lliteralTree"); +a:for(;;)if(h=j(ba),256<=h){h-=256;if(0==h)break;h--;p=d(K[h])+M[h];h=j(P);8t-o)break a;g=u[t-o&32767];e(g)}}else e(h)}}while(!b);t=0;C=1;return 0}function o(){m&&alert("NEXTFILE");p=[];var b=[];E=!1;b[0]=a();b[1]=a();m&&alert("type: "+b[0]+" "+b[1]);120==b[0]&&218==b[1]&&(m&&alert("GEONExT-GZIP"),l(),m&&alert(p.join("")),v[x]=Array(2),v[x][0]=p.join(""),v[x][1]="geonext.gxt",x++);120==b[0]&&156==b[1]&&(m&&alert("ZLIB"),l(),m&&alert(p.join("")), +v[x]=Array(2),v[x][0]=p.join(""),v[x][1]="ZLIB",x++);31==b[0]&&139==b[1]&&(m&&alert("GZIP"),r(),m&&alert(p.join("")),v[x]=Array(2),v[x][0]=p.join(""),v[x][1]="file",x++);if(80==b[0]&&75==b[1]&&(E=!0,b[2]=a(),b[3]=a(),3==b[2]&&4==b[3])){b[0]=a();b[1]=a();m&&alert("ZIP-Version: "+b[1]+" "+b[0]/10+"."+b[0]%10);y=a();y|=a()<<8;m&&alert("gpflags: "+y);b=a();b|=a()<<8;m&&alert("method: "+b);a();a();a();a();var c=a(),c=c|a()<<8,c=c|a()<<16,c=c|a()<<24,d=a(),d=d|a()<<8,d=d|a()<<16,d=d|a()<<24,e=a(),e=e|a()<< +8,e=e|a()<<16,e=e|a()<<24;m&&alert("local CRC: "+c+"\nlocal Size: "+e+"\nlocal CompSize: "+d);c=a();c|=a()<<8;d=a();d|=a()<<8;m&&alert("filelen "+c);f=0;for(R=[];c--;)e=a(),"/"==e|":"==e?f=0:f>2,c=(c&3)<<4|d>>4,g=(d&15)<<2|e>>6,h=e&63,isNaN(d)?g=h=64:isNaN(e)&&(h=64),a.push([this._keyStr.charAt(f),this._keyStr.charAt(c),this._keyStr.charAt(g),this._keyStr.charAt(h)].join(""));return a.join("")},decode:function(b,a){for(var c=[],d,e,f,g,h, k=0,b=b.replace(/[^A-Za-z0-9\+\/\=]/g,"");k>4,e=(e&15)<<4|g>>2,f=(g&3)<<6|h,c.push(String.fromCharCode(d)),64!=g&&c.push(String.fromCharCode(e)),64!=h&&c.push(String.fromCharCode(f));c=c.join("");a&&(c=JXG.Util.Base64._utf8_decode(c));return c},_utf8_encode:function(b){for(var b=b.replace(/\r\n/g,"\n"),a="",c=0;cd?a+=String.fromCharCode(d):(127d?a+=String.fromCharCode(d>>6|192):(a+=String.fromCharCode(d>>12|224),a+=String.fromCharCode(d>>6&63|128)),a+=String.fromCharCode(d&63|128))}return a},_utf8_decode:function(b){for(var a=[],c=0,d=0,e=0,f=0;cd?(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| diff --git a/src/compression/zlib/jsxcompressor.js b/src/compression/zlib/jsxcompressor.js index 39bfeb6e..d5f138c1 100644 --- a/src/compression/zlib/jsxcompressor.js +++ b/src/compression/zlib/jsxcompressor.js @@ -575,6 +575,7 @@ JXG.Util.Unzip = function (barray){ } if (debug) document.write("
literalTree"); + outer: while(1) { j = DecodeValue(literalTree); if(j >= 256) { // In C64: if carry set @@ -596,6 +597,9 @@ JXG.Util.Unzip = function (barray){ } dist += cpdist[j]; while(len--) { + if(bIdx - dist < 0) { + break outer; + } var c = buf32k[(bIdx - dist) & 0x7fff]; addBuffer(c); } diff --git a/src/openpgp.js b/src/openpgp.js index 40d5ad90..52f62538 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -137,13 +137,20 @@ function _openpgp () { util.print_error('no message found!'); return null; } - var input = dearmored.openpgp; + return read_messages_dearmored(dearmored); + } + + function read_messages_dearmored(input){ + var messageString = input.openpgp; var messages = new Array(); var messageCount = 0; var mypos = 0; - var l = input.length; - while (mypos < input.length) { - var first_packet = openpgp_packet.read_packet(input, mypos, l); + var l = messageString.length; + while (mypos < messageString.length) { + var first_packet = openpgp_packet.read_packet(messageString, mypos, l); + if (!first_packet) { + break; + } // public key parser (definition from the standard:) // OpenPGP Message :- Encrypted Message | Signed Message | // Compressed Message | Literal Message. @@ -169,6 +176,7 @@ function _openpgp () { if (first_packet.tagType == 1 || (first_packet.tagType == 2 && first_packet.signatureType < 16) || first_packet.tagType == 3 || + first_packet.tagType == 4 || first_packet.tagType == 8 || first_packet.tagType == 9 || first_packet.tagType == 10 || @@ -177,7 +185,7 @@ function _openpgp () { first_packet.tagType == 19) { messages[messages.length] = new openpgp_msg_message(); messages[messageCount].messagePacket = first_packet; - messages[messageCount].type = dearmored.type; + messages[messageCount].type = input.type; // Encrypted Message if (first_packet.tagType == 9 || first_packet.tagType == 1 || @@ -195,7 +203,7 @@ function _openpgp () { messages[messageCount].sessionKeys[sessionKeyCount] = first_packet; mypos += first_packet.packetLength + first_packet.headerLength; l -= (first_packet.packetLength + first_packet.headerLength); - first_packet = openpgp_packet.read_packet(input, mypos, l); + first_packet = openpgp_packet.read_packet(messageString, mypos, l); if (first_packet.tagType != 1 && first_packet.tagType != 3) issessionkey = false; @@ -219,12 +227,19 @@ function _openpgp () { } else // Signed Message if (first_packet.tagType == 2 && first_packet.signatureType < 3) { - messages[messageCount].text = dearmored.text; + messages[messageCount].text = input.text; messages[messageCount].signature = first_packet; break; + } else + // Signed Message + if (first_packet.tagType == 4) { + //TODO: Implement check + 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; @@ -237,12 +252,13 @@ function _openpgp () { // continue with next packet mypos += first_packet.packetLength + first_packet.headerLength; l -= (first_packet.packetLength + first_packet.headerLength); - } else - // Literal Message - // TODO: needs to be implemented. From a security perspective: this message is plaintext anyway. + } else if (first_packet.tagType == 11) { - util.print_error("A direct literal message is currently not supported."); - break; + // Literal Message -- work is already done in read_packet + mypos += first_packet.packetLength + first_packet.headerLength; + l -= (first_packet.packetLength + first_packet.headerLength); + messages[messageCount].data = first_packet.data; + messageCount++; } } else { util.print_error('no message found!'); @@ -407,6 +423,7 @@ function _openpgp () { this.write_signed_and_encrypted_message = write_signed_and_encrypted_message; this.write_encrypted_message = write_encrypted_message; this.read_message = read_message; + this.read_messages_dearmored = read_messages_dearmored; this.read_publicKey = read_publicKey; this.read_privateKey = read_privateKey; this.init = init; diff --git a/src/packet/openpgp.packet.compressed.js b/src/packet/openpgp.packet.compressed.js index 2a5e0d76..b611ecfd 100644 --- a/src/packet/openpgp.packet.compressed.js +++ b/src/packet/openpgp.packet.compressed.js @@ -80,9 +80,13 @@ function openpgp_packet_compressed() { var radix = s2r(compData).replace(/\n/g,""); var outputString = JXG.decompress(radix); //TODO check ADLER32 checksum - var packet = openpgp_packet.read_packet(outputString, 0, outputString.length); - util.print_info('Decompressed packet [Type 2-ZLIB]: ' + packet); - this.decompressedData = packet.data; + 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; + } + } } else { util.print_error("Compression algorithm ZLIB only supports DEFLATE compression method."); } diff --git a/src/packet/openpgp.packet.js b/src/packet/openpgp.packet.js index 5f5646e2..28efe50f 100644 --- a/src/packet/openpgp.packet.js +++ b/src/packet/openpgp.packet.js @@ -134,7 +134,6 @@ function _openpgp_packet() { mypos++; // parsed length from length field - var len = 0; var bodydata = null; // used for partial body lengths @@ -169,6 +168,8 @@ function _openpgp_packet() { // definite length, or a new format header. The new format // headers described below have a mechanism for precisely // encoding data of indeterminate length. + packet_length = len; + break; } } else // 4.2.2. New Format Packet Lengths