Only throw on authorized revocation key when verifying self-signatures (#1017)

This also has the effect that we only throw on them when trying to use
the key, instead of when parsing it, and that we don't throw when the
authorized revocation key is specified in a separate direct-key
signature instead of a User ID self-signature (the spec only specifies
including it in a direct-key signature, so that means that we
effectively don't reject them anymore. This is because users that
wanted to use the key, could remove this separate signature, anyway.)
This commit is contained in:
Daniel Huigens 2019-12-20 17:21:35 +01:00 committed by GitHub
parent e1b9156e72
commit 3d75efc1dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 95 additions and 25 deletions

View File

@ -274,19 +274,6 @@ export function getExpirationTime(keyPacket, signature) {
return expirationTime ? new Date(expirationTime) : Infinity;
}
/**
* Check if signature has revocation key sub packet (not supported by OpenPGP.js)
* and throw error if found
* @param {module:packet.Signature} signature The certificate or signature to check
* @param {type/keyid} keyId Check only certificates or signatures from a certain issuer key ID
*/
export function checkRevocationKey(signature, keyId) {
if (signature.revocationKeyClass !== null &&
signature.issuerKeyId.equals(keyId)) {
throw new Error('This key is intended to be revoked with an authorized key, which OpenPGP.js does not support.');
}
}
/**
* Returns whether aead is supported by all keys in the set
* @param {Array<module:key.Key>} keys Set of keys

View File

@ -106,7 +106,6 @@ Key.prototype.packetlist2structure = function(packetlist) {
continue;
}
if (packetlist[i].issuerKeyId.equals(primaryKeyId)) {
helper.checkRevocationKey(packetlist[i], primaryKeyId);
user.selfCertifications.push(packetlist[i]);
} else {
user.otherCertifications.push(packetlist[i]);
@ -120,7 +119,6 @@ Key.prototype.packetlist2structure = function(packetlist) {
}
break;
case enums.signature.key:
helper.checkRevocationKey(packetlist[i], primaryKeyId);
this.directSignatures.push(packetlist[i]);
break;
case enums.signature.subkey_binding:
@ -128,7 +126,6 @@ Key.prototype.packetlist2structure = function(packetlist) {
util.print_debug('Dropping subkey binding signature without preceding subkey packet');
continue;
}
helper.checkRevocationKey(packetlist[i], primaryKeyId);
subKey.bindingSignatures.push(packetlist[i]);
break;
case enums.signature.key_revocation:

View File

@ -706,9 +706,10 @@ Signature.prototype.verify = async function (key, signatureType, data, detached
hash = await this.hash(signatureType, data, toHash);
}
hash = await stream.readToEnd(hash);
let verified;
if (this.signedHashValue[0] !== hash[0] ||
this.signedHashValue[1] !== hash[1]) {
this.verified = false;
verified = false;
} else {
let mpicount = 0;
// Algorithm-Specific Fields for RSA signatures:
@ -735,12 +736,16 @@ Signature.prototype.verify = async function (key, signatureType, data, detached
mpi[j] = new type_mpi();
i += mpi[j].read(this.signature.subarray(i, this.signature.length), endian);
}
this.verified = await crypto.signature.verify(
verified = await crypto.signature.verify(
publicKeyAlgorithm, hashAlgorithm, mpi, key.params,
toHash, hash
);
if (verified && this.revocationKeyClass !== null) {
throw new Error('This key is intended to be revoked with an authorized key, which OpenPGP.js does not support.');
}
}
return this.verified;
this.verified = verified;
return verified;
};
/**

View File

@ -1258,6 +1258,84 @@ lbjwPj3QUTbLFvHisYzXEQ==
-----END PGP PUBLIC KEY BLOCK-----
`;
const key_with_authorized_revocation_key_in_separate_sig = `-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: CounterMailEngine v1.4
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
=KtVw
-----END PGP PUBLIC KEY BLOCK-----
`;
const key_with_revoked_third_party_cert = `-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: GPGTools - https://gpgtools.org
@ -2268,12 +2346,15 @@ describe('Key', function() {
expect(pubKeys.keys[1].getKeyId().toHex()).to.equal('dbf223e870534df4');
});
it('Parsing armored key with an authorized revocation key', async function() {
const pubKeys = await openpgp.key.readArmored(key_with_authorized_revocation_key);
expect(pubKeys).to.exist;
expect(pubKeys.err).to.exist.and.have.length(1);
expect(pubKeys.err[0].message).to.equal('This key is intended to be revoked with an authorized key, which OpenPGP.js does not support.');
expect(pubKeys.keys).to.have.length(0);
it('Parsing armored key with an authorized revocation key in a User ID self-signature', async function() {
const { keys: [pubKey] } = await openpgp.key.readArmored(key_with_authorized_revocation_key);
await expect(pubKey.getPrimaryUser()).to.be.rejectedWith('This key is intended to be revoked with an authorized key, which OpenPGP.js does not support.');
});
it('Parsing armored key with an authorized revocation key in a direct-key signature', async function() {
const { keys: [pubKey] } = await openpgp.key.readArmored(key_with_authorized_revocation_key_in_separate_sig);
const primaryUser = await pubKey.getPrimaryUser();
expect(primaryUser).to.exist;
});
it('Parsing V5 public key packet', async function() {