diff --git a/resources/openpgp.js b/resources/openpgp.js index a2b7467d..4d7d68ba 100644 --- a/resources/openpgp.js +++ b/resources/openpgp.js @@ -1495,9 +1495,11 @@ function openpgp_packet_userid() { this.verifyCertificationSignatures = verifyCertificationSignatures; this.verify = verify; this.read_packet = read_packet; + this.write_packet = write_packet; this.toString = toString; this.read_nodes = read_nodes; -}// GPG4Browsers - An OpenPGP implementation in javascript +} +// GPG4Browsers - An OpenPGP implementation in javascript // Copyright (C) 2011 Recurity Labs GmbH // // This library is free software; you can redistribute it and/or @@ -3305,17 +3307,80 @@ function openpgp_packet_keymaterial() { */ function getFingerprint() { if (this.version == 4) { - var tohash= this.header+this.data; - //if (this.tagType == 14) { - tohash = String.fromCharCode(0x99)+this.header.substring(1)+this.packetdata; - util.print_debug("openpgp.msg.publickey creating subkey fingerprint by hashing:"+util.hexstrdump(tohash)+"\npublickeyalgorithm: "+this.publicKeyAlgorithm); - //} + tohash = String.fromCharCode(0x99)+ String.fromCharCode(((this.packetdata.length) >> 8) & 0xFF) + + String.fromCharCode((this.packetdata.length) & 0xFF)+this.packetdata; + util.print_debug("openpgp.msg.publickey creating subkey fingerprint by hashing:"+util.hexstrdump(tohash)+"\npublickeyalgorithm: "+this.publicKeyAlgorithm); return str_sha1(tohash, tohash.length); } else if (this.version == 3 && this.publicKeyAlgorithm > 0 && this.publicKeyAlgorithm < 4) { return MD5(this.MPIs[0].MPI); } } + /* + * creates an OpenPGP key packet for the given key. much TODO in regards to s2k, subkeys. + * @param keyType [int] follows the OpenPGP algorithm standard, IE 1 corresponds to RSA. + * @param key [RSA.keyObject] + * @return {body: [string]OpenPGP packet body contents, header: [string] OpenPGP packet header, string: [string] header+body} + */ + function write_private_key(keyType, key){ + var tag = 5; + var body = String.fromCharCode(4); + //TODO make the date into a util function + var d = new Date(); + d = d.getTime()/1000; + body += String.fromCharCode(Math.floor(d/0x1000000%0x100)) + String.fromCharCode(Math.floor(d/0x10000%0x100)) + String.fromCharCode(Math.floor(d/0x100%0x100)) + String.fromCharCode(Math.floor(d%0x100)); + switch(keyType){ + case 1: + body += String.fromCharCode(1);//public key algo + body += key.n.toMPI(); + body += key.ee.toMPI(); + var algorithmStart = 6; //6 bits of extra info + //below shows ske/s2k TODO: currently disabled (no pw) + body += String.fromCharCode(0);//1 octet -- s2k, 0 for no s2k + //TODO: if s2k == 255,254 then 1 octet symmetric encryption algo + //TODO: if s2k == 255,254 then s2k specifier + //TODO if s2k, IV of same length as cipher's block + body += key.d.toMPI(); + body += key.p.toMPI(); + body += key.q.toMPI(); + body += key.coeff.toMPI(); + break; + default : + body = ""; + util.print_error("openpgp.packet.keymaterial.js\n"+'error writing private key, unknown type :'+keyType); + } + body += util.calc_checksum(body.substr(algorithmStart));//DEPRECATED:s2k == 0, 255: 2 octet checksum, sum all octets%65536 + var header = openpgp_packet.write_packet_header(tag,body.length); + return {string: header+body , header: header, body: body}; + } + + /* + * same as write_private_key, but has less information because of public key. + * @param keyType [int] follows the OpenPGP algorithm standard, IE 1 corresponds to RSA. + * @param key [RSA.keyObject] + * @return {body: [string]OpenPGP packet body contents, header: [string] OpenPGP packet header, string: [string] header+body} + */ + function write_public_key(keyType, key){ + var tag = 6; + var body = String.fromCharCode(4); + //TODO make the date into a util function + var d = new Date(); + d = d.getTime()/1000; + body += String.fromCharCode(Math.floor(d/0x1000000%0x100)) + String.fromCharCode(Math.floor(d/0x10000%0x100)) + String.fromCharCode(Math.floor(d/0x100%0x100)) + String.fromCharCode(Math.floor(d%0x100)); + switch(keyType){ + case 1: + body += String.fromCharCode(1);//public key algo + body += key.n.toMPI(); + body += key.ee.toMPI(); + break; + default: + 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.read_tag5 = read_tag5; this.read_tag6 = read_tag6; this.read_tag7 = read_tag7; @@ -3328,6 +3393,8 @@ function openpgp_packet_keymaterial() { this.verifyKey = verifyKey; this.getKeyId = getKeyId; this.getFingerprint = getFingerprint; + this.write_private_key = write_private_key; + this.write_public_key = write_public_key; } /* * md5.jvs 1.0b 27/06/96 @@ -7168,6 +7235,15 @@ function createTwofish() { // // RSA implementation +function SecureRandom(){ + function nextBytes(byteArray){ + for(var n = 0; n < byteArray.length;n++){ + byteArray[n] = openpgp_crypto_getSecureRandomOctet(); + } + } + this.nextBytes = nextBytes; +} + function RSA() { /** * This function uses jsbn Big Num library to decrypt RSA @@ -7218,12 +7294,64 @@ function RSA() { function verify(x,e,n) { return x.modPowInt(e, n); } + + // "empty" RSA key constructor + function keyObject() { + this.n = null; + this.e = 0; + this.ee = null; + this.d = null; + this.p = null; + this.q = null; + this.dmp1 = null; + this.dmq1 = null; + this.coeff = null; + } + + // Generate a new random private key B bits long, using public expt E + function generate(B,E) { + var key = new keyObject(); + var rng = new SecureRandom(); + var qs = B>>1; + key.e = parseInt(E,16); + key.ee = new BigInteger(E,16); + for(;;) { + for(;;) { + key.p = new BigInteger(B-qs,1,rng); + if(key.p.subtract(BigInteger.ONE).gcd(key.ee).compareTo(BigInteger.ONE) == 0 && key.p.isProbablePrime(10)) break; + } + for(;;) { + key.q = new BigInteger(qs,1,rng); + if(key.q.subtract(BigInteger.ONE).gcd(key.ee).compareTo(BigInteger.ONE) == 0 && key.q.isProbablePrime(10)) break; + } + if(key.p.compareTo(key.q) <= 0) { + var t = key.p; + key.p = key.q; + key.q = t; + } + var p1 = key.p.subtract(BigInteger.ONE); + var q1 = key.q.subtract(BigInteger.ONE); + var phi = p1.multiply(q1); + if(phi.gcd(key.ee).compareTo(BigInteger.ONE) == 0) { + key.n = key.p.multiply(key.q); + key.d = key.ee.modInverse(phi); + key.dmp1 = key.d.mod(p1); + key.dmq1 = key.d.mod(q1); + key.coeff = key.q.modInverse(key.p); + break; + } + } + return key; + } this.encrypt = encrypt; this.decrypt = decrypt; this.verify = verify; this.sign = sign; -}// GPG4Browsers - An OpenPGP implementation in javascript + this.generate = generate; + this.keyObject = keyObject; +} +// GPG4Browsers - An OpenPGP implementation in javascript // Copyright (C) 2011 Recurity Labs GmbH // // This library is free software; you can redistribute it and/or @@ -9457,6 +9585,29 @@ function openpgp_crypto_getRandomBigIntegerInRange(min, max) { } return min.add(r); } + + +/** + * calls the necessary crypto functions to generate a keypair. Called directly by openpgp.js + * @keyType [int] follows OpenPGP algorithm convention. + * @numBits [int] number of bits to make the key to be generated + * @return {privateKey: [openpgp_packet_keymaterial] , publicKey: [openpgp_packet_keymaterial]} + */ +function openpgp_crypto_generateKeyPair(keyType, numBits){ + var privKeyPacket; + var publicKeyPacket; + switch(keyType){ + case 1: + var rsa = new RSA(); + var key = rsa.generate(numBits,"10001"); + privKeyPacket = new openpgp_packet_keymaterial().write_private_key(1, key); + publicKeyPacket = new openpgp_packet_keymaterial().write_public_key(1, key); + break; + default: + util.print_error("Unknown keytype "+keyType) + } + return {privateKey: privKeyPacket, publicKey: publicKeyPacket}; +} // GPG4Browsers - An OpenPGP implementation in javascript // Copyright (C) 2011 Recurity Labs GmbH // @@ -9536,7 +9687,8 @@ function _openpgp () { } publicKeys[publicKeyCount].data = input.substring(0,mypos); publicKeyCount++; - } + } + debugger; return publicKeys; } @@ -9579,7 +9731,14 @@ function _openpgp () { * returns null */ function read_message(armoredText) { - var dearmored = openpgp_encoding_deArmor(armoredText.replace(/\r/g,'')); + var dearmored; + try{ + dearmored = openpgp_encoding_deArmor(armoredText.replace(/\r/g,'')); + } + catch(e){ + util.print_error('no message found!'); + return null; + } var input = dearmored.openpgp; var messages = new Array(); var messageCount = 0; @@ -9802,6 +9961,40 @@ function _openpgp () { return openpgp_encoding_armor(2,result, null, null) } + /** + * generates a new key pair for openpgp. Beta stage. Currently only supports RSA keys, and no subkeys. + * @param keyType [int] to indicate what type of key to make. RSA is 1. Follows algorithms outlined in OpenPGP. + * @param numBits [int] number of bits for the key creation. (should be 1024+, generally) + * @userId [string] assumes already in form of "User Name " + * @preferredHashAlgorithm [int] + * @return {privateKey: [openpgp_msg_privatekey], privateKeyArmored: [string], publicKeyArmored: [string]} + */ + function generate_key_pair(keyType, numBits, userId,preferredHashAlgorithm){ + var userIdPacket = new openpgp_packet_userid(); + var userIdString = userIdPacket.write_packet(userId); + + var keyPair = openpgp_crypto_generateKeyPair(keyType,numBits); + var privKeyString = keyPair.privateKey; + var privKeyPacket = new openpgp_packet_keymaterial().read_priv_key(privKeyString.string,3,privKeyString.string.length-3); + var privKey = new openpgp_msg_privatekey(); + privKey.privateKeyPacket = privKeyPacket; + privKey.getPreferredSignatureHashAlgorithm = function(){return preferredHashAlgorithm};//need to override this to solve catch 22 to generate signature. 8 is value for SHA256 + + var publicKeyString = privKey.privateKeyPacket.publicKey.data; + var hashData = String.fromCharCode(0x99)+ String.fromCharCode(((publicKeyString.length) >> 8) & 0xFF) + + String.fromCharCode((publicKeyString.length) & 0xFF) +publicKeyString+String.fromCharCode(0xB4) + + String.fromCharCode((userId.length) >> 24) +String.fromCharCode(((userId.length) >> 16) & 0xFF) + + String.fromCharCode(((userId.length) >> 8) & 0xFF) + String.fromCharCode((userId.length) & 0xFF) + userId + var signature = new openpgp_packet_signature(); + signature = signature.write_message_signature(16,hashData, privKey); + var publicArmored = openpgp_encoding_armor(4, keyPair.publicKey.string + userIdString + signature.openpgp ); + + var privArmored = openpgp_encoding_armor(5,privKeyString.string+userIdString+signature.openpgp); + + return {privateKey : privKey, privateKeyArmored: privArmored, publicKeyArmored: publicArmored} + } + + this.generate_key_pair = generate_key_pair; this.write_signed_message = write_signed_message; this.write_signed_and_encrypted_message = write_signed_and_encrypted_message; this.write_encrypted_message = write_encrypted_message; diff --git a/resources/openpgp.min.js b/resources/openpgp.min.js index cd24ea26..c6e8fe3b 100644 --- a/resources/openpgp.min.js +++ b/resources/openpgp.min.js @@ -40,11 +40,11 @@ a)return this.certificationRevocationSignatures[b];return null};this.verifyCerti d&&d.creationTime>this.certificationSignatures[b].creationTime){var e=String.fromCharCode(153)+a.header.substring(1)+a.data+String.fromCharCode(180)+String.fromCharCode(this.text.length>>24&255)+String.fromCharCode(this.text.length>>16&255)+String.fromCharCode(this.text.length>>8&255)+String.fromCharCode(this.text.length&255)+this.text;if(d.verify(e,c)){result[b]=this.certificationSignatures[b].issuerKeyId==a.getKeyId()?6:3;continue}}e=String.fromCharCode(153)+a.header.substring(1)+a.data+String.fromCharCode(180)+ String.fromCharCode(this.text.length>>24&255)+String.fromCharCode(this.text.length>>16&255)+String.fromCharCode(this.text.length>>8&255)+String.fromCharCode(this.text.length&255)+this.text;result[b]=this.certificationSignatures[b].verify(e,c)?4:0}}else if(3==this.certificationSignatures[b].version)if(null==this.certificationSignatures[b].keyId)result[b]=0;else if(c=openpgp.keyring.getPublicKeysForKeyId(this.certificationSignatures[b].keyId),null==c||0==c.length)result[b]=2;else if(c=publicKey.obj.getSigningKey(), null==c)result[b]=0;else{d=this.hasCertificationRevocationSignature(this.certificationSignatures[b].keyId);if(null!=d&&d.creationTime>this.certificationSignatures[b].creationTime&&(e=String.fromCharCode(153)+this.publicKeyPacket.header.substring(1)+this.publicKeyPacket.data+this.text,d.verify(e,c))){result[b]=d.keyId==a.getKeyId()?6:3;continue}e=String.fromCharCode(153)+a.header.substring(1)+a.data+this.text;result[b]=this.certificationSignatures[b].verify(e,c)?4:0}else result[b]=0;return result}; -this.verify=function(a){a=this.verifyCertificationSignatures(a);return-1!=a.indexOf(6)?2:-1!=a.indexOf(5)?1:0};this.read_packet=function(a,b,c){this.text="";this.packetLength=c;for(var d=0;dg.signatureType){this.certificationSignatures[this.certificationSignatures.length]=g;break}else if(48==g.signatureType){this.certificationRevocationSignatures[this.certificationRevocationSignatures.length]=g;break}else if(24==g.signatureType){this.certificationSignatures[this.certificationSignatures.length]=g;break}else util.debug("unknown sig t: "+g.signatureType+"@"+(e-(g.packetLength+g.headerLength)));default:return this.data=b,this.position=c-a.packetLength,this.len=e-c-(g.headerLength+g.packetLength)}}this.data= -b;this.position=c-a.packetLength;return this.len=e-c-(g.headerLength+g.packetLength)}if(5==a.tagType){this.parentNode=a;for(e=c;b.length!=e;)if(g=openpgp_packet.read_packet(b,e,f-(e-c)),null==g){util.print_error("parsing ends here @:"+e+" l:"+f);break}else switch(e+=g.packetLength+g.headerLength,g.tagType){case 2:15g.signatureType?this.certificationSignatures[this.certificationSignatures.length]=g:48==g.signatureType&&(this.certificationRevocationSignatures[this.certificationRevocationSignatures.length]= -g);default:return this.data=b,this.position=c-a.packetLength,this.len=e-c-(g.headerLength+g.packetLength)}}else util.print_error("unknown parent node for a userId packet "+a.tagType)}} +this.verify=function(a){a=this.verifyCertificationSignatures(a);return-1!=a.indexOf(6)?2:-1!=a.indexOf(5)?1:0};this.read_packet=function(a,b,c){this.text="";this.packetLength=c;for(var d=0;dg.signatureType){this.certificationSignatures[this.certificationSignatures.length]=g;break}else if(48==g.signatureType){this.certificationRevocationSignatures[this.certificationRevocationSignatures.length]=g;break}else if(24==g.signatureType){this.certificationSignatures[this.certificationSignatures.length]=g;break}else util.debug("unknown sig t: "+g.signatureType+"@"+(e-(g.packetLength+g.headerLength))); +default:return this.data=b,this.position=c-a.packetLength,this.len=e-c-(g.headerLength+g.packetLength)}}this.data=b;this.position=c-a.packetLength;return this.len=e-c-(g.headerLength+g.packetLength)}if(5==a.tagType){this.parentNode=a;for(e=c;b.length!=e;)if(g=openpgp_packet.read_packet(b,e,f-(e-c)),null==g){util.print_error("parsing ends here @:"+e+" l:"+f);break}else switch(e+=g.packetLength+g.headerLength,g.tagType){case 2:15g.signatureType?this.certificationSignatures[this.certificationSignatures.length]= +g:48==g.signatureType&&(this.certificationRevocationSignatures[this.certificationRevocationSignatures.length]=g);default:return this.data=b,this.position=c-a.packetLength,this.len=e-c-(g.headerLength+g.packetLength)}}else util.print_error("unknown parent node for a userId packet "+a.tagType)}} function openpgp_packet_encryptedsessionkey(){this.read_pub_key_packet=function(a,b,c){this.tagType=1;this.packetLength=c;var d=b;if(10>c)return util.print_error("openpgp.packet.encryptedsessionkey.js\ninvalid length"),null;this.version=a[d++].charCodeAt();this.keyId=new openpgp_type_keyid;this.keyId.read_packet(a,d);d+=8;this.publicKeyAlgorithmUsed=a[d++].charCodeAt();switch(this.publicKeyAlgorithmUsed){case 1:case 2:this.MPIs=[];this.MPIs[0]=new openpgp_type_mpi;this.MPIs[0].read(a,d,d-b);break; case 16:this.MPIs=[];this.MPIs[0]=new openpgp_type_mpi;this.MPIs[0].read(a,d,d-b);d+=this.MPIs[0].packetLength;this.MPIs[1]=new openpgp_type_mpi;this.MPIs[1].read(a,d,d-b);break;default:util.print_error("openpgp.packet.encryptedsessionkey.js\nunknown public key packet algorithm type "+this.publicKeyAlgorithmType)}return this};this.read_symmetric_key_packet=function(a,b,c){this.tagType=3;var d=b;this.version=a[d++];this.symmetricKeyAlgorithmUsed=a[d++];this.s2k=new openpgp_type_s2k;this.s2k.read(a, d);if(s2k.s2kLength+d>8&255),d=d+String.fromCharCode(e&255),f=f+a+String.fromCharCode(c),a=new openpgp_type_mpi,b=openpgp_crypto_asymetricEncrypt(c,b,a.create(openpgp_encoding_eme_pkcs1_encode(d,b[0].mpiByteLength))),c=0;cthis.publicKeyAlgorithm){var a=this.MPIs[0].substring(this.MPIs[0].mpiByteLength-8);util.print_debug("openpgp.msg.publickey read_nodes:\nV3 key ID: "+a);return a}};this.getFingerprint=function(){if(4==this.version){var a=this.header+this.data,a=String.fromCharCode(153)+ -this.header.substring(1)+this.packetdata;util.print_debug("openpgp.msg.publickey creating subkey fingerprint by hashing:"+util.hexstrdump(a)+"\npublickeyalgorithm: "+this.publicKeyAlgorithm);return str_sha1(a,a.length)}if(3==this.version&&0this.publicKeyAlgorithm)return MD5(this.MPIs[0].MPI)}} +this.header.substring(1)+this.packetdata),this.subKeyRevocationSignature[0].verify(a,this.parentNode)?2:0}return 3};this.getKeyId=function(){if(4==this.version)return this.getFingerprint().substring(12,20);if(3==this.version&&0this.publicKeyAlgorithm){var a=this.MPIs[0].substring(this.MPIs[0].mpiByteLength-8);util.print_debug("openpgp.msg.publickey read_nodes:\nV3 key ID: "+a);return a}};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(a,b){var c=String.fromCharCode(4),d=new Date,d=d.getTime()/1E3,c= +c+(String.fromCharCode(Math.floor(d/16777216%256))+String.fromCharCode(Math.floor(d/65536%256))+String.fromCharCode(Math.floor(d/256%256))+String.fromCharCode(Math.floor(d%256)));switch(a){case 1:var c=c+String.fromCharCode(1),c=c+b.n.toMPI(),c=c+b.ee.toMPI(),e=6,c=c+String.fromCharCode(0),c=c+b.d.toMPI(),c=c+b.p.toMPI(),c=c+b.q.toMPI(),c=c+b.coeff.toMPI();break;default:c="",util.print_error("openpgp.packet.keymaterial.js\nerror writing private key, unknown type :"+a)}c+=util.calc_checksum(c.substr(e)); +d=openpgp_packet.write_packet_header(5,c.length);return{string:d+c,header:d,body:c}};this.write_public_key=function(a,b){var c=String.fromCharCode(4),d=new Date,d=d.getTime()/1E3,c=c+(String.fromCharCode(Math.floor(d/16777216%256))+String.fromCharCode(Math.floor(d/65536%256))+String.fromCharCode(Math.floor(d/256%256))+String.fromCharCode(Math.floor(d%256)));switch(a){case 1:c+=String.fromCharCode(1);c+=b.n.toMPI();c+=b.ee.toMPI();break;default:util.print_error("openpgp.packet.keymaterial.js\nerror writing private key, unknown type :"+ +a)}d=openpgp_packet.write_packet_header(6,c.length);return{string:d+c,header:d,body:c}}} function MD5(a){function b(a){for(i=0;i>b)+(1073741824>>b-1):a>>b}function e(a,b){for(var a=c(a),b=c(b),d=0;dy[0]||(y[1]++,y[0]-=4294967296);y[0]+=8;z[b]=f(a,255);if(63<=b){var a=z,c=b=0,g=0,h=0,k=v;b=x[0];c=x[1];g=x[2];h=x[3];for(i=0;16>i;i++){k[i]=f(a[4*i+0],255);for(j=1;4>j;j++)k[i]+=e(f(a[4*i+j+0],255),8*j)}b=m(b,c,g,h,k[0],N,3614090360);h=m(h,b,c,g,k[1],M,3905402710);g=m(g,h,b,c,k[2],D,606105819);c=m(c,g,h,b,k[3],K,3250441966);b=m(b,c,g,h,k[4],N,4118548399);h=m(h,b,c,g,k[5],M,1200080426); @@ -277,9 +280,10 @@ e];c=N[a][K[e]^E[c]];return D[a][K[c]^E[f]]<<4|M[a][f^c]}function e(a,b){var c=g x[a+a],q[a]=o,r=x[a+a+1],s[a]=r,z[y-a-1]=b(o,r);for(a=0;40>a;a+=2)o=16843009*a,r=o+16843009,o=e(o,q),r=rotw(e(r,s),8),f[a]=o+r&MAXINT,f[a+1]=rotw(o+2*r,9);for(a=0;256>a;a++)switch(o=r=q=s=a,y){case 4:o=w[1][o]^getB(z[3],0),r=w[0][r]^getB(z[3],1),q=w[0][q]^getB(z[3],2),s=w[1][s]^getB(z[3],3);case 3:o=w[1][o]^getB(z[2],0),r=w[1][r]^getB(z[2],1),q=w[0][q]^getB(z[2],2),s=w[0][s]^getB(z[2],3);case 2:g[0][a]=A[0][w[0][w[0][o]^getB(z[1],0)]^getB(z[0],0)],g[1][a]=A[1][w[0][w[1][r]^getB(z[1],1)]^getB(z[0], 1)],g[2][a]=A[2][w[1][w[0][q]^getB(z[1],2)]^getB(z[0],2)],g[3][a]=A[3][w[1][w[1][s]^getB(z[1],3)]^getB(z[0],3)]}},close:function(){f=[];g=[[],[],[],[]]},encrypt:function(c,g){d=c;e=g;for(var l=[getW(d,e)^f[0],getW(d,e+4)^f[1],getW(d,e+8)^f[2],getW(d,e+12)^f[3]],m=0;8>m;m++){var o=m,r=l,q=a(r[0]),s=b(r[1]);r[2]=rotw(r[2]^q+s+f[4*o+8]&MAXINT,31);r[3]=rotw(r[3],1)^q+2*s+f[4*o+9]&MAXINT;q=a(r[2]);s=b(r[3]);r[0]=rotw(r[0]^q+s+f[4*o+10]&MAXINT,31);r[1]=rotw(r[1],1)^q+2*s+f[4*o+11]&MAXINT}setW(d,e,l[2]^ f[4]);setW(d,e+4,l[3]^f[5]);setW(d,e+8,l[0]^f[6]);setW(d,e+12,l[1]^f[7]);e+=16;return d},decrypt:function(c,g){d=c;e=g;for(var l=[getW(d,e)^f[4],getW(d,e+4)^f[5],getW(d,e+8)^f[6],getW(d,e+12)^f[7]],m=7;0<=m;m--){var o=m,r=l,q=a(r[0]),s=b(r[1]);r[2]=rotw(r[2],1)^q+s+f[4*o+10]&MAXINT;r[3]=rotw(r[3]^q+2*s+f[4*o+11]&MAXINT,31);q=a(r[2]);s=b(r[3]);r[0]=rotw(r[0],1)^q+s+f[4*o+8]&MAXINT;r[1]=rotw(r[1]^q+2*s+f[4*o+9]&MAXINT,31)}setW(d,e,l[2]^f[0]);setW(d,e+4,l[3]^f[1]);setW(d,e+8,l[0]^f[2]);setW(d,e+12,l[1]^ -f[3]);e+=16},finalize:function(){return d}}} -function RSA(){this.encrypt=function(a,b,c){return a.modPowInt(b,c)};this.decrypt=function(a,b,c,d,e){var f=a.mod(c).modPow(b.mod(c.subtract(BigInteger.ONE)),c),a=a.mod(d).modPow(b.mod(d.subtract(BigInteger.ONE)),d);util.print_debug("rsa.js decrypt\nxpn:"+util.hexstrdump(f.toMPI())+"\nxqn:"+util.hexstrdump(a.toMPI()));b=a.subtract(f);0==b[0]?(b=f.subtract(a),b=b.multiply(e).mod(d),b=d.subtract(b)):b=b.multiply(e).mod(d);return b.multiply(c).add(f)};this.verify=function(a,b,c){return a.modPowInt(b, -c)};this.sign=function(a,b,c){return a.modPow(b,c)}} +f[3]);e+=16},finalize:function(){return d}}}function SecureRandom(){this.nextBytes=function(a){for(var b=0;b>1;d.e=parseInt(c,16);for(d.ee=new BigInteger(c,16);;){for(;!(d.p=new BigInteger(b-f,1,e),0==d.p.subtract(BigInteger.ONE).gcd(d.ee).compareTo(BigInteger.ONE)&&d.p.isProbablePrime(10)););for(;!(d.q=new BigInteger(f,1,e),0==d.q.subtract(BigInteger.ONE).gcd(d.ee).compareTo(BigInteger.ONE)&& +d.q.isProbablePrime(10)););if(0>=d.p.compareTo(d.q)){var g=d.p;d.p=d.q;d.q=g}var g=d.p.subtract(BigInteger.ONE),h=d.q.subtract(BigInteger.ONE),k=g.multiply(h);if(0==k.gcd(d.ee).compareTo(BigInteger.ONE)){d.n=d.p.multiply(d.q);d.d=d.ee.modInverse(k);d.dmp1=d.d.mod(g);d.dmq1=d.d.mod(h);d.coeff=d.q.modInverse(d.p);break}}return d};this.keyObject=a} function DSA(){this.select_hash_algorithm=function(a){var b=openpgp.config.config.prefer_hash_algorithm;switch(Math.round(a.bitLength()/8)){case 20:return 2!=b&&11b?2:b;case 28:return 11b?11:b;case 32:return 10b?8:b;default:return util.print_debug("DSA select hash algorithm: returning null for an unknown length of q"),null}};this.sign=function(a,b,c,d,e,f){a=util.getLeftNBits(openpgp_crypto_hashData(a,b),e.bitLength());a=new BigInteger(util.hexstrdump(a),16);b=openpgp_crypto_getRandomBigIntegerInRange(BigInteger.ONE.add(BigInteger.ONE), e.subtract(BigInteger.ONE));c=c.modPow(b,d).mod(e);e=b.modInverse(e).multiply(a.add(f.multiply(c))).mod(e);f=[];f[0]=c.toMPI();f[1]=e.toMPI();return f};this.verify=function(a,b,c,d,e,f,g,h){a=util.getLeftNBits(openpgp_crypto_hashData(a,d),f.bitLength());a=new BigInteger(util.hexstrdump(a),16);if(0b-a;)window.crypto.getRandomValues(c);return a+Math.abs(c[0]&Math.pow(2,d)-1)}function openpgp_crypto_getSecureRandomOctet(){var a=new Uint32Array(1);window.crypto.getRandomValues(a);return a[0]&255} function openpgp_crypto_getRandomBigInteger(a){if(0>a)return null;var b=openpgp_crypto_getRandomBytes(Math.floor((a+7)/8));0=b.compareTo(a))){for(var c=b.subtract(a),d=openpgp_crypto_getRandomBigInteger(c.bitLength());d>c;)d=openpgp_crypto_getRandomBigInteger(c.bitLength());return a.add(d)}} -function _openpgp(){this.tostring="";this.write_signed_message=function(a,b){var c=(new openpgp_packet_signature).write_message_signature(1,b.replace(/\r\n/g,"\n").replace(/\n/,"\r\n"),a),c={text:b.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(a,b,c){var d="",e=(new openpgp_packet_literaldata).write_packet(c.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"));util.print_debug("literal_packet: |"+ -e+"|\n"+util.hexstrdump(e));for(var f=0;fg.signatureType||3==g.tagType||8==g.tagType||9==g.tagType||10==g.tagType||11==g.tagType||18==g.tagType||19==g.tagType)if(c[c.length]=new openpgp_msg_message,c[d].messagePacket=g,c[d].type=a.type,9==g.tagType||1==g.tagType||3==g.tagType||18==g.tagType)if(9==g.tagType){util.print_error("unexpected openpgp packet"); -break}else if(1==g.tagType){util.print_debug("session key found:\n "+g.toString());var h=!0;c[d].sessionKeys=[];for(var k=0;h;)c[d].sessionKeys[k]=g,e+=g.packetLength+g.headerLength,f-=g.packetLength+g.headerLength,g=openpgp_packet.read_packet(b,e,f),1!=g.tagType&&3!=g.tagType&&(h=!1),k++;18==g.tagType||9==g.tagType?(util.print_debug("encrypted data found:\n "+g.toString()),c[d].encryptedData=g,e+=g.packetLength+g.headerLength,f-=g.packetLength+g.headerLength,d++):util.print_debug("something is wrong: "+ -g.tagType)}else{if(18==g.tagType){util.print_debug("symmetric encrypted data");break}}else if(2==g.tagType&&3>g.signatureType){c[d].text=a.text;c[d].signature=g;break}else if(8==g.tagType){util.print_error("A directly compressed message is currently not supported");break}else{if(11==g.tagType){util.print_error("A direct literal message is currently not supported.");break}}else return util.print_error("no message found!"),null}return c};this.read_publicKey=function(a){for(var b=0,c=[],d=0,a=openpgp_encoding_deArmor(a.replace(/\r/g, -"")).openpgp,e=a.length;b!=a.length;){var f=openpgp_packet.read_packet(a,b,e);if(153==a[b].charCodeAt()||6==f.tagType)c[d]=new openpgp_msg_publickey,c[d].header=a.substring(b,b+3),153==a[b].charCodeAt()?(b++,e=a[b++].charCodeAt()<<8|a[b++].charCodeAt(),c[d].publicKeyPacket=new openpgp_packet_keymaterial,c[d].publicKeyPacket.header=c[d].header,c[d].publicKeyPacket.read_tag6(a,b,e),b+=c[d].publicKeyPacket.packetLength,b+=c[d].read_nodes(c[d].publicKeyPacket,a,b,a.length-b)):(c[c.length]=new openpgp_msg_publickey, -c[d].publicKeyPacket=f,b+=f.headerLength+f.packetLength,b+=c[d].read_nodes(f,a,b,a.length-b));else return util.print_error("no public key found!"),null;c[d].data=a.substring(0,b);d++}return c};this.read_privateKey=function(a){for(var b=[],c=0,d=0,a=openpgp_encoding_deArmor(a.replace(/\r/g,"")).openpgp,e=a.length;d!=a.length;){var f=openpgp_packet.read_packet(a,d,e);if(5==f.tagType)b[b.length]=new openpgp_msg_privatekey,d+=f.headerLength+f.packetLength,d+=b[c].read_nodes(f,a,d,e);else return util.print_error("no block packet found!"), +function openpgp_crypto_generateKeyPair(a,b){var c,d;switch(a){case 1:d=(new RSA).generate(b,"10001");c=(new openpgp_packet_keymaterial).write_private_key(1,d);d=(new openpgp_packet_keymaterial).write_public_key(1,d);break;default:util.print_error("Unknown keytype "+a)}return{privateKey:c,publicKey:d}} +function _openpgp(){this.tostring="";this.generate_key_pair=function(a,b,c,d){var e=(new openpgp_packet_userid).write_packet(c),f=openpgp_crypto_generateKeyPair(a,b),b=f.privateKey,g=(new openpgp_packet_keymaterial).read_priv_key(b.string,3,b.string.length-3),a=new openpgp_msg_privatekey;a.privateKeyPacket=g;a.getPreferredSignatureHashAlgorithm=function(){return d};g=a.privateKeyPacket.publicKey.data;g=String.fromCharCode(153)+String.fromCharCode(g.length>>8&255)+String.fromCharCode(g.length&255)+ +g+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,g,a);f=openpgp_encoding_armor(4,f.publicKey.string+e+c.openpgp);e=openpgp_encoding_armor(5,b.string+e+c.openpgp);return{privateKey:a,privateKeyArmored:e,publicKeyArmored:f}};this.write_signed_message=function(a,b){var c=(new openpgp_packet_signature).write_message_signature(1, +b.replace(/\r\n/g,"\n").replace(/\n/,"\r\n"),a),c={text:b.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(a,b,c){var d="",e=(new openpgp_packet_literaldata).write_packet(c.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"));util.print_debug("literal_packet: |"+e+"|\n"+util.hexstrdump(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=b.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 l=0;k;)d[e].sessionKeys[l]=h,f+=h.packetLength+h.headerLength,g-=h.packetLength+h.headerLength,h=openpgp_packet.read_packet(a,f,g),1!=h.tagType&&3!=h.tagType&&(k=!1),l++;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=b.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(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(a){for(var b=0,c=[],d=0,a=openpgp_encoding_deArmor(a.replace(/\r/g,"")).openpgp,e=a.length;b!=a.length;){var f= +openpgp_packet.read_packet(a,b,e);if(153==a[b].charCodeAt()||6==f.tagType)c[d]=new openpgp_msg_publickey,c[d].header=a.substring(b,b+3),153==a[b].charCodeAt()?(b++,e=a[b++].charCodeAt()<<8|a[b++].charCodeAt(),c[d].publicKeyPacket=new openpgp_packet_keymaterial,c[d].publicKeyPacket.header=c[d].header,c[d].publicKeyPacket.read_tag6(a,b,e),b+=c[d].publicKeyPacket.packetLength,b+=c[d].read_nodes(c[d].publicKeyPacket,a,b,a.length-b)):(c[c.length]=new openpgp_msg_publickey,c[d].publicKeyPacket=f,b+=f.headerLength+ +f.packetLength,b+=c[d].read_nodes(f,a,b,a.length-b));else return util.print_error("no public key found!"),null;c[d].data=a.substring(0,b);d++}debugger;return c};this.read_privateKey=function(a){for(var b=[],c=0,d=0,a=openpgp_encoding_deArmor(a.replace(/\r/g,"")).openpgp,e=a.length;d!=a.length;){var f=openpgp_packet.read_packet(a,d,e);if(5==f.tagType)b[b.length]=new openpgp_msg_privatekey,d+=f.headerLength+f.packetLength,d+=b[c].read_nodes(f,a,d,e);else return util.print_error("no block packet found!"), null;b[c].data=a.substring(0,d);c++}return b};this.init=function(){this.config=new openpgp_config;this.config.read();this.keyring=new openpgp_keyring;this.keyring.init()}}var openpgp=new _openpgp; 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 a=[],b=0;b>1; + key.e = parseInt(E,16); + key.ee = new BigInteger(E,16); + for(;;) { + for(;;) { + key.p = new BigInteger(B-qs,1,rng); + if(key.p.subtract(BigInteger.ONE).gcd(key.ee).compareTo(BigInteger.ONE) == 0 && key.p.isProbablePrime(10)) break; + } + for(;;) { + key.q = new BigInteger(qs,1,rng); + if(key.q.subtract(BigInteger.ONE).gcd(key.ee).compareTo(BigInteger.ONE) == 0 && key.q.isProbablePrime(10)) break; + } + if(key.p.compareTo(key.q) <= 0) { + var t = key.p; + key.p = key.q; + key.q = t; + } + var p1 = key.p.subtract(BigInteger.ONE); + var q1 = key.q.subtract(BigInteger.ONE); + var phi = p1.multiply(q1); + if(phi.gcd(key.ee).compareTo(BigInteger.ONE) == 0) { + key.n = key.p.multiply(key.q); + key.d = key.ee.modInverse(phi); + key.dmp1 = key.d.mod(p1); + key.dmq1 = key.d.mod(q1); + key.coeff = key.q.modInverse(key.p); + break; + } + } + return key; + } this.encrypt = encrypt; this.decrypt = decrypt; this.verify = verify; this.sign = sign; -} \ No newline at end of file + this.generate = generate; + this.keyObject = keyObject; +} diff --git a/src/ciphers/openpgp.crypto.js b/src/ciphers/openpgp.crypto.js index b9619d03..bcb0241a 100644 --- a/src/ciphers/openpgp.crypto.js +++ b/src/ciphers/openpgp.crypto.js @@ -456,3 +456,26 @@ function openpgp_crypto_getRandomBigIntegerInRange(min, max) { } return min.add(r); } + + +/** + * calls the necessary crypto functions to generate a keypair. Called directly by openpgp.js + * @keyType [int] follows OpenPGP algorithm convention. + * @numBits [int] number of bits to make the key to be generated + * @return {privateKey: [openpgp_packet_keymaterial] , publicKey: [openpgp_packet_keymaterial]} + */ +function openpgp_crypto_generateKeyPair(keyType, numBits){ + var privKeyPacket; + var publicKeyPacket; + switch(keyType){ + case 1: + var rsa = new RSA(); + var key = rsa.generate(numBits,"10001"); + privKeyPacket = new openpgp_packet_keymaterial().write_private_key(1, key); + publicKeyPacket = new openpgp_packet_keymaterial().write_public_key(1, key); + break; + default: + util.print_error("Unknown keytype "+keyType) + } + return {privateKey: privKeyPacket, publicKey: publicKeyPacket}; +} diff --git a/src/openpgp.js b/src/openpgp.js index 080ca1f7..7b026056 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -77,7 +77,8 @@ function _openpgp () { } publicKeys[publicKeyCount].data = input.substring(0,mypos); publicKeyCount++; - } + } + debugger; return publicKeys; } @@ -120,7 +121,14 @@ function _openpgp () { * returns null */ function read_message(armoredText) { - var dearmored = openpgp_encoding_deArmor(armoredText.replace(/\r/g,'')); + var dearmored; + try{ + dearmored = openpgp_encoding_deArmor(armoredText.replace(/\r/g,'')); + } + catch(e){ + util.print_error('no message found!'); + return null; + } var input = dearmored.openpgp; var messages = new Array(); var messageCount = 0; @@ -343,6 +351,40 @@ function _openpgp () { return openpgp_encoding_armor(2,result, null, null) } + /** + * generates a new key pair for openpgp. Beta stage. Currently only supports RSA keys, and no subkeys. + * @param keyType [int] to indicate what type of key to make. RSA is 1. Follows algorithms outlined in OpenPGP. + * @param numBits [int] number of bits for the key creation. (should be 1024+, generally) + * @userId [string] assumes already in form of "User Name " + * @preferredHashAlgorithm [int] + * @return {privateKey: [openpgp_msg_privatekey], privateKeyArmored: [string], publicKeyArmored: [string]} + */ + function generate_key_pair(keyType, numBits, userId,preferredHashAlgorithm){ + var userIdPacket = new openpgp_packet_userid(); + var userIdString = userIdPacket.write_packet(userId); + + var keyPair = openpgp_crypto_generateKeyPair(keyType,numBits); + var privKeyString = keyPair.privateKey; + var privKeyPacket = new openpgp_packet_keymaterial().read_priv_key(privKeyString.string,3,privKeyString.string.length-3); + var privKey = new openpgp_msg_privatekey(); + privKey.privateKeyPacket = privKeyPacket; + privKey.getPreferredSignatureHashAlgorithm = function(){return preferredHashAlgorithm};//need to override this to solve catch 22 to generate signature. 8 is value for SHA256 + + var publicKeyString = privKey.privateKeyPacket.publicKey.data; + var hashData = String.fromCharCode(0x99)+ String.fromCharCode(((publicKeyString.length) >> 8) & 0xFF) + + String.fromCharCode((publicKeyString.length) & 0xFF) +publicKeyString+String.fromCharCode(0xB4) + + String.fromCharCode((userId.length) >> 24) +String.fromCharCode(((userId.length) >> 16) & 0xFF) + + String.fromCharCode(((userId.length) >> 8) & 0xFF) + String.fromCharCode((userId.length) & 0xFF) + userId + var signature = new openpgp_packet_signature(); + signature = signature.write_message_signature(16,hashData, privKey); + var publicArmored = openpgp_encoding_armor(4, keyPair.publicKey.string + userIdString + signature.openpgp ); + + var privArmored = openpgp_encoding_armor(5,privKeyString.string+userIdString+signature.openpgp); + + return {privateKey : privKey, privateKeyArmored: privArmored, publicKeyArmored: publicArmored} + } + + this.generate_key_pair = generate_key_pair; this.write_signed_message = write_signed_message; this.write_signed_and_encrypted_message = write_signed_and_encrypted_message; this.write_encrypted_message = write_encrypted_message; diff --git a/src/packet/openpgp.packet.keymaterial.js b/src/packet/openpgp.packet.keymaterial.js index 596d9740..28431daa 100644 --- a/src/packet/openpgp.packet.keymaterial.js +++ b/src/packet/openpgp.packet.keymaterial.js @@ -663,17 +663,80 @@ function openpgp_packet_keymaterial() { */ function getFingerprint() { if (this.version == 4) { - var tohash= this.header+this.data; - //if (this.tagType == 14) { - tohash = String.fromCharCode(0x99)+this.header.substring(1)+this.packetdata; - util.print_debug("openpgp.msg.publickey creating subkey fingerprint by hashing:"+util.hexstrdump(tohash)+"\npublickeyalgorithm: "+this.publicKeyAlgorithm); - //} + tohash = String.fromCharCode(0x99)+ String.fromCharCode(((this.packetdata.length) >> 8) & 0xFF) + + String.fromCharCode((this.packetdata.length) & 0xFF)+this.packetdata; + util.print_debug("openpgp.msg.publickey creating subkey fingerprint by hashing:"+util.hexstrdump(tohash)+"\npublickeyalgorithm: "+this.publicKeyAlgorithm); return str_sha1(tohash, tohash.length); } else if (this.version == 3 && this.publicKeyAlgorithm > 0 && this.publicKeyAlgorithm < 4) { return MD5(this.MPIs[0].MPI); } } + /* + * creates an OpenPGP key packet for the given key. much TODO in regards to s2k, subkeys. + * @param keyType [int] follows the OpenPGP algorithm standard, IE 1 corresponds to RSA. + * @param key [RSA.keyObject] + * @return {body: [string]OpenPGP packet body contents, header: [string] OpenPGP packet header, string: [string] header+body} + */ + function write_private_key(keyType, key){ + var tag = 5; + var body = String.fromCharCode(4); + //TODO make the date into a util function + var d = new Date(); + d = d.getTime()/1000; + body += String.fromCharCode(Math.floor(d/0x1000000%0x100)) + String.fromCharCode(Math.floor(d/0x10000%0x100)) + String.fromCharCode(Math.floor(d/0x100%0x100)) + String.fromCharCode(Math.floor(d%0x100)); + switch(keyType){ + case 1: + body += String.fromCharCode(1);//public key algo + body += key.n.toMPI(); + body += key.ee.toMPI(); + var algorithmStart = 6; //6 bits of extra info + //below shows ske/s2k TODO: currently disabled (no pw) + body += String.fromCharCode(0);//1 octet -- s2k, 0 for no s2k + //TODO: if s2k == 255,254 then 1 octet symmetric encryption algo + //TODO: if s2k == 255,254 then s2k specifier + //TODO if s2k, IV of same length as cipher's block + body += key.d.toMPI(); + body += key.p.toMPI(); + body += key.q.toMPI(); + body += key.coeff.toMPI(); + break; + default : + body = ""; + util.print_error("openpgp.packet.keymaterial.js\n"+'error writing private key, unknown type :'+keyType); + } + body += util.calc_checksum(body.substr(algorithmStart));//DEPRECATED:s2k == 0, 255: 2 octet checksum, sum all octets%65536 + var header = openpgp_packet.write_packet_header(tag,body.length); + return {string: header+body , header: header, body: body}; + } + + /* + * same as write_private_key, but has less information because of public key. + * @param keyType [int] follows the OpenPGP algorithm standard, IE 1 corresponds to RSA. + * @param key [RSA.keyObject] + * @return {body: [string]OpenPGP packet body contents, header: [string] OpenPGP packet header, string: [string] header+body} + */ + function write_public_key(keyType, key){ + var tag = 6; + var body = String.fromCharCode(4); + //TODO make the date into a util function + var d = new Date(); + d = d.getTime()/1000; + body += String.fromCharCode(Math.floor(d/0x1000000%0x100)) + String.fromCharCode(Math.floor(d/0x10000%0x100)) + String.fromCharCode(Math.floor(d/0x100%0x100)) + String.fromCharCode(Math.floor(d%0x100)); + switch(keyType){ + case 1: + body += String.fromCharCode(1);//public key algo + body += key.n.toMPI(); + body += key.ee.toMPI(); + break; + default: + 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.read_tag5 = read_tag5; this.read_tag6 = read_tag6; this.read_tag7 = read_tag7; @@ -686,4 +749,6 @@ function openpgp_packet_keymaterial() { this.verifyKey = verifyKey; this.getKeyId = getKeyId; this.getFingerprint = getFingerprint; + this.write_private_key = write_private_key; + this.write_public_key = write_public_key; } diff --git a/src/packet/openpgp.packet.signature.js b/src/packet/openpgp.packet.signature.js index 053bd3e9..744d2859 100644 --- a/src/packet/openpgp.packet.signature.js +++ b/src/packet/openpgp.packet.signature.js @@ -455,8 +455,8 @@ function openpgp_packet_signature() { case 108: // Private or experimental case 109: // Private or experimental case 110: // Private or experimental - return subplen+1; util.print_error("openpgp.packet.signature.js\n"+'private or experimental signature subpacket type '+type+" @:"+mypos+" subplen:"+subplen+" len:"+len); + return subplen+1; break; case 0: // Reserved case 1: // Reserved @@ -752,4 +752,4 @@ function openpgp_packet_signature() { this.verify = verify; this.read_packet = read_packet; this.toString = toString; -} \ No newline at end of file +} diff --git a/src/packet/openpgp.packet.userid.js b/src/packet/openpgp.packet.userid.js index 49025e3b..a7e347f5 100644 --- a/src/packet/openpgp.packet.userid.js +++ b/src/packet/openpgp.packet.userid.js @@ -328,6 +328,7 @@ function openpgp_packet_userid() { this.verifyCertificationSignatures = verifyCertificationSignatures; this.verify = verify; this.read_packet = read_packet; + this.write_packet = write_packet; this.toString = toString; this.read_nodes = read_nodes; -} \ No newline at end of file +}