diff --git a/src/key.js b/src/key.js index 5d4fd15b..394af502 100644 --- a/src/key.js +++ b/src/key.js @@ -268,7 +268,7 @@ Key.prototype.armor = function() { * @returns {Promise} The latest valid signature * @async */ -async function getLatestValidSignature(signatures, primaryKey, dataToVerify, date=new Date()) { +async function getLatestValidSignature(signatures, primaryKey, signatureType, dataToVerify, date=new Date()) { let signature; for (let i = signatures.length - 1; i >= 0; i--) { if ( @@ -276,7 +276,7 @@ async function getLatestValidSignature(signatures, primaryKey, dataToVerify, dat // check binding signature is not expired (ie, check for V4 expiration time) !signatures[i].isExpired(date) && // check binding signature is verified - (signatures[i].verified || await signatures[i].verify(primaryKey, dataToVerify)) + (signatures[i].verified || await signatures[i].verify(primaryKey, signatureType, dataToVerify)) ) { signature = signatures[i]; } @@ -300,12 +300,12 @@ Key.prototype.getSigningKey = async function (keyId=null, date=new Date(), userI if (!keyId || subKeys[i].getKeyId().equals(keyId)) { if (await subKeys[i].verify(primaryKey, date) === enums.keyStatus.valid) { const dataToVerify = { key: primaryKey, bind: subKeys[i].keyPacket }; - const bindingSignature = await getLatestValidSignature(subKeys[i].bindingSignatures, primaryKey, dataToVerify, date); + const bindingSignature = await getLatestValidSignature(subKeys[i].bindingSignatures, primaryKey, enums.signature.subkey_binding, dataToVerify, date); if ( bindingSignature && bindingSignature.embeddedSignature && isValidSigningKeyPacket(subKeys[i].keyPacket, bindingSignature) && - await getLatestValidSignature([bindingSignature.embeddedSignature], subKeys[i].keyPacket, dataToVerify, date) + await getLatestValidSignature([bindingSignature.embeddedSignature], subKeys[i].keyPacket, enums.signature.key_binding, dataToVerify, date) ) { return subKeys[i]; } @@ -349,7 +349,7 @@ Key.prototype.getEncryptionKey = async function(keyId, date=new Date(), userId={ if (!keyId || subKeys[i].getKeyId().equals(keyId)) { if (await subKeys[i].verify(primaryKey, date) === enums.keyStatus.valid) { const dataToVerify = { key: primaryKey, bind: subKeys[i].keyPacket }; - const bindingSignature = await getLatestValidSignature(subKeys[i].bindingSignatures, primaryKey, dataToVerify, date); + const bindingSignature = await getLatestValidSignature(subKeys[i].bindingSignatures, primaryKey, enums.signature.subkey_binding, dataToVerify, date); if (bindingSignature && isValidEncryptionKeyPacket(subKeys[i].keyPacket, bindingSignature)) { return subKeys[i]; } @@ -451,7 +451,7 @@ Key.prototype.decrypt = async function(passphrases, keyId=null) { */ Key.prototype.isRevoked = async function(signature, key, date=new Date()) { return isDataRevoked( - this.keyPacket, { key: this.keyPacket }, this.revocationSignatures, signature, key, date + this.keyPacket, enums.signature.key_revocation, { key: this.keyPacket }, this.revocationSignatures, signature, key, date ); }; @@ -542,7 +542,7 @@ Key.prototype.getPrimaryUser = async function(date=new Date(), userId={}) { (userId.comment === undefined || user.userId.comment === userId.comment) )) continue; const dataToVerify = { userId: user.userId, key: primaryKey }; - const selfCertification = await getLatestValidSignature(user.selfCertifications, primaryKey, dataToVerify, date); + const selfCertification = await getLatestValidSignature(user.selfCertifications, primaryKey, enums.signature.cert_generic, dataToVerify, date); if (!selfCertification) continue; users.push({ index: i, user, selfCertification }); } @@ -599,7 +599,7 @@ Key.prototype.update = async function(key) { } // revocation signatures await mergeSignatures(key, this, 'revocationSignatures', srcRevSig => { - return isDataRevoked(this.keyPacket, this, [srcRevSig], null, key.keyPacket); + return isDataRevoked(this.keyPacket, enums.signature.key_revocation, this, [srcRevSig], null, key.keyPacket); }); // direct signatures await mergeSignatures(key, this, 'directSignatures'); @@ -695,7 +695,7 @@ Key.prototype.revoke = async function({ */ Key.prototype.getRevocationCertificate = async function() { const dataToVerify = { key: this.keyPacket }; - const revocationSignature = await getLatestValidSignature(this.revocationSignatures, this.keyPacket, dataToVerify); + const revocationSignature = await getLatestValidSignature(this.revocationSignatures, this.keyPacket, enums.signature.key_revocation, dataToVerify); if (revocationSignature) { const packetlist = new packet.List(); packetlist.push(revocationSignature); @@ -725,7 +725,7 @@ Key.prototype.applyRevocationCertificate = async function(revocationCertificate) if (revocationSignature.isExpired()) { throw new Error('Revocation signature is expired'); } - if (!await revocationSignature.verify(this.keyPacket, { key: this.keyPacket })) { + if (!await revocationSignature.verify(this.keyPacket, enums.signature.key_revocation, { key: this.keyPacket })) { throw new Error('Could not verify revocation signature'); } const key = new Key(this.toPacketlist()); @@ -892,7 +892,7 @@ User.prototype.sign = async function(primaryKey, privateKeys) { */ User.prototype.isRevoked = async function(primaryKey, certificate, key, date=new Date()) { return isDataRevoked( - primaryKey, { + primaryKey, enums.signature.cert_revocation, { key: primaryKey, userId: this.userId, userAttribute: this.userAttribute @@ -946,7 +946,7 @@ User.prototype.verifyCertificate = async function(primaryKey, certificate, keys, if (certificate.revoked || await that.isRevoked(primaryKey, certificate, signingKey.keyPacket)) { return enums.keyStatus.revoked; } - if (!(certificate.verified || await certificate.verify(signingKey.keyPacket, dataToVerify))) { + if (!(certificate.verified || await certificate.verify(signingKey.keyPacket, enums.signature.cert_generic, dataToVerify))) { return enums.keyStatus.invalid; } if (certificate.isExpired()) { @@ -1002,7 +1002,7 @@ User.prototype.verify = async function(primaryKey) { if (selfCertification.revoked || await that.isRevoked(primaryKey, selfCertification)) { return enums.keyStatus.revoked; } - if (!(selfCertification.verified || await selfCertification.verify(primaryKey, dataToVerify))) { + if (!(selfCertification.verified || await selfCertification.verify(primaryKey, enums.signature.cert_generic, dataToVerify))) { return enums.keyStatus.invalid; } if (selfCertification.isExpired()) { @@ -1030,13 +1030,13 @@ User.prototype.update = async function(user, primaryKey) { }; // self signatures await mergeSignatures(user, this, 'selfCertifications', async function(srcSelfSig) { - return srcSelfSig.verified || srcSelfSig.verify(primaryKey, dataToVerify); + return srcSelfSig.verified || srcSelfSig.verify(primaryKey, enums.signature.cert_generic, dataToVerify); }); // other signatures await mergeSignatures(user, this, 'otherCertifications'); // revocation signatures await mergeSignatures(user, this, 'revocationSignatures', function(srcRevSig) { - return isDataRevoked(primaryKey, dataToVerify, [srcRevSig]); + return isDataRevoked(primaryKey, enums.signature.cert_revocation, dataToVerify, [srcRevSig]); }); }; @@ -1086,7 +1086,7 @@ SubKey.prototype.toPacketlist = function() { */ SubKey.prototype.isRevoked = async function(primaryKey, signature, key, date=new Date()) { return isDataRevoked( - primaryKey, { + primaryKey, enums.signature.subkey_revocation, { key: primaryKey, bind: this.keyPacket }, this.revocationSignatures, signature, key, date @@ -1106,7 +1106,7 @@ SubKey.prototype.verify = async function(primaryKey, date=new Date()) { const that = this; const dataToVerify = { key: primaryKey, bind: this.keyPacket }; // check subkey binding signatures - const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, dataToVerify, date); + const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkey_binding, dataToVerify, date); // check binding signature is verified if (!bindingSignature) { return enums.keyStatus.invalid; @@ -1133,7 +1133,7 @@ SubKey.prototype.verify = async function(primaryKey, date=new Date()) { */ SubKey.prototype.getExpirationTime = async function(primaryKey, date=new Date()) { const dataToVerify = { key: primaryKey, bind: this.keyPacket }; - const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, dataToVerify, date); + const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkey_binding, dataToVerify, date); if (!bindingSignature) return null; const keyExpiry = getExpirationTime(this.keyPacket, bindingSignature); const sigExpiry = bindingSignature.getExpirationTime(); @@ -1164,7 +1164,7 @@ SubKey.prototype.update = async function(subKey, primaryKey) { const that = this; const dataToVerify = { key: primaryKey, bind: that.keyPacket }; await mergeSignatures(subKey, this, 'bindingSignatures', async function(srcBindSig) { - if (!(srcBindSig.verified || await srcBindSig.verify(primaryKey, dataToVerify))) { + if (!(srcBindSig.verified || await srcBindSig.verify(primaryKey, enums.signature.subkey_binding, dataToVerify))) { return false; } for (let i = 0; i < that.bindingSignatures.length; i++) { @@ -1179,7 +1179,7 @@ SubKey.prototype.update = async function(subKey, primaryKey) { }); // revocation signatures await mergeSignatures(subKey, this, 'revocationSignatures', function(srcRevSig) { - return isDataRevoked(primaryKey, dataToVerify, [srcRevSig]); + return isDataRevoked(primaryKey, enums.signature.subkey_revocation, dataToVerify, [srcRevSig]); }); }; @@ -1580,7 +1580,7 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options) { * @returns {Promise} True if the signature revokes the data * @async */ -async function isDataRevoked(primaryKey, dataToVerify, revocations, signature, key, date=new Date()) { +async function isDataRevoked(primaryKey, signatureType, dataToVerify, revocations, signature, key, date=new Date()) { key = key || primaryKey; const normDate = util.normalizeDate(date); const revocationKeyIds = []; @@ -1596,7 +1596,7 @@ async function isDataRevoked(primaryKey, dataToVerify, revocations, signature, k // `verifyAllCertifications`.) (!signature || revocationSignature.issuerKeyId.equals(signature.issuerKeyId)) && !(config.revocations_expire && revocationSignature.isExpired(normDate)) && - (revocationSignature.verified || await revocationSignature.verify(key, dataToVerify)) + (revocationSignature.verified || await revocationSignature.verify(key, signatureType, dataToVerify)) ) { // TODO get an identifier of the revoked object instead revocationKeyIds.push(revocationSignature.issuerKeyId); diff --git a/src/message.js b/src/message.js index 65597e60..492286d9 100644 --- a/src/message.js +++ b/src/message.js @@ -559,7 +559,7 @@ Message.prototype.verify = async function(keys, date=new Date(), streaming) { onePassSig.correspondingSigReject = reject; }); onePassSig.signatureData = stream.fromAsync(async () => (await onePassSig.correspondingSig).signatureData); - onePassSig.hashed = await onePassSig.hash(literalDataList[0], undefined, streaming); + onePassSig.hashed = await onePassSig.hash(onePassSig.signatureType, literalDataList[0], undefined, streaming); })); msg.packets.stream = stream.transformPair(msg.packets.stream, async (readable, writable) => { const reader = stream.getReader(readable); @@ -625,7 +625,7 @@ async function createVerificationObject(signature, literalDataList, keys, date=n const verifiedSig = { keyid: signature.issuerKeyId, - verified: keyPacket ? signature.verify(keyPacket, literalDataList[0]) : Promise.resolve(null) + verified: keyPacket ? signature.verify(keyPacket, signature.signatureType, literalDataList[0]) : Promise.resolve(null) }; verifiedSig.signature = Promise.resolve(signature.correspondingSig || signature).then(signature => { diff --git a/src/packet/signature.js b/src/packet/signature.js index 292ba128..0faf2875 100644 --- a/src/packet/signature.js +++ b/src/packet/signature.js @@ -171,8 +171,8 @@ Signature.prototype.sign = async function (key, data) { this.signatureData = util.concat(arr); - const toHash = this.toHash(data); - const hash = await this.hash(data, toHash); + const toHash = this.toHash(signatureType, data); + const hash = await this.hash(signatureType, data, toHash); this.signedHashValue = stream.slice(stream.clone(hash), 0, 2); @@ -637,19 +637,17 @@ Signature.prototype.calculateTrailer = function () { }; -Signature.prototype.toHash = function(data) { - const signatureType = enums.write(enums.signature, this.signatureType); - +Signature.prototype.toHash = function(signatureType, data) { const bytes = this.toSign(signatureType, data); return util.concat([bytes, this.signatureData, this.calculateTrailer()]); }; -Signature.prototype.hash = async function(data, toHash, streaming=true) { +Signature.prototype.hash = async function(signatureType, data, toHash, streaming=true) { const hashAlgorithm = enums.write(enums.hash, this.hashAlgorithm); - if (!toHash) toHash = this.toHash(data); + if (!toHash) toHash = this.toHash(signatureType, data); if (!streaming && util.isStream(toHash)) { - return stream.fromAsync(async () => this.hash(data, await stream.readToEnd(toHash))); + return stream.fromAsync(async () => this.hash(signatureType, data, await stream.readToEnd(toHash))); } return crypto.hash.digest(hashAlgorithm, toHash); }; @@ -657,13 +655,14 @@ Signature.prototype.hash = async function(data, toHash, streaming=true) { /** * verifys the signature packet. Note: not signature types are implemented - * @param {String|Object} data data which on the signature applies * @param {module:packet.PublicSubkey|module:packet.PublicKey| * module:packet.SecretSubkey|module:packet.SecretKey} key the public key to verify the signature + * @param {module:enums.signature} signatureType expected signature type + * @param {String|Object} data data which on the signature applies * @returns {Promise} True if message is verified, else false. * @async */ -Signature.prototype.verify = async function (key, data) { +Signature.prototype.verify = async function (key, signatureType, data) { const publicKeyAlgorithm = enums.write(enums.publicKey, this.publicKeyAlgorithm); const hashAlgorithm = enums.write(enums.hash, this.hashAlgorithm); @@ -672,8 +671,8 @@ Signature.prototype.verify = async function (key, data) { if (this.hashed) { hash = this.hashed; } else { - toHash = this.toHash(data); - hash = await this.hash(data, toHash); + toHash = this.toHash(signatureType, data); + hash = await this.hash(signatureType, data, toHash); } hash = await stream.readToEnd(hash); diff --git a/test/general/packet.js b/test/general/packet.js index e076a27e..a7b23554 100644 --- a/test/general/packet.js +++ b/test/general/packet.js @@ -729,11 +729,13 @@ describe("Packet", function() { await key.read((await openpgp.armor.decode(armored_key)).data); return Promise.all([ expect(key[2].verify(key[0], + openpgp.enums.signature.cert_generic, { userId: key[1], key: key[0] })).to.eventually.be.true, expect(key[4].verify(key[0], + openpgp.enums.signature.key_binding, { key: key[0], bind: key[3] @@ -773,7 +775,7 @@ describe("Packet", function() { await Promise.all([ expect(payload[2].verify( - key[0], payload[1] + key[0], openpgp.enums.signature.binary, payload[1] )).to.eventually.be.true, openpgp.stream.pipe(payload[1].getBytes(), new WritableStream()) ]); @@ -900,7 +902,7 @@ kePFjAnu9cpynKXu3usf8+FuBw2zLsg1Id1n7ttxoAte416KjBN9lFBt8mcu signed2.concat(await openpgp.stream.readToEnd(signed2.stream, arr => arr)); await Promise.all([ - expect(signed2[1].verify(key, signed2[0])).to.eventually.be.true, + expect(signed2[1].verify(key, openpgp.enums.signature.text, signed2[0])).to.eventually.be.true, openpgp.stream.pipe(signed2[0].getBytes(), new WritableStream()) ]); }); diff --git a/test/general/signature.js b/test/general/signature.js index 22b25832..d6c53acc 100644 --- a/test/general/signature.js +++ b/test/general/signature.js @@ -839,7 +839,7 @@ hkJiXopCSWKSlQInL1devkJJUWJmTmZeugJYlpdLAagQJM0JpsCqIQZwKgAA it('Verify primary key revocation signatures', async function() { const pubKey = (await openpgp.key.readArmored(pub_revoked)).keys[0]; await expect(pubKey.revocationSignatures[0].verify( - pubKey.primaryKey, {key: pubKey.primaryKey} + pubKey.primaryKey, openpgp.enums.signature.key_revocation, {key: pubKey.primaryKey} )).to.eventually.be.true; }); @@ -847,7 +847,7 @@ hkJiXopCSWKSlQInL1devkJJUWJmTmZeugJYlpdLAagQJM0JpsCqIQZwKgAA it('Verify subkey revocation signatures', async function() { const pubKey = (await openpgp.key.readArmored(pub_revoked)).keys[0]; await expect(pubKey.subKeys[0].revocationSignatures[0].verify( - pubKey.primaryKey, {key: pubKey.primaryKey, bind: pubKey.subKeys[0].keyPacket} + pubKey.primaryKey, openpgp.enums.signature.subkey_revocation, {key: pubKey.primaryKey, bind: pubKey.subKeys[0].keyPacket} )).to.eventually.be.true; }); diff --git a/test/general/x25519.js b/test/general/x25519.js index e0cefeb1..a938ded1 100644 --- a/test/general/x25519.js +++ b/test/general/x25519.js @@ -241,7 +241,7 @@ describe('X25519 Cryptography', function () { // Self Certificate is valid const user = hi.users[0]; await expect(user.selfCertifications[0].verify( - primaryKey, { userId: user.userId, key: primaryKey } + primaryKey, openpgp.enums.signature.cert_generic, { userId: user.userId, key: primaryKey } )).to.eventually.be.true; await expect(user.verifyCertificate( primaryKey, user.selfCertifications[0], [hi.toPublic()] @@ -261,7 +261,7 @@ describe('X25519 Cryptography', function () { // Self Certificate is valid const user = bye.users[0]; await expect(user.selfCertifications[0].verify( - bye.primaryKey, { userId: user.userId, key: bye.primaryKey } + bye.primaryKey, openpgp.enums.signature.cert_generic, { userId: user.userId, key: bye.primaryKey } )).to.eventually.be.true; await expect(user.verifyCertificate( bye.primaryKey, user.selfCertifications[0], [bye.toPublic()] @@ -271,7 +271,7 @@ describe('X25519 Cryptography', function () { // Hi trusts Bye! bye.toPublic().signPrimaryUser([hi]).then(trustedBye => { expect(trustedBye.users[0].otherCertifications[0].verify( - primaryKey, { userId: user.userId, key: bye.toPublic().primaryKey } + primaryKey, openpgp.enums.signature.cert_generic, { userId: user.userId, key: bye.toPublic().primaryKey } )).to.eventually.be.true; }), // Signing message