ignore revoked user ids for primary key expiry
This commit is contained in:
@@ -79,9 +79,8 @@ public abstract class CanonicalizedKeyRing extends KeyRing {
|
|||||||
|
|
||||||
public boolean isExpired() {
|
public boolean isExpired() {
|
||||||
// Is the master key expired?
|
// Is the master key expired?
|
||||||
Date creationDate = getRing().getPublicKey().getCreationTime();
|
Date creationDate = getPublicKey().getCreationTime();
|
||||||
Date expiryDate = getRing().getPublicKey().getValidSeconds() > 0
|
Date expiryDate = getPublicKey().getExpiryTime();
|
||||||
? new Date(creationDate.getTime() + getRing().getPublicKey().getValidSeconds() * 1000) : null;
|
|
||||||
|
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
return creationDate.after(now) || (expiryDate != null && expiryDate.before(now));
|
return creationDate.after(now) || (expiryDate != null && expiryDate.before(now));
|
||||||
|
|||||||
@@ -20,8 +20,16 @@ package org.sufficientlysecure.keychain.pgp;
|
|||||||
|
|
||||||
import org.spongycastle.bcpg.sig.KeyFlags;
|
import org.spongycastle.bcpg.sig.KeyFlags;
|
||||||
import org.spongycastle.openpgp.PGPPublicKey;
|
import org.spongycastle.openpgp.PGPPublicKey;
|
||||||
|
import org.spongycastle.openpgp.PGPSignature;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator;
|
import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator;
|
||||||
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||||
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
/** Wrapper for a PGPPublicKey.
|
/** Wrapper for a PGPPublicKey.
|
||||||
*
|
*
|
||||||
@@ -100,6 +108,72 @@ public class CanonicalizedPublicKey extends UncachedPublicKey {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRevoked() {
|
||||||
|
return mPublicKey.getSignaturesOfType(isMasterKey()
|
||||||
|
? PGPSignature.KEY_REVOCATION
|
||||||
|
: PGPSignature.SUBKEY_REVOCATION).hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isExpired () {
|
||||||
|
Date expiry = getExpiryTime();
|
||||||
|
return expiry != null && expiry.before(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getValidSeconds() {
|
||||||
|
|
||||||
|
long seconds;
|
||||||
|
|
||||||
|
// the getValidSeconds method is unreliable for master keys. we need to iterate all
|
||||||
|
// user ids, then use the most recent certification from a non-revoked user id
|
||||||
|
if (isMasterKey()) {
|
||||||
|
Date latestCreation = null;
|
||||||
|
seconds = 0;
|
||||||
|
|
||||||
|
for (byte[] rawUserId : getUnorderedRawUserIds()) {
|
||||||
|
Iterator<WrappedSignature> sigs = getSignaturesForRawId(rawUserId);
|
||||||
|
|
||||||
|
// there is always a certification, so this call is safe
|
||||||
|
WrappedSignature sig = sigs.next();
|
||||||
|
|
||||||
|
// we know a user id has at most two sigs: one certification, one revocation.
|
||||||
|
// if the sig is a revocation, or there is another sig (which is a revocation),
|
||||||
|
// the data in this uid is not relevant
|
||||||
|
if (sig.isRevocation() || sigs.hasNext()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is our revocation, UNLESS there is a newer certificate!
|
||||||
|
if (latestCreation == null || latestCreation.before(sig.getCreationTime())) {
|
||||||
|
latestCreation = sig.getCreationTime();
|
||||||
|
seconds = sig.getKeyExpirySeconds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
seconds = mPublicKey.getValidSeconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
return seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getExpiryTime() {
|
||||||
|
long seconds = getValidSeconds();
|
||||||
|
|
||||||
|
if (seconds > Integer.MAX_VALUE) {
|
||||||
|
Log.e(Constants.TAG, "error, expiry time too large");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (seconds == 0) {
|
||||||
|
// no expiry
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Date creationDate = getCreationTime();
|
||||||
|
Calendar calendar = GregorianCalendar.getInstance();
|
||||||
|
calendar.setTime(creationDate);
|
||||||
|
calendar.add(Calendar.SECOND, (int) seconds);
|
||||||
|
|
||||||
|
return calendar.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
/** Same method as superclass, but we make it public. */
|
/** Same method as superclass, but we make it public. */
|
||||||
public Integer getKeyUsage() {
|
public Integer getKeyUsage() {
|
||||||
return super.getKeyUsage();
|
return super.getKeyUsage();
|
||||||
|
|||||||
@@ -439,8 +439,8 @@ public class PgpKeyOperation {
|
|||||||
// since this is the master key, this contains at least CERTIFY_OTHER
|
// since this is the master key, this contains at least CERTIFY_OTHER
|
||||||
PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
|
PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
|
||||||
int masterKeyFlags = readKeyFlags(masterPublicKey) | KeyFlags.CERTIFY_OTHER;
|
int masterKeyFlags = readKeyFlags(masterPublicKey) | KeyFlags.CERTIFY_OTHER;
|
||||||
long masterKeyExpiry = masterPublicKey.getValidSeconds() == 0L ? 0L :
|
Date expiryTime = wsKR.getPublicKey().getExpiryTime();
|
||||||
masterPublicKey.getCreationTime().getTime() / 1000 + masterPublicKey.getValidSeconds();
|
long masterKeyExpiry = expiryTime != null ? expiryTime.getTime() / 1000 : 0L;
|
||||||
|
|
||||||
return internal(sKR, masterSecretKey, masterKeyFlags, masterKeyExpiry, saveParcel, passphrase, log);
|
return internal(sKR, masterSecretKey, masterKeyFlags, masterKeyExpiry, saveParcel, passphrase, log);
|
||||||
|
|
||||||
|
|||||||
@@ -60,24 +60,6 @@ public class UncachedPublicKey {
|
|||||||
return mPublicKey.getCreationTime();
|
return mPublicKey.getCreationTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date getExpiryTime() {
|
|
||||||
long seconds = mPublicKey.getValidSeconds();
|
|
||||||
if (seconds > Integer.MAX_VALUE) {
|
|
||||||
Log.e(Constants.TAG, "error, expiry time too large");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (seconds == 0) {
|
|
||||||
// no expiry
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Date creationDate = getCreationTime();
|
|
||||||
Calendar calendar = GregorianCalendar.getInstance();
|
|
||||||
calendar.setTime(creationDate);
|
|
||||||
calendar.add(Calendar.SECOND, (int) seconds);
|
|
||||||
|
|
||||||
return calendar.getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isExpired() {
|
public boolean isExpired() {
|
||||||
Date creationDate = mPublicKey.getCreationTime();
|
Date creationDate = mPublicKey.getCreationTime();
|
||||||
Date expiryDate = mPublicKey.getValidSeconds() > 0
|
Date expiryDate = mPublicKey.getValidSeconds() > 0
|
||||||
|
|||||||
@@ -78,6 +78,10 @@ public class WrappedSignature {
|
|||||||
return mSig.getCreationTime();
|
return mSig.getCreationTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getKeyExpirySeconds() {
|
||||||
|
return mSig.getHashedSubPackets().getKeyExpirationTime();
|
||||||
|
}
|
||||||
|
|
||||||
public ArrayList<WrappedSignature> getEmbeddedSignatures() {
|
public ArrayList<WrappedSignature> getEmbeddedSignatures() {
|
||||||
ArrayList<WrappedSignature> sigs = new ArrayList<>();
|
ArrayList<WrappedSignature> sigs = new ArrayList<>();
|
||||||
if (!mSig.hasSubpackets()) {
|
if (!mSig.hasSubpackets()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user