diff --git a/resources/openpgp.js b/resources/openpgp.js
index a060ca84..539d4754 100644
--- a/resources/openpgp.js
+++ b/resources/openpgp.js
@@ -3925,7 +3925,7 @@ function openpgp_crypto_verifySignature(algo, hash_algo, msg_MPIs, publickey_MPI
* @param {openpgp_type_mpi[]} secretMPIs Private key multiprecision
* integers which is used to sign the data
* @param {String} data Data to be signed
- * @return {(String|openpgp_type_mpi)}
+ * @return {openpgp_type_mpi[]}
*/
function openpgp_crypto_signData(hash_algo, algo, publicMPIs, secretMPIs, data) {
@@ -3936,7 +3936,7 @@ function openpgp_crypto_signData(hash_algo, algo, publicMPIs, secretMPIs, data)
var rsa = new RSA();
var d = secretMPIs[0].toBigInteger();
var n = publicMPIs[0].toBigInteger();
- var m = openpgp_encoding_emsa_pkcs1_encode(hash_algo, data,publicMPIs[0].mpiByteLength);
+ var m = openpgp_encoding_emsa_pkcs1_encode(hash_algo, data,publicMPIs[0].byteLength());
util.print_debug("signing using RSA");
return rsa.sign(m, d, n).toMPI();
case 17: // DSA (Digital Signature Algorithm) [FIPS186] [HAC]
@@ -3950,7 +3950,7 @@ function openpgp_crypto_signData(hash_algo, algo, publicMPIs, secretMPIs, data)
var m = data;
var result = dsa.sign(hash_algo,m, g, p, q, x);
util.print_debug("signing using DSA\n result:"+util.hexstrdump(result[0])+"|"+util.hexstrdump(result[1]));
- return result[0]+result[1];
+ return result[0].toString() + result[1].toString();
case 16: // Elgamal (Encrypt-Only) [ELGAMAL] [HAC]
util.print_debug("signing with Elgamal is not defined in the OpenPGP standard.");
return null;
@@ -10917,15 +10917,19 @@ function openpgp_packet_secret_subkey() {
*/
function openpgp_packet_signature() {
this.tag = 2;
+
this.signatureType = null;
- this.created = null;
+ this.hashAlgorithm = null;
+ this.publicKeyAlgorithm = null;
+ this.version = 4;
+
this.signatureData = null;
- this.signatureExpirationTime = null;
- this.signatureNeverExpires = null;
this.signedHashValue = null;
this.mpi = null;
- this.publicKeyAlgorithm = null;
- this.hashAlgorithm = null;
+
+ this.created = null;
+ this.signatureExpirationTime = null;
+ this.signatureNeverExpires = null;
this.exportable = null;
this.trustLevel = null;
this.trustAmount = null;
@@ -10953,6 +10957,7 @@ function openpgp_packet_signature() {
this.signatureTargetHashAlgorithm = null;
this.signatureTargetHash = null;
this.embeddedSignature = null;
+
this.verified = false;
@@ -11052,71 +11057,48 @@ function openpgp_packet_signature() {
this.signedHashValue = bytes.substr(i, 2);
i += 2;
- var mpicount = 0;
- // Algorithm-Specific Fields for RSA signatures:
- // - multiprecision number (MPI) of RSA signature value m**d mod n.
- if (this.publicKeyAlgorithm > 0 && this.publicKeyAlgorithm < 4)
- mpicount = 1;
- // Algorithm-Specific Fields for DSA signatures:
- // - MPI of DSA value r.
- // - MPI of DSA value s.
- else if (this.publicKeyAlgorithm == 17)
- mpicount = 2;
-
- this.mpi = [];
- for (var j = 0; j < mpicount; j++) {
- this.mpi[j] = new openpgp_type_mpi();
- i += this.mpi[j].read(bytes.substr(i));
- }
+ this.signature = bytes.substr(i);
+ }
+
+ this.write = function() {
+ return this.signatureData +
+ openpgp_packet_number_write(0, 2) + // Number of unsigned subpackets.
+ this.signedHashValue +
+ this.signature;
}
/**
- * creates a string representation of a message signature packet (tag 2).
- * This can be only used on text data
- * @param {Integer} signature_type should be 1 (one)
- * @param {String} data data to be signed
- * @param {openpgp_msg_privatekey} privatekey private key used to sign the message. (secmpi MUST be unlocked)
- * @return {String} string representation of a signature packet
+ * Signs provided data. This needs to be done prior to serialization.
+ * @param {Object} data Contains packets to be signed.
+ * @param {openpgp_msg_privatekey} privatekey private key used to sign the message.
*/
- function write_message_signature(signature_type, data, privatekey) {
- var publickey = privatekey.privateKeyPacket.publicKey;
- var hash_algo = privatekey.getPreferredSignatureHashAlgorithm();
+ this.sign = function(privatekey, data) {
+ var publickey = privatekey.public_key;
+
var result = String.fromCharCode(4);
- result += String.fromCharCode(signature_type);
- result += String.fromCharCode(publickey.publicKeyAlgorithm);
- result += String.fromCharCode(hash_algo);
- var d = Math.round(new Date().getTime() / 1000);
- var datesubpacket = write_sub_signature_packet(2,""+
- String.fromCharCode((d >> 24) & 0xFF) +
- String.fromCharCode((d >> 16) & 0xFF) +
- String.fromCharCode((d >> 8) & 0xFF) +
- String.fromCharCode(d & 0xFF));
- var issuersubpacket = write_sub_signature_packet(16, privatekey.getKeyId());
- result += String.fromCharCode(((datesubpacket.length + issuersubpacket.length) >> 8) & 0xFF);
- result += String.fromCharCode ((datesubpacket.length + issuersubpacket.length) & 0xFF);
- result += datesubpacket;
- result += issuersubpacket;
- var trailer = '';
+ result += String.fromCharCode(this.signatureType);
+ result += String.fromCharCode(this.publicKeyAlgorithm);
+ result += String.fromCharCode(this.hashAlgorithm);
+
+
+ // Add subpackets here
+ result += openpgp_packet_number_write(0, 2);
+
+
+ this.signatureData = result;
+
+ var trailer = this.calculateTrailer();
- trailer += String.fromCharCode(4);
- trailer += String.fromCharCode(0xFF);
- trailer += String.fromCharCode((result.length) >> 24);
- trailer += String.fromCharCode(((result.length) >> 16) & 0xFF);
- trailer += String.fromCharCode(((result.length) >> 8) & 0xFF);
- trailer += String.fromCharCode((result.length) & 0xFF);
- var result2 = String.fromCharCode(0);
- result2 += String.fromCharCode(0);
- var hash = openpgp_crypto_hashData(hash_algo, data+result+trailer);
- util.print_debug("DSA Signature is calculated with:|"+data+result+trailer+"|\n"+util.hexstrdump(data+result+trailer)+"\n hash:"+util.hexstrdump(hash));
- result2 += hash.charAt(0);
- result2 += hash.charAt(1);
- result2 += openpgp_crypto_signData(hash_algo,privatekey.privateKeyPacket.publicKey.publicKeyAlgorithm,
- publickey.mpi,
- privatekey.privateKeyPacket.secmpi,
- data+result+trailer);
- return {openpgp: (openpgp_packet.write_packet_header(2, (result+result2).length)+result + result2),
- hash: util.get_hashAlgorithmString(hash_algo)};
+ var toHash = this.toSign(this.signatureType, data) + this.signatureData + trailer;
+ var hash = openpgp_crypto_hashData(this.hashAlgorithm, toHash);
+
+ this.signedHashValue = hash.substr(0, 2);
+
+
+ this.signature = openpgp_crypto_signData(this.hashAlgorithm, this.publicKeyAlgorithm,
+ publickey.mpi, privatekey.mpi, toHash);
}
+
/**
* creates a string representation of a sub signature packet (See RFC 4880 5.2.3.1)
* @param {Integer} type subpacket signature type. Signature types as described
@@ -11124,7 +11106,7 @@ function openpgp_packet_signature() {
* @param {String} data data to be included
* @return {String} a string-representation of a sub signature packet (See RFC 4880 5.2.3.1)
*/
- function write_sub_signature_packet(type, data) {
+ function write_sub_packet(type, data) {
var result = "";
result += openpgp_packet.encode_length(data.length+1);
result += String.fromCharCode(type);
@@ -11341,6 +11323,16 @@ function openpgp_packet_signature() {
}
}
+
+ this.calculateTrailer = function() {
+ // calculating the trailer
+ var trailer = '';
+ trailer += String.fromCharCode(this.version);
+ trailer += String.fromCharCode(0xFF);
+ trailer += openpgp_packet_number_write(this.signatureData.length, 4);
+ return trailer
+ }
+
/**
* verifys the signature packet. Note: not signature types are implemented
@@ -11350,16 +11342,29 @@ function openpgp_packet_signature() {
*/
this.verify = function(key, data) {
- var bytes = this.toSign(this.signatureType, data);
+ var bytes = this.toSign(this.signatureType, data),
+ trailer = this.calculateTrailer();
- // calculating the trailer
- var trailer = '';
- trailer += String.fromCharCode(this.version);
- trailer += String.fromCharCode(0xFF);
- trailer += openpgp_packet_number_write(this.signatureData.length, 4);
+
+ var mpicount = 0;
+ // Algorithm-Specific Fields for RSA signatures:
+ // - multiprecision number (MPI) of RSA signature value m**d mod n.
+ if (this.publicKeyAlgorithm > 0 && this.publicKeyAlgorithm < 4)
+ mpicount = 1;
+ // Algorithm-Specific Fields for DSA signatures:
+ // - MPI of DSA value r.
+ // - MPI of DSA value s.
+ else if (this.publicKeyAlgorithm == 17)
+ mpicount = 2;
+
+ var mpi = [], i = 0;
+ for (var j = 0; j < mpicount; j++) {
+ mpi[j] = new openpgp_type_mpi();
+ i += mpi[j].read(this.signature.substr(i));
+ }
this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm,
- this.hashAlgorithm, this.mpi, key.mpi,
+ this.hashAlgorithm, mpi, key.mpi,
bytes + this.signatureData + trailer);
return this.verified;
diff --git a/resources/openpgp.min.js b/resources/openpgp.min.js
index 9caa9f70..dd269657 100644
--- a/resources/openpgp.min.js
+++ b/resources/openpgp.min.js
@@ -114,8 +114,8 @@ function openpgp_crypto_MDCSystemBytes(a,b,c){util.print_debug_hexstr_dump("open
"Twofish Algorithm not implemented"))}return null}function openpgp_crypto_generateSessionKey(a){return openpgp_crypto_getRandomBytes(openpgp_crypto_getKeyLength(a))}function openpgp_crypto_getKeyLength(a){switch(a){case 2:case 8:return 24;case 3:case 4:case 7:return 16;case 9:case 10:return 32}return null}function openpgp_crypto_getBlockLength(a){switch(a){case 1:case 2:case 3:return 8;case 4:case 7:case 8:case 9:return 16;case 10:return 32;default:return 0}}
function openpgp_crypto_verifySignature(a,b,c,d,e){var f=openpgp_crypto_hashData(b,e);switch(a){case 1:case 2:case 3:e=new RSA;a=d[0].toBigInteger();d=d[1].toBigInteger();c=c[0].toBigInteger();d=e.verify(c,d,a);b=openpgp_encoding_emsa_pkcs1_decode(b,d.toMPI().substring(2));return-1==b?(util.print_error("PKCS1 padding in message or key incorrect. Aborting..."),!1):b==f;case 16:return util.print_error("signing with Elgamal is not defined in the OpenPGP standard."),null;case 17:var a=new DSA,f=c[0].toBigInteger(),
c=c[1].toBigInteger(),h=d[0].toBigInteger(),g=d[1].toBigInteger(),j=d[2].toBigInteger(),d=d[3].toBigInteger(),d=a.verify(b,f,c,e,h,g,j,d);return 0==d.compareTo(f);default:return null}}
-function openpgp_crypto_signData(a,b,c,d,e){switch(b){case 1:case 2:case 3:var b=new RSA,d=d[0].toBigInteger(),f=c[0].toBigInteger(),a=openpgp_encoding_emsa_pkcs1_encode(a,e,c[0].mpiByteLength);util.print_debug("signing using RSA");return b.sign(a,d,f).toMPI();case 17:b=new DSA;util.print_debug("DSA Sign: q size in Bytes:"+c[1].getByteLength());var f=c[0].toBigInteger(),h=c[1].toBigInteger(),g=c[2].toBigInteger();c[3].toBigInteger();c=d[0].toBigInteger();a=b.sign(a,e,g,f,h,c);util.print_debug("signing using DSA\n result:"+
-util.hexstrdump(a[0])+"|"+util.hexstrdump(a[1]));return a[0]+a[1];case 16:return util.print_debug("signing with Elgamal is not defined in the OpenPGP standard."),null;default:return null}}function openpgp_crypto_hashData(a,b){var c=null;switch(a){case 1:c=MD5(b);break;case 2:c=str_sha1(b);break;case 3:c=RMDstring(b);break;case 8:c=str_sha256(b);break;case 9:c=str_sha384(b);break;case 10:c=str_sha512(b);break;case 11:c=str_sha224(b)}return c}
+function openpgp_crypto_signData(a,b,c,d,e){switch(b){case 1:case 2:case 3:var b=new RSA,d=d[0].toBigInteger(),f=c[0].toBigInteger(),a=openpgp_encoding_emsa_pkcs1_encode(a,e,c[0].byteLength());util.print_debug("signing using RSA");return b.sign(a,d,f).toMPI();case 17:b=new DSA;util.print_debug("DSA Sign: q size in Bytes:"+c[1].getByteLength());var f=c[0].toBigInteger(),h=c[1].toBigInteger(),g=c[2].toBigInteger();c[3].toBigInteger();c=d[0].toBigInteger();a=b.sign(a,e,g,f,h,c);util.print_debug("signing using DSA\n result:"+
+util.hexstrdump(a[0])+"|"+util.hexstrdump(a[1]));return a[0].toString()+a[1].toString();case 16:return util.print_debug("signing with Elgamal is not defined in the OpenPGP standard."),null;default:return null}}function openpgp_crypto_hashData(a,b){var c=null;switch(a){case 1:c=MD5(b);break;case 2:c=str_sha1(b);break;case 3:c=RMDstring(b);break;case 8:c=str_sha256(b);break;case 9:c=str_sha384(b);break;case 10:c=str_sha512(b);break;case 11:c=str_sha224(b)}return c}
function openpgp_crypto_getHashByteLength(a){switch(a){case 1:return 16;case 2:case 3:return 20;case 8:return 32;case 9:return 48;case 10:return 64;case 11:return 28}return null}function openpgp_crypto_getRandomBytes(a){for(var b="",c=0;cb-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)}}
@@ -383,18 +383,19 @@ switch(f){case 1:throw Error("IDEA is not implemented.");case 2:f=normal_cfb_dec
b)},g.length,new keyExpansion(a),c,g);break;case 10:throw Error("Twofish is not implemented.");default:throw Error("Unknown symmetric algorithm.");}this.mpi=b(254==h?openpgp.hash.sha1:"mod",f,this.public_key.algorithm)}};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)}}
function openpgp_packet_secret_subkey(){openpgp_packet_secret_key.call(this);this.tag=7}
-function openpgp_packet_signature(){this.tag=2;this.issuerKeyId=this.revocationKeyFingerprint=this.revocationKeyAlgorithm=this.revocationKeyClass=this.preferredSymmetricAlgorithms=this.keyNeverExpires=this.keyExpirationTime=this.revocable=this.regularExpression=this.trustAmount=this.trustLevel=this.exportable=this.hashAlgorithm=this.publicKeyAlgorithm=this.mpi=this.signedHashValue=this.signatureNeverExpires=this.signatureExpirationTime=this.signatureData=this.created=this.signatureType=null;this.notation=
-{};this.embeddedSignature=this.signatureTargetHash=this.signatureTargetHashAlgorithm=this.signatureTargetPublicKeyAlgorithm=this.reasonForRevocationString=this.reasonForRevocationFlag=this.signersUserId=this.keyFlags=this.policyURI=this.isPrimaryUserID=this.preferredKeyServer=this.keyServerPreferences=this.preferredCompressionAlgorithms=this.preferredHashAlgorithms=null;this.verified=!1;this.read=function(a){var b=0;this.version=a[b++].charCodeAt();switch(this.version){case 3:5!=a[b++].charCodeAt()&&
-util.print_debug("openpgp.packet.signature.js\ninvalid One-octet length of following hashed material.MUST be 5. @:"+(b-1));this.signatureType=a[b++].charCodeAt();this.created=openpgp_packet_time_read(a.substr(b,4));b+=4;this.signatureData=a.substring(position,b);this.issuerKeyId=a.substring(b,b+8);b+=8;this.publicKeyAlgorithm=a[b++].charCodeAt();this.hashAlgorithm=a[b++].charCodeAt();break;case 4:this.signatureType=a[b++].charCodeAt();this.publicKeyAlgorithm=a[b++].charCodeAt();this.hashAlgorithm=
-a[b++].charCodeAt();var c=function(a,b){for(var c=openpgp_packet_number_read(a.substr(0,2)),d=2;d<2+c;){var j=openpgp_packet.read_simple_length(a.substr(d)),d=d+j.offset;b&&this.read_sub_packet(a.substr(d,j.len));d+=j.len}return d},b=b+c.call(this,a.substr(b),!0);this.signatureData=a.substr(0,b);b+=c.call(this,a.substr(b),!1);break;default:util.print_error("openpgp.packet.signature.js\nunknown signature packet version"+this.version)}this.signedHashValue=a.substr(b,2);b+=2;c=0;0this.publicKeyAlgorithm?c=1:17==this.publicKeyAlgorithm&&(c=2);this.mpi=[];for(var d=0;dthis.publicKeyAlgorithm?e=1:17==this.publicKeyAlgorithm&&(e=2);for(var f=[],h=0,g=0;g 0 && this.publicKeyAlgorithm < 4)
- mpicount = 1;
- // Algorithm-Specific Fields for DSA signatures:
- // - MPI of DSA value r.
- // - MPI of DSA value s.
- else if (this.publicKeyAlgorithm == 17)
- mpicount = 2;
-
- this.mpi = [];
- for (var j = 0; j < mpicount; j++) {
- this.mpi[j] = new openpgp_type_mpi();
- i += this.mpi[j].read(bytes.substr(i));
- }
+ this.signature = bytes.substr(i);
+ }
+
+ this.write = function() {
+ return this.signatureData +
+ openpgp_packet_number_write(0, 2) + // Number of unsigned subpackets.
+ this.signedHashValue +
+ this.signature;
}
/**
- * creates a string representation of a message signature packet (tag 2).
- * This can be only used on text data
- * @param {Integer} signature_type should be 1 (one)
- * @param {String} data data to be signed
- * @param {openpgp_msg_privatekey} privatekey private key used to sign the message. (secmpi MUST be unlocked)
- * @return {String} string representation of a signature packet
+ * Signs provided data. This needs to be done prior to serialization.
+ * @param {Object} data Contains packets to be signed.
+ * @param {openpgp_msg_privatekey} privatekey private key used to sign the message.
*/
- function write_message_signature(signature_type, data, privatekey) {
- var publickey = privatekey.privateKeyPacket.publicKey;
- var hash_algo = privatekey.getPreferredSignatureHashAlgorithm();
+ this.sign = function(privatekey, data) {
+ var publickey = privatekey.public_key;
+
var result = String.fromCharCode(4);
- result += String.fromCharCode(signature_type);
- result += String.fromCharCode(publickey.publicKeyAlgorithm);
- result += String.fromCharCode(hash_algo);
- var d = Math.round(new Date().getTime() / 1000);
- var datesubpacket = write_sub_signature_packet(2,""+
- String.fromCharCode((d >> 24) & 0xFF) +
- String.fromCharCode((d >> 16) & 0xFF) +
- String.fromCharCode((d >> 8) & 0xFF) +
- String.fromCharCode(d & 0xFF));
- var issuersubpacket = write_sub_signature_packet(16, privatekey.getKeyId());
- result += String.fromCharCode(((datesubpacket.length + issuersubpacket.length) >> 8) & 0xFF);
- result += String.fromCharCode ((datesubpacket.length + issuersubpacket.length) & 0xFF);
- result += datesubpacket;
- result += issuersubpacket;
- var trailer = '';
+ result += String.fromCharCode(this.signatureType);
+ result += String.fromCharCode(this.publicKeyAlgorithm);
+ result += String.fromCharCode(this.hashAlgorithm);
+
+
+ // Add subpackets here
+ result += openpgp_packet_number_write(0, 2);
+
+
+ this.signatureData = result;
+
+ var trailer = this.calculateTrailer();
- trailer += String.fromCharCode(4);
- trailer += String.fromCharCode(0xFF);
- trailer += String.fromCharCode((result.length) >> 24);
- trailer += String.fromCharCode(((result.length) >> 16) & 0xFF);
- trailer += String.fromCharCode(((result.length) >> 8) & 0xFF);
- trailer += String.fromCharCode((result.length) & 0xFF);
- var result2 = String.fromCharCode(0);
- result2 += String.fromCharCode(0);
- var hash = openpgp_crypto_hashData(hash_algo, data+result+trailer);
- util.print_debug("DSA Signature is calculated with:|"+data+result+trailer+"|\n"+util.hexstrdump(data+result+trailer)+"\n hash:"+util.hexstrdump(hash));
- result2 += hash.charAt(0);
- result2 += hash.charAt(1);
- result2 += openpgp_crypto_signData(hash_algo,privatekey.privateKeyPacket.publicKey.publicKeyAlgorithm,
- publickey.mpi,
- privatekey.privateKeyPacket.secmpi,
- data+result+trailer);
- return {openpgp: (openpgp_packet.write_packet_header(2, (result+result2).length)+result + result2),
- hash: util.get_hashAlgorithmString(hash_algo)};
+ var toHash = this.toSign(this.signatureType, data) + this.signatureData + trailer;
+ var hash = openpgp_crypto_hashData(this.hashAlgorithm, toHash);
+
+ this.signedHashValue = hash.substr(0, 2);
+
+
+ this.signature = openpgp_crypto_signData(this.hashAlgorithm, this.publicKeyAlgorithm,
+ publickey.mpi, privatekey.mpi, toHash);
}
+
/**
* creates a string representation of a sub signature packet (See RFC 4880 5.2.3.1)
* @param {Integer} type subpacket signature type. Signature types as described
@@ -233,7 +215,7 @@ function openpgp_packet_signature() {
* @param {String} data data to be included
* @return {String} a string-representation of a sub signature packet (See RFC 4880 5.2.3.1)
*/
- function write_sub_signature_packet(type, data) {
+ function write_sub_packet(type, data) {
var result = "";
result += openpgp_packet.encode_length(data.length+1);
result += String.fromCharCode(type);
@@ -450,6 +432,16 @@ function openpgp_packet_signature() {
}
}
+
+ this.calculateTrailer = function() {
+ // calculating the trailer
+ var trailer = '';
+ trailer += String.fromCharCode(this.version);
+ trailer += String.fromCharCode(0xFF);
+ trailer += openpgp_packet_number_write(this.signatureData.length, 4);
+ return trailer
+ }
+
/**
* verifys the signature packet. Note: not signature types are implemented
@@ -459,16 +451,29 @@ function openpgp_packet_signature() {
*/
this.verify = function(key, data) {
- var bytes = this.toSign(this.signatureType, data);
+ var bytes = this.toSign(this.signatureType, data),
+ trailer = this.calculateTrailer();
- // calculating the trailer
- var trailer = '';
- trailer += String.fromCharCode(this.version);
- trailer += String.fromCharCode(0xFF);
- trailer += openpgp_packet_number_write(this.signatureData.length, 4);
+
+ var mpicount = 0;
+ // Algorithm-Specific Fields for RSA signatures:
+ // - multiprecision number (MPI) of RSA signature value m**d mod n.
+ if (this.publicKeyAlgorithm > 0 && this.publicKeyAlgorithm < 4)
+ mpicount = 1;
+ // Algorithm-Specific Fields for DSA signatures:
+ // - MPI of DSA value r.
+ // - MPI of DSA value s.
+ else if (this.publicKeyAlgorithm == 17)
+ mpicount = 2;
+
+ var mpi = [], i = 0;
+ for (var j = 0; j < mpicount; j++) {
+ mpi[j] = new openpgp_type_mpi();
+ i += mpi[j].read(this.signature.substr(i));
+ }
this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm,
- this.hashAlgorithm, this.mpi, key.mpi,
+ this.hashAlgorithm, mpi, key.mpi,
bytes + this.signatureData + trailer);
return this.verified;
diff --git a/test/general/packet.js b/test/general/packet.js
index ef023f62..12eaf1ac 100644
--- a/test/general/packet.js
+++ b/test/general/packet.js
@@ -424,6 +424,53 @@ unittests.register("Packet testing", function() {
return new test_result('Writing and encryptio of a secret key packet.',
key[0].mpi.toString() == key2[0].mpi.toString());
+ }, function() {
+ var key = new openpgp_packet_secret_key;
+
+ var rsa = new RSA(),
+ mpi = rsa.generate(512, "10001")
+
+
+ var mpi = [
+ [mpi.d, mpi.p, mpi.q, mpi.u],
+ [mpi.n, mpi.ee]];
+
+ mpi = mpi.map(function(k) {
+ return k.map(function(bn) {
+ var mpi = new openpgp_type_mpi();
+ mpi.fromBigInteger(bn);
+ return mpi;
+ });
+ });
+
+ key.public_key.mpi = mpi[1];
+ key.mpi = mpi[0];
+
+ var signed = new openpgp_packetlist(),
+ literal = new openpgp_packet_literal(),
+ signature = new openpgp_packet_signature();
+
+ literal.set_data('Hello world', openpgp_packet_literal.format.utf8);
+
+ signature.hashAlgorithm = openpgp.hash.sha256;
+ signature.publicKeyAlgorithm = openpgp.publickey.rsa_sign;
+ signature.signatureType = openpgp_packet_signature.type.binary;
+
+ signature.sign(key, { literal: literal });
+
+ signed.push(literal);
+ signed.push(signature);
+
+ var raw = signed.write();
+
+ var signed2 = new openpgp_packetlist();
+ signed2.read(raw);
+
+ var verified = signed2[1].verify(key.public_key, { literal: signed2[0] });
+
+
+ return new test_result('Writing and verification of a signature packet.',
+ verified == true);
}];