From dd5d0c801c344c587512ae093c7894498678e2b1 Mon Sep 17 00:00:00 2001 From: Michal Kolodziej Date: Sat, 27 Apr 2013 18:14:57 +0200 Subject: [PATCH] Secret key packet decryption is working though, there is still work to be done in the decryption function as it's quite a mess still. --- resources/openpgp.js | 212 ++++++++++++--------------------------- resources/openpgp.min.js | 32 +++--- src/packet/secret_key.js | 212 ++++++++++++--------------------------- test/general/packet.js | 67 ++++++++++++- 4 files changed, 203 insertions(+), 320 deletions(-) diff --git a/resources/openpgp.js b/resources/openpgp.js index c012b67e..8253c8c2 100644 --- a/resources/openpgp.js +++ b/resources/openpgp.js @@ -11497,6 +11497,7 @@ function openpgp_packet_secret_key() { this.public_key = new openpgp_packet_public_key(); this.mpi = []; this.symmetric_algorithm = openpgp.symmetric.plaintext; + this.hash_algorithm = openpgp.hash.sha1; this.s2k = null; this.encrypted = null; this.iv = null; @@ -11545,7 +11546,6 @@ function openpgp_packet_secret_key() { if (s2k_usage != 0 && s2k_usage != 255 && s2k_usage != 254) { this.symmetric_algorithm = s2k_usage; - } if (s2k_usage != 0 && this.s2k.type != 1001) { @@ -11555,6 +11555,11 @@ function openpgp_packet_secret_key() { i += this.iv.length; } + if(s2k_usage == 254) + this.hash_algorithm = openpgp.hash.sha1; + else + this.hash_algorithm = 'checksum'; + // - Plain or encrypted multiprecision integers comprising the secret // key data. These algorithm-specific fields are as described // below. @@ -11616,10 +11621,18 @@ function openpgp_packet_secret_key() { bytes += String.fromCharCode(254); bytes += String.fromCharCode(this.symmetric_algorithm); bytes += this.s2k.write(); + bytes += this.encrypted; } + + return bytes; + } + + this.encrypt = function(password) { + + switch(keyType){ case 1: body += String.fromCharCode(keyType);//public key algo @@ -11636,8 +11649,8 @@ function openpgp_packet_secret_key() { body += String.fromCharCode(s2kHash); //8 octet salt value //1 octet count - var cleartextMPIs = key.d.toMPI() + key.p.toMPI() + key.q.toMPI() + key.u.toMPI(); - var sha1Hash = str_sha1(cleartextMPIs); + var cleartext = key.d.toMPI() + key.p.toMPI() + key.q.toMPI() + key.u.toMPI(); + var sha1Hash = str_sha1(cleartext); util.print_debug_hexstr_dump('write_private_key sha1: ',sha1Hash); var salt = openpgp_crypto_getRandomBytes(8); util.print_debug_hexstr_dump('write_private_key Salt: ',salt); @@ -11650,93 +11663,23 @@ function openpgp_packet_secret_key() { //if s2k, IV of same length as cipher's block switch(this.symmetric_algorithm){ case 3: - this.IVLength = 8; - this.IV = openpgp_crypto_getRandomBytes(this.IVLength); + this.iv.length = 8; + this.iv = openpgp_crypto_getRandomBytes(this.iv.length); ciphertextMPIs = normal_cfb_encrypt(function(block, key) { var cast5 = new openpgp_symenc_cast5(); cast5.setKey(key); return cast5.encrypt(util.str2bin(block)); - }, this.IVLength, util.str2bin(hashKey.substring(0,16)), cleartextMPIs + sha1Hash, this.IV); - body += this.IV + ciphertextMPIs; + }, this.iv.length, util.str2bin(hashKey.substring(0,16)), cleartext + sha1Hash, this.iv); + body += this.iv + ciphertextMPIs; break; case 7: case 8: case 9: - this.IVLength = 16; - this.IV = openpgp_crypto_getRandomBytes(this.IVLength); + this.iv.length = 16; + this.iv = openpgp_crypto_getRandomBytes(this.iv.length); ciphertextMPIs = normal_cfb_encrypt(AESencrypt, - this.IVLength, hashKey, cleartextMPIs + sha1Hash, this.IV); - body += this.IV + ciphertextMPIs; - break; - } - } - else{ - body += String.fromCharCode(0);//1 octet -- s2k, 0 for no s2k - body += key.d.toMPI() + key.p.toMPI() + key.q.toMPI() + key.u.toMPI(); - var checksum = util.calc_checksum(key.d.toMPI() + key.p.toMPI() + key.q.toMPI() + key.u.toMPI()); - body += String.fromCharCode(checksum/0x100) + String.fromCharCode(checksum%0x100);//DEPRECATED:s2k == 0, 255: 2 octet checksum, sum all octets%65536 - util.print_debug_hexstr_dump('write_private_key basic checksum: '+ checksum); - } - break; - default : - body = ""; - util.print_error("openpgp.packet.keymaterial.js\n"+'error writing private key, unknown type :'+keyType); - } - var header = openpgp_packet.write_packet_header(tag,body.length); - return {string: header+body , header: header, body: body}; - } - - this.encrypt = function() { - - var body = String.fromCharCode(4); - body += timePacket; - switch(keyType){ - case 1: - body += String.fromCharCode(keyType);//public key algo - body += key.n.toMPI(); - body += key.ee.toMPI(); - var algorithmStart = body.length; - //below shows ske/s2k - if(password){ - body += String.fromCharCode(254); //octet of 254 indicates s2k with SHA1 - //if s2k == 255,254 then 1 octet symmetric encryption algo - body += String.fromCharCode(this.symmetric_algorithm); - //if s2k == 255,254 then s2k specifier - body += String.fromCharCode(3); //s2k salt+iter - body += String.fromCharCode(s2kHash); - //8 octet salt value - //1 octet count - var cleartextMPIs = key.d.toMPI() + key.p.toMPI() + key.q.toMPI() + key.u.toMPI(); - var sha1Hash = str_sha1(cleartextMPIs); - util.print_debug_hexstr_dump('write_private_key sha1: ',sha1Hash); - var salt = openpgp_crypto_getRandomBytes(8); - util.print_debug_hexstr_dump('write_private_key Salt: ',salt); - body += salt; - var c = 96; //c of 96 translates to count of 65536 - body += String.fromCharCode(c); - util.print_debug('write_private_key c: '+ c); - var s2k = new openpgp_type_s2k(); - var hashKey = s2k.write(3, s2kHash, password, salt, c); - //if s2k, IV of same length as cipher's block - switch(this.symmetric_algorithm){ - case 3: - this.IVLength = 8; - this.IV = openpgp_crypto_getRandomBytes(this.IVLength); - ciphertextMPIs = normal_cfb_encrypt(function(block, key) { - var cast5 = new openpgp_symenc_cast5(); - cast5.setKey(key); - return cast5.encrypt(util.str2bin(block)); - }, this.IVLength, util.str2bin(hashKey.substring(0,16)), cleartextMPIs + sha1Hash, this.IV); - body += 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, hashKey, cleartextMPIs + sha1Hash, this.IV); - body += this.IV + ciphertextMPIs; + this.iv.length, hashKey, cleartext + sha1Hash, this.iv); + body += this.iv + ciphertextMPIs; break; } } @@ -11772,49 +11715,43 @@ function openpgp_packet_secret_key() { return; // creating a key out of the passphrase - var key = this.s2k.produce_key(passphrase); + var key = this.s2k.produce_key(passphrase, + openpgp_crypto_getKeyLength(this.symmetric_algorithm)); + + var cleartext = ''; - var cleartextMPIs = ""; switch (this.symmetric_algorithm) { case 1: // - IDEA [IDEA] - util.print_error("openpgp.packet.keymaterial.js\n"+"symmetric encryption algorithim: IDEA is not implemented"); + util.print_error("openpgp.packet.keymaterial.js\n" + +"symmetric encryption algorithim: IDEA is not implemented"); return false; case 2: // - TripleDES (DES-EDE, [SCHNEIER] [HAC] - 168 bit key derived from 192) - cleartextMPIs = normal_cfb_decrypt(function(block, key) { + cleartext = normal_cfb_decrypt(function(block, key) { return des(key, block,1,null,0); - }, this.IVLength, key, this.encrypted, this.IV); + }, this.iv.length, key, this.encrypted, this.iv); break; case 3: // - CAST5 (128 bit key, as per [RFC2144]) - cleartextMPIs = normal_cfb_decrypt(function(block, key) { + cleartext = normal_cfb_decrypt(function(block, key) { var cast5 = new openpgp_symenc_cast5(); cast5.setKey(key); return cast5.encrypt(util.str2bin(block)); - }, this.IVLength, util.str2bin(key.substring(0,16)), this.encrypted, this.IV); + }, this.iv.length, util.str2bin(key.substring(0,16)), this.encrypted, this.iv); break; case 4: // - Blowfish (128 bit key, 16 rounds) [BLOWFISH] - cleartextMPIs = normal_cfb_decrypt(function(block, key) { + cleartext = normal_cfb_decrypt(function(block, key) { var blowfish = new Blowfish(key); return blowfish.encrypt(block); - }, this.IVLength, key, this.encrypted, this.IV); + }, this.iv.length, key, this.encrypted, this.iv); break; case 7: // - AES with 128-bit key [AES] case 8: // - AES with 192-bit key case 9: // - AES with 256-bit key - var numBytes = 16; - //This is a weird way to achieve this. If's within a switch is probably not ideal. - if(this.symmetric_algorithm == 8){ - numBytes = 24; - key = this.s2k.produce_key(str_passphrase,numBytes); - } - if(this.symmetric_algorithm == 9){ - numBytes = 32; - key = this.s2k.produce_key(str_passphrase,numBytes); - } - cleartextMPIs = normal_cfb_decrypt(function(block,key){ - return AESencrypt(util.str2bin(block),key); - }, - this.IVLength, keyExpansion(key.substring(0,numBytes)), this.encrypted, this.IV); + cleartext = normal_cfb_decrypt(function(block,key){ + return AESencrypt(util.str2bin(block),key); + }, + this.iv.length, keyExpansion(key), + this.encrypted, this.iv); break; case 10: // - Twofish with 256-bit key [TWOFISH] util.print_error("openpgp.packet.keymaterial.js\n"+"Key material is encrypted with twofish: not implemented"); @@ -11826,58 +11763,33 @@ function openpgp_packet_secret_key() { return false; } - if (cleartextMPIs == null) { - util.print_error("openpgp.packet.keymaterial.js\n"+"cleartextMPIs was null"); + if (cleartext == null) { + util.print_error("openpgp.packet.keymaterial.js\n"+"cleartext was null"); return false; } - var cleartextMPIslength = cleartextMPIs.length; - if (s2k_usage == 254 && - str_sha1(cleartextMPIs.substring(0,cleartextMPIs.length - 20)) == - cleartextMPIs.substring(cleartextMPIs.length - 20)) { - cleartextMPIslength -= 20; - } else if (s2k_usage != 254 && util.calc_checksum(cleartextMPIs.substring(0,cleartextMPIs.length - 2)) == - (cleartextMPIs.charCodeAt(cleartextMPIs.length -2) << 8 | cleartextMPIs.charCodeAt(cleartextMPIs.length -1))) { - cleartextMPIslength -= 2; + if (this.hash_algorithm == openpgp.hash.sha1) { + var hash = str_sha1(cleartext.substring(0,cleartext.length - 20)); + + if(hash != cleartext.substring(cleartext.length - 20)) + throw "Hash mismatch!"; + cleartext = cleartext.substr(0, cleartext.length - 20); } else { - return false; - } + var hash = util.calc_checksum(cleartext.substring(0, cleartext.length - 2)); + + if(hash != cleartext.substring(cleartext.length -2)) + throw "Hash mismatch!"; + cleartext = cleartext.substr(0, cleartext.length - 2); + } - if (this.publicKey.publicKeyAlgorithm > 0 && this.publicKey.publicKeyAlgorithm < 4) { - // Algorithm-Specific Fields for RSA secret keys: - // - multiprecision integer (MPI) of RSA secret exponent d. - // - MPI of RSA secret prime value p. - // - MPI of RSA secret prime value q (p < q). - // - MPI of u, the multiplicative inverse of p, mod q. - var i = 0; - this.mpi = new Array(); - this.mpi[0] = new openpgp_type_mpi(); - this.mpi[0].read(cleartextMPIs, 0, cleartextMPIslength); - i += this.mpi[0].packetLength; - this.mpi[1] = new openpgp_type_mpi(); - this.mpi[1].read(cleartextMPIs, i, cleartextMPIslength-i); - i += this.mpi[1].packetLength; - this.mpi[2] = new openpgp_type_mpi(); - this.mpi[2].read(cleartextMPIs, i, cleartextMPIslength-i); - i += this.mpi[2].packetLength; - this.mpi[3] = new openpgp_type_mpi(); - this.mpi[3].read(cleartextMPIs, i, cleartextMPIslength-i); - i += this.mpi[3].packetLength; - } else if (this.publicKey.publicKeyAlgorithm == 16) { - // Algorithm-Specific Fields for Elgamal secret keys: - // - MPI of Elgamal secret exponent x. - this.mpi = new Array(); - this.mpi[0] = new openpgp_type_mpi(); - this.mpi[0].read(cleartextMPIs, 0, cleartextMPIs); - } else if (this.publicKey.publicKeyAlgorithm == 17) { - // Algorithm-Specific Fields for DSA secret keys: - // - MPI of DSA secret exponent x. - this.mpi = new Array(); - this.mpi[0] = new openpgp_type_mpi(); - this.mpi[0].read(cleartextMPIs, 0, cleartextMPIslength); - } - return true; + var mpis = openpgp_crypto_getPrivateMpiCount(this.public_key.algorithm); + + var j = 0; + for(var i = 0; i < mpis && j < cleartext.length; i++) { + this.mpi[i] = new openpgp_type_mpi(); + j += this.mpi[i].read(cleartext.substr(j)); + } } /** diff --git a/resources/openpgp.min.js b/resources/openpgp.min.js index 713d1169..1bb306d5 100644 --- a/resources/openpgp.min.js +++ b/resources/openpgp.min.js @@ -405,20 +405,16 @@ b[0].byteLength()));this.encrypted=openpgp_crypto_asymetricEncrypt(this.public_k function(){for(var b="5.1. Public-Key Encrypted Session Key Packets (Tag 1)\n KeyId: "+this.keyId.toString()+"\n length: "+this.packetLength+"\n version:"+this.version+"\n pubAlgUs:"+this.publicKeyAlgorithmUsed+"\n",a=0;athis.algorithm?2:16==this.algorithm?3:17==this.algorithm?4:0;this.mpi=[];for(var b=b.substr(6),c=0,d=0;db.length&&util.print_error("openpgp.packet.keymaterial.js\nerror reading MPI @:"+c);return c+6}util.print_error("Unknown packet version")}};this.write=function(){var b=String.fromCharCode(4),b=b+openpgp_packet_time_write(this.created),b=b+String.fromCharCode(this.algorithm),a;for(a in this.mpi)b+=this.mpi[a].write();return b}}function openpgp_packet_public_subkey(){openpgp_packet_public_key.call(this);this.tag=14} -function openpgp_packet_secret_key(){this.tag=5;this.public_key=new openpgp_packet_public_key;this.mpi=[];this.symmetric_algorithm=openpgp.symmetric.plaintext;this.iv=this.encrypted=this.s2k=null;this.read=function(b){var a=this.public_key.read(b),b=b.substr(a),c=b[0].charCodeAt(),a=1;if(255==c||254==c)this.symmetric_algorithm=b[a++].charCodeAt(),this.s2k=new openpgp_type_s2k,a+=this.s2k.read(b.substr(a));if(0!=c&&255!=c&&254!=c)this.symmetric_algorithm=c;if(0!=c&&1001!=this.s2k.type)this.iv=b.substr(a, -openpgp_crypto_getBlockLength(this.symmetric_algorithm)),a+=this.iv.length;if(0!=c&&1001==this.s2k.type)this.encrypted=this.mpi=null;else if(0!=c)this.encrypted=b.substr(a);else{c=openpgp_crypto_getPrivateMpiCount(this.public_key.algorithm);this.mpi=[];for(var d=0;dthis.publicKey.publicKeyAlgorithm){var c=0;this.mpi=[];this.mpi[0]=new openpgp_type_mpi;this.mpi[0].read(b,0,a);c+=this.mpi[0].packetLength;this.mpi[1]=new openpgp_type_mpi;this.mpi[1].read(b,c,a-c);c+=this.mpi[1].packetLength;this.mpi[2]=new openpgp_type_mpi;this.mpi[2].read(b,c,a-c);c+=this.mpi[2].packetLength;this.mpi[3]=new openpgp_type_mpi;this.mpi[3].read(b,c,a-c); -c+=this.mpi[3].packetLength}else if(16==this.publicKey.publicKeyAlgorithm)this.mpi=[],this.mpi[0]=new openpgp_type_mpi,this.mpi[0].read(b,0,b);else if(17==this.publicKey.publicKeyAlgorithm)this.mpi=[],this.mpi[0]=new openpgp_type_mpi,this.mpi[0].read(b,0,a);return!0}}}function openpgp_packet_secret_subkey(){openpgp_packet_secret_key.call(this);this.tag=7}function openpgp_packet_signature(){this.tag=2;this.write=function(){};this.read=function(){}} +function openpgp_packet_secret_key(){this.tag=5;this.public_key=new openpgp_packet_public_key;this.mpi=[];this.symmetric_algorithm=openpgp.symmetric.plaintext;this.hash_algorithm=openpgp.hash.sha1;this.iv=this.encrypted=this.s2k=null;this.read=function(b){var a=this.public_key.read(b),b=b.substr(a),c=b[0].charCodeAt(),a=1;if(255==c||254==c)this.symmetric_algorithm=b[a++].charCodeAt(),this.s2k=new openpgp_type_s2k,a+=this.s2k.read(b.substr(a));if(0!=c&&255!=c&&254!=c)this.symmetric_algorithm=c;if(0!= +c&&1001!=this.s2k.type)this.iv=b.substr(a,openpgp_crypto_getBlockLength(this.symmetric_algorithm)),a+=this.iv.length;this.hash_algorithm=254==c?openpgp.hash.sha1:"checksum";if(0!=c&&1001==this.s2k.type)this.encrypted=this.mpi=null;else if(0!=c)this.encrypted=b.substr(a);else{c=openpgp_crypto_getPrivateMpiCount(this.public_key.algorithm);this.mpi=[];for(var d=0;d>8*(a-d-1)&255);return c}function openpgp_packet_time_read(b){var b=openpgp_packet_number_read(b),a=new Date;a.setTime(1E3*b);return a} function openpgp_packet_time_write(b){b=Math.round(b.getTime()/1E3);return openpgp_packet_number_write(b,4)}function openpgp_packet_userid(){this.userid="";this.tag=13;this.read=function(b){this.userid=util.decode_utf8(b)};this.write=function(){return util.encode_utf8(this.userid)}} function openpgp_type_mpi(){this.data=null;this.read=function(b){var a=b[0].charCodeAt()<<8|b[1].charCodeAt(),a=Math.ceil(a/8);this.fromBytes(b.substr(2,a));return 2+a};this.fromBytes=function(b){this.data=new BigInteger(util.hexstrdump(b),16)};this.toBytes=function(){return this.write().substr(2)};this.byteLength=function(){return this.toBytes().length};this.write=function(){return this.data.toMPI()};this.toBigInteger=function(){return this.data.clone()};this.fromBigInteger=function(b){this.data= -b.clone()};this.toString=function(){var b=" MPI("+this.mpiBitLength+"b/"+this.mpiByteLength+"B) : 0x",b=b+util.hexstrdump(this.MPI);return b+"\n"}}function openpgp_type_keyid(){for(var b="",a=0;8>a;a++)b+=String.fromCharCode(0);this.read_packet=function(b,a){this.bytes=b.substring(a,a+8);return this};this.toString=function(){return util.hexstrdump(this.bytes)}} +b.clone()};this.toString=function(){var b=" MPI("+this.mpiBitLength+"b/"+this.mpiByteLength+"B) : 0x",b=b+util.hexstrdump(this.MPI);return b+"\n"}}function openpgp_type_keyid(){for(var b="",a=0;8>a;a++)b+=String.fromCharCode(0);this.read_packet=function(a,b){this.bytes=a.substring(b,b+8);return this};this.toString=function(){return util.hexstrdump(this.bytes)}} function openpgp_type_s2k(){this.read=function(b,a){var c=a;this.type=b[c++].charCodeAt();switch(this.type){case 0:this.hashAlgorithm=b[c++].charCodeAt();this.s2kLength=1;break;case 1:this.hashAlgorithm=b[c++].charCodeAt();this.saltValue=b.substring(c,c+8);c+=8;this.s2kLength=9;break;case 3:this.hashAlgorithm=b[c++].charCodeAt();this.saltValue=b.substring(c,c+8);c+=8;this.EXPBIAS=6;var d=b[c++].charCodeAt();this.count=16+(d&15)<<(d>>4)+this.EXPBIAS;this.s2kLength=10;break;case 101:"GNU"==b.substring(c+ 1,c+4)?(this.hashAlgorithm=b[c++].charCodeAt(),c+=3,d=1E3+b[c++].charCodeAt(),1001==d?(this.type=d,this.s2kLength=5):util.print_error("unknown s2k gnu protection mode! "+this.type)):util.print_error("unknown s2k type! "+this.type);break;default:util.print_error("unknown s2k type! "+this.type)}this.packetLength=c-a;return this};this.write=function(b,a,c,d,e){this.type=b;if(3==this.type)this.saltValue=d,this.hashAlgorithm=a,this.count=16+(e&15)<<(e>>4)+6,this.s2kLength=10;return this.produce_key(c)}; this.produce_key=function(b,a){var b=util.encode_utf8(b),c;if(0==this.type)c=openpgp_crypto_hashData(this.hashAlgorithm,b);else if(1==this.type)c=openpgp_crypto_hashData(this.hashAlgorithm,this.saltValue+b);else if(3==this.type){c=[];for(c[0]=this.saltValue+b;c.length*(this.saltValue+b).lengththis.count&&(c=c.substr(0,this.count));c=a&&(24==a||32==a)?openpgp_crypto_hashData(this.hashAlgorithm,c)+openpgp_crypto_hashData(this.hashAlgorithm, @@ -440,8 +436,8 @@ function openpgp_type_s2k(){this.algorithm=openpgp.hash.sha256;this.type=openpgp break;case c.gnu:"GNU"==b.substr(a,3)?(a+=3,b=1E3+b[a++].charCodeAt(),1001==b?this.type=b:util.print_error("unknown s2k gnu protection mode! "+this.type)):util.print_error("unknown s2k type! "+this.type);break;default:util.print_error("unknown s2k type! "+this.type)}return a};this.write=function(){var b=String.fromCharCode(this.type),b=b+String.fromCharCode(this.algorithm),a=openpgp_type_s2k.type;switch(this.type){case a.salted:b+=this.salt;break;case a.iterated:b+=this.salt,b+=String.fromCharCode(this.c)}return b}; this.produce_key=function(b,a){for(var b=util.encode_utf8(b),c="",d="";c.length<=a;){var e;a:{e=d;var f=openpgp_type_s2k.type;switch(this.type){case f.simple:e=openpgp_crypto_hashData(this.algorithm,e+b);break a;case f.salted:e=openpgp_crypto_hashData(this.algorithm,e+this.salt+b);break a;case f.iterated:var f=[],g=this.get_count();for(data=this.salt+b;f.length*data.lengthg&&(f=f.substr(0,g));e=openpgp_crypto_hashData(this.algorithm,e+f);break a}e=void 0}c+= e;d+=String.fromCharCode(0)}return c.substr(0,a)}}openpgp_type_s2k.type={simple:0,salted:1,iterated:3,gnu:101}; -var Util=function(){this.emailRegEx=/[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;this.debug=!1;this.hexdump=function(b){for(var a=[],e=b.length,f=0,g,h=0;fg.length;)g="0"+g;a.push(" "+g);h++;0==h%32&&a.push("\n ")}return a.join("")};this.hexstrdump=function(b){if(null==b)return"";for(var a=[],e=b.length,f=0,g;f -g.length;)g="0"+g;a.push(""+g)}return a.join("")};this.hex2bin=function(b){for(var a="",e=0;eg.length;)g="0"+g;a.push(""+g)}return a.join("")};this.encode_utf8=function(b){return unescape(encodeURIComponent(b))};this.decode_utf8=function(b){return decodeURIComponent(escape(b))};var b=function(b,a){for(var e=0;eg.length;)g="0"+g;b.push(" "+g);h++;0==h%32&&b.push("\n ")}return b.join("")};this.hexstrdump=function(a){if(null==a)return"";for(var b=[],e=a.length,f=0,g;f +g.length;)g="0"+g;b.push(""+g)}return b.join("")};this.hex2bin=function(a){for(var b="",e=0;eg.length;)g="0"+g;b.push(""+g)}return b.join("")};this.encode_utf8=function(a){return unescape(encodeURIComponent(a))};this.decode_utf8=function(a){return decodeURIComponent(escape(a))};var b=function(a,b){for(var e=0;e>=b%8,0 0 && this.publicKey.publicKeyAlgorithm < 4) { - // Algorithm-Specific Fields for RSA secret keys: - // - multiprecision integer (MPI) of RSA secret exponent d. - // - MPI of RSA secret prime value p. - // - MPI of RSA secret prime value q (p < q). - // - MPI of u, the multiplicative inverse of p, mod q. - var i = 0; - this.mpi = new Array(); - this.mpi[0] = new openpgp_type_mpi(); - this.mpi[0].read(cleartextMPIs, 0, cleartextMPIslength); - i += this.mpi[0].packetLength; - this.mpi[1] = new openpgp_type_mpi(); - this.mpi[1].read(cleartextMPIs, i, cleartextMPIslength-i); - i += this.mpi[1].packetLength; - this.mpi[2] = new openpgp_type_mpi(); - this.mpi[2].read(cleartextMPIs, i, cleartextMPIslength-i); - i += this.mpi[2].packetLength; - this.mpi[3] = new openpgp_type_mpi(); - this.mpi[3].read(cleartextMPIs, i, cleartextMPIslength-i); - i += this.mpi[3].packetLength; - } else if (this.publicKey.publicKeyAlgorithm == 16) { - // Algorithm-Specific Fields for Elgamal secret keys: - // - MPI of Elgamal secret exponent x. - this.mpi = new Array(); - this.mpi[0] = new openpgp_type_mpi(); - this.mpi[0].read(cleartextMPIs, 0, cleartextMPIs); - } else if (this.publicKey.publicKeyAlgorithm == 17) { - // Algorithm-Specific Fields for DSA secret keys: - // - MPI of DSA secret exponent x. - this.mpi = new Array(); - this.mpi[0] = new openpgp_type_mpi(); - this.mpi[0].read(cleartextMPIs, 0, cleartextMPIslength); - } - return true; + var mpis = openpgp_crypto_getPrivateMpiCount(this.public_key.algorithm); + + var j = 0; + for(var i = 0; i < mpis && j < cleartext.length; i++) { + this.mpi[i] = new openpgp_type_mpi(); + j += this.mpi[i].read(cleartext.substr(j)); + } } /** diff --git a/test/general/packet.js b/test/general/packet.js index 87c44bb3..a60d72a2 100644 --- a/test/general/packet.js +++ b/test/general/packet.js @@ -260,9 +260,72 @@ unittests.register("Packet testing", function() { }, function() { - + var armored_key = + '-----BEGIN PGP PRIVATE KEY BLOCK-----\n' + + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + + '\n' + + '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\n' + + 'YRlci72GHhlyos8YHA==\n' + + '=KXkj\n' + + '-----END PGP PRIVATE KEY BLOCK-----'; + + var armored_msg = + '-----BEGIN PGP MESSAGE-----\n' + + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + + '\n' + + 'hIwD95D9aHS5fxEBA/98CwH54XZmwobOmHUcvWcDDQysBEC4uf7wASiGcRbejDaO\n' + + 'aJqcrK/3k8sBQMO7yOhvrCRqqpGDqnmx7IaaKLnZS7nYAZoHEsK9UyG0hDa8Cfbo\n' + + 'CP4xZVcgIvIfAW/in1LeT2td0QcQNbeewBmPea+vQEEvRgIP10tlE7MK8Ay48dJH\n' + + 'AagMgNYg7MBUjpuOCVrjM1pWja8uzbULfYhTq3IJ8H3QhbdT+k9khY9f0aJPEeYi\n' + + 'dVv6DK9uviMGc/DsVCw5K8lQRLlkcHc=\n' + + '=pR+C\n' + + '-----END PGP MESSAGE-----'; + + var key = new openpgp_packetlist(); + key.read(openpgp_encoding_deArmor(armored_key).openpgp); + key = key[3]; + key.decrypt('test'); + + var msg = new openpgp_packetlist(); + msg.read(openpgp_encoding_deArmor(armored_msg).openpgp); + + msg[0].decrypt(key.public_key.mpi, key.mpi); + msg[1].decrypt(msg[0].symmetric_algorithm, msg[0].symmetric_key); + + var text = msg[1].packets[0].packets[0].data; + + + return new test_result('Secret key encryption/decryption test', - 'tello' == 'Hello world!'); + text == 'Hello world!'); }]; tests.reverse();