Fix getExpirationTime with capabilities and an expired signing subkey

When the latest subkey with the requested capabilities is expired,
and the primary key has the requested capabilities, return the
primary key expiry instead.

Also, change isExpired/isDataExpired to still return false at the
date returned by getExpirationTime, so that the latter returns the
last date that the key can still be used.
This commit is contained in:
Daniel Huigens 2018-12-21 12:24:59 -05:00
parent 937150b5bd
commit 9691dc9c99
4 changed files with 20 additions and 5 deletions

View File

@ -510,13 +510,17 @@ Key.prototype.getExpirationTime = async function(capabilities, keyId, userId) {
const sigExpiry = selfCert.getExpirationTime();
let expiry = keyExpiry < sigExpiry ? keyExpiry : sigExpiry;
if (capabilities === 'encrypt' || capabilities === 'encrypt_sign') {
const encryptKey = await this.getEncryptionKey(keyId, null, userId);
const encryptKey =
await this.getEncryptionKey(keyId, expiry, userId) ||
await this.getEncryptionKey(keyId, null, userId);
if (!encryptKey) return null;
const encryptExpiry = await encryptKey.getExpirationTime(this.keyPacket);
if (encryptExpiry < expiry) expiry = encryptExpiry;
}
if (capabilities === 'sign' || capabilities === 'encrypt_sign') {
const signKey = await this.getSigningKey(keyId, null, userId);
const signKey =
await this.getSigningKey(keyId, expiry, userId) ||
await this.getSigningKey(keyId, null, userId);
if (!signKey) return null;
const signExpiry = await signKey.getExpirationTime(this.keyPacket);
if (signExpiry < expiry) expiry = signExpiry;
@ -1632,7 +1636,7 @@ function isDataExpired(keyPacket, signature, date=new Date()) {
const normDate = util.normalizeDate(date);
if (normDate !== null) {
const expirationTime = getExpirationTime(keyPacket, signature);
return !(keyPacket.created <= normDate && normDate < expirationTime) ||
return !(keyPacket.created <= normDate && normDate <= expirationTime) ||
(signature && signature.isExpired(date));
}
return false;

View File

@ -727,7 +727,7 @@ Signature.prototype.isExpired = function (date=new Date()) {
const normDate = util.normalizeDate(date);
if (normDate !== null) {
const expirationTime = this.getExpirationTime();
return !(this.created <= normDate && normDate < expirationTime);
return !(this.created <= normDate && normDate <= expirationTime);
}
return false;
};

View File

@ -165,7 +165,7 @@ export default {
},
normalizeDate: function (time = Date.now()) {
return time === null ? time : new Date(Math.floor(+time / 1000) * 1000);
return time === null || time === Infinity ? time : new Date(Math.floor(+time / 1000) * 1000);
},
/**

View File

@ -1983,12 +1983,23 @@ describe('Key', function() {
const pubKey = (await openpgp.key.readArmored(priv_key_2000_2008)).keys[0];
expect(pubKey).to.exist;
expect(pubKey).to.be.an.instanceof(openpgp.key.Key);
pubKey.users[0].selfCertifications[0].keyFlags = [1];
const expirationTime = await pubKey.getExpirationTime();
expect(expirationTime).to.equal(Infinity);
const encryptExpirationTime = await pubKey.getExpirationTime('encrypt_sign');
expect(encryptExpirationTime.toISOString()).to.equal('2008-02-12T17:12:08.000Z');
});
it('Method getExpirationTime V4 Key with capabilities - capable primary key', async function() {
const pubKey = (await openpgp.key.readArmored(priv_key_2000_2008)).keys[0];
expect(pubKey).to.exist;
expect(pubKey).to.be.an.instanceof(openpgp.key.Key);
const expirationTime = await pubKey.getExpirationTime();
expect(expirationTime).to.equal(Infinity);
const encryptExpirationTime = await pubKey.getExpirationTime('encrypt_sign');
expect(encryptExpirationTime).to.equal(Infinity);
});
it('update() - throw error if fingerprints not equal', async function() {
const keys = (await openpgp.key.readArmored(twoKeys)).keys;
await expect(keys[0].update.bind(