Experimental support for revoked, expired keys with signatures

This commit is contained in:
Dominik Schürmann 2014-09-01 00:14:59 +02:00
parent 40e6b24b14
commit a64443e71f
2 changed files with 66 additions and 36 deletions

View File

@ -21,6 +21,8 @@ import org.openintents.openpgp.OpenPgpSignatureResult;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import java.util.ArrayList;
/** /**
* This class can be used to build OpenPgpSignatureResult objects based on several checks. * This class can be used to build OpenPgpSignatureResult objects based on several checks.
* It serves as a constraint which information are returned inside an OpenPgpSignatureResult object. * It serves as a constraint which information are returned inside an OpenPgpSignatureResult object.
@ -28,7 +30,8 @@ import org.sufficientlysecure.keychain.util.Log;
public class OpenPgpSignatureResultBuilder { public class OpenPgpSignatureResultBuilder {
// OpenPgpSignatureResult // OpenPgpSignatureResult
private boolean mSignatureOnly = false; private boolean mSignatureOnly = false;
private String mUserId; private String mPrimaryUserId;
private ArrayList<String> mUserIds = new ArrayList<String>();
private long mKeyId; private long mKeyId;
// builder // builder
@ -36,35 +39,49 @@ public class OpenPgpSignatureResultBuilder {
private boolean mKnownKey = false; private boolean mKnownKey = false;
private boolean mValidSignature = false; private boolean mValidSignature = false;
private boolean mIsSignatureKeyCertified = false; private boolean mIsSignatureKeyCertified = false;
private boolean mIsKeyRevoked = false;
private boolean mIsKeyExpired = false;
public void signatureOnly(boolean signatureOnly) { public void setSignatureOnly(boolean signatureOnly) {
this.mSignatureOnly = signatureOnly; this.mSignatureOnly = signatureOnly;
} }
public void userId(String userId) { public void setPrimaryUserId(String userId) {
this.mUserId = userId; this.mPrimaryUserId = userId;
} }
public void keyId(long keyId) { public void setKeyId(long keyId) {
this.mKeyId = keyId; this.mKeyId = keyId;
} }
public void knownKey(boolean knownKey) { public void setKnownKey(boolean knownKey) {
this.mKnownKey = knownKey; this.mKnownKey = knownKey;
} }
public void validSignature(boolean validSignature) { public void setValidSignature(boolean validSignature) {
this.mValidSignature = validSignature; this.mValidSignature = validSignature;
} }
public void signatureKeyCertified(boolean isSignatureKeyCertified) { public void setSignatureKeyCertified(boolean isSignatureKeyCertified) {
this.mIsSignatureKeyCertified = isSignatureKeyCertified; this.mIsSignatureKeyCertified = isSignatureKeyCertified;
} }
public void signatureAvailable(boolean signatureAvailable) { public void setSignatureAvailable(boolean signatureAvailable) {
this.mSignatureAvailable = signatureAvailable; this.mSignatureAvailable = signatureAvailable;
} }
public void setKeyRevoked(boolean keyRevoked) {
this.mIsKeyRevoked = keyRevoked;
}
public void setKeyExpired(boolean keyExpired) {
this.mIsKeyExpired = keyExpired;
}
public void setUserIds(ArrayList<String> userIds) {
this.mUserIds = userIds;
}
public boolean isValidSignature() { public boolean isValidSignature() {
return mValidSignature; return mValidSignature;
} }
@ -78,9 +95,16 @@ public class OpenPgpSignatureResultBuilder {
if (mKnownKey) { if (mKnownKey) {
if (mValidSignature) { if (mValidSignature) {
result.setKeyId(mKeyId); result.setKeyId(mKeyId);
result.setPrimaryUserId(mUserId); result.setPrimaryUserId(mPrimaryUserId);
result.setUserIds(mUserIds);
if (mIsSignatureKeyCertified) { if (mIsKeyRevoked) {
Log.d(Constants.TAG, "SIGNATURE_KEY_REVOKED");
result.setStatus(OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED);
} else if (mIsKeyExpired) {
Log.d(Constants.TAG, "SIGNATURE_KEY_EXPIRED");
result.setStatus(OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED);
} else if (mIsSignatureKeyCertified) {
Log.d(Constants.TAG, "SIGNATURE_SUCCESS_CERTIFIED"); Log.d(Constants.TAG, "SIGNATURE_SUCCESS_CERTIFIED");
result.setStatus(OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED); result.setStatus(OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED);
} else { } else {

View File

@ -38,6 +38,7 @@ import org.spongycastle.openpgp.PGPUtil;
import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory; import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory;
import org.spongycastle.openpgp.operator.PGPDigestCalculatorProvider; import org.spongycastle.openpgp.operator.PGPDigestCalculatorProvider;
import org.spongycastle.openpgp.operator.PublicKeyDataDecryptorFactory; import org.spongycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder; import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
import org.spongycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder; import org.spongycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder;
@ -46,7 +47,6 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ProgressScaler; import org.sufficientlysecure.keychain.util.ProgressScaler;
@ -226,7 +226,7 @@ public class PgpDecryptVerify {
InvalidDataException, IntegrityCheckFailedException { InvalidDataException, IntegrityCheckFailedException {
PgpDecryptVerifyResult result = new PgpDecryptVerifyResult(); PgpDecryptVerifyResult result = new PgpDecryptVerifyResult();
PGPObjectFactory pgpF = new PGPObjectFactory(in); PGPObjectFactory pgpF = new PGPObjectFactory(in, new JcaKeyFingerprintCalculator());
PGPEncryptedDataList enc; PGPEncryptedDataList enc;
Object o = pgpF.nextObject(); Object o = pgpF.nextObject();
@ -377,7 +377,7 @@ public class PgpDecryptVerify {
throw new NoSecretKeyException(); throw new NoSecretKeyException();
} }
PGPObjectFactory plainFact = new PGPObjectFactory(clear); PGPObjectFactory plainFact = new PGPObjectFactory(clear, new JcaKeyFingerprintCalculator());
Object dataChunk = plainFact.nextObject(); Object dataChunk = plainFact.nextObject();
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder(); OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
int signatureIndex = -1; int signatureIndex = -1;
@ -390,7 +390,7 @@ public class PgpDecryptVerify {
PGPCompressedData compressedData = (PGPCompressedData) dataChunk; PGPCompressedData compressedData = (PGPCompressedData) dataChunk;
PGPObjectFactory fact = new PGPObjectFactory(compressedData.getDataStream()); PGPObjectFactory fact = new PGPObjectFactory(compressedData.getDataStream(), new JcaKeyFingerprintCalculator());
dataChunk = fact.nextObject(); dataChunk = fact.nextObject();
plainFact = fact; plainFact = fact;
} }
@ -421,15 +421,18 @@ public class PgpDecryptVerify {
// key found in our database! // key found in our database!
signature = sigList.get(signatureIndex); signature = sigList.get(signatureIndex);
signatureResultBuilder.signatureAvailable(true); signatureResultBuilder.setSignatureAvailable(true);
signatureResultBuilder.knownKey(true); signatureResultBuilder.setKnownKey(true);
signatureResultBuilder.keyId(signingRing.getMasterKeyId()); signatureResultBuilder.setKeyId(signingRing.getMasterKeyId());
try { try {
signatureResultBuilder.userId(signingRing.getPrimaryUserIdWithFallback()); signatureResultBuilder.setPrimaryUserId(signingRing.getPrimaryUserIdWithFallback());
} catch (PgpGeneralException e) { } catch (PgpGeneralException e) {
Log.d(Constants.TAG, "No primary user id in keyring with master key id " + signingRing.getMasterKeyId()); Log.d(Constants.TAG, "No primary user id in keyring with master key id " + signingRing.getMasterKeyId());
} }
signatureResultBuilder.signatureKeyCertified(signingRing.getVerified() > 0); signatureResultBuilder.setSignatureKeyCertified(signingRing.getVerified() > 0);
signatureResultBuilder.setKeyExpired(signingKey.isExpired());
signatureResultBuilder.setKeyRevoked(signingKey.isRevoked());
signatureResultBuilder.setUserIds(signingKey.getUnorderedUserIds());
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
new JcaPGPContentVerifierBuilderProvider() new JcaPGPContentVerifierBuilderProvider()
@ -438,9 +441,9 @@ public class PgpDecryptVerify {
} else { } else {
// no key in our database -> return "unknown pub key" status including the first key id // no key in our database -> return "unknown pub key" status including the first key id
if (!sigList.isEmpty()) { if (!sigList.isEmpty()) {
signatureResultBuilder.signatureAvailable(true); signatureResultBuilder.setSignatureAvailable(true);
signatureResultBuilder.knownKey(false); signatureResultBuilder.setKnownKey(false);
signatureResultBuilder.keyId(sigList.get(0).getKeyID()); signatureResultBuilder.setKeyId(sigList.get(0).getKeyID());
} }
} }
@ -547,11 +550,11 @@ public class PgpDecryptVerify {
// these are not cleartext signatures! // these are not cleartext signatures!
// TODO: what about binary signatures? // TODO: what about binary signatures?
signatureResultBuilder.signatureOnly(false); signatureResultBuilder.setSignatureOnly(false);
// Verify signature and check binding signatures // Verify signature and check binding signatures
boolean validSignature = signature.verify(messageSignature); boolean validSignature = signature.verify(messageSignature);
signatureResultBuilder.validSignature(validSignature); signatureResultBuilder.setValidSignature(validSignature);
} }
} }
@ -596,7 +599,7 @@ public class PgpDecryptVerify {
PgpDecryptVerifyResult result = new PgpDecryptVerifyResult(); PgpDecryptVerifyResult result = new PgpDecryptVerifyResult();
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder(); OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
// cleartext signatures are never encrypted ;) // cleartext signatures are never encrypted ;)
signatureResultBuilder.signatureOnly(true); signatureResultBuilder.setSignatureOnly(true);
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
@ -623,7 +626,7 @@ public class PgpDecryptVerify {
mOutStream.write(clearText); mOutStream.write(clearText);
updateProgress(R.string.progress_processing_signature, 60, 100); updateProgress(R.string.progress_processing_signature, 60, 100);
PGPObjectFactory pgpFact = new PGPObjectFactory(aIn); PGPObjectFactory pgpFact = new PGPObjectFactory(aIn, new JcaKeyFingerprintCalculator());
PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject(); PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject();
if (sigList == null) { if (sigList == null) {
@ -655,15 +658,18 @@ public class PgpDecryptVerify {
// key found in our database! // key found in our database!
signature = sigList.get(signatureIndex); signature = sigList.get(signatureIndex);
signatureResultBuilder.signatureAvailable(true); signatureResultBuilder.setSignatureAvailable(true);
signatureResultBuilder.knownKey(true); signatureResultBuilder.setKnownKey(true);
signatureResultBuilder.keyId(signingRing.getMasterKeyId()); signatureResultBuilder.setKeyId(signingRing.getMasterKeyId());
try { try {
signatureResultBuilder.userId(signingRing.getPrimaryUserIdWithFallback()); signatureResultBuilder.setPrimaryUserId(signingRing.getPrimaryUserIdWithFallback());
} catch (PgpGeneralException e) { } catch (PgpGeneralException e) {
Log.d(Constants.TAG, "No primary user id in key with master key id " + signingRing.getMasterKeyId()); Log.d(Constants.TAG, "No primary user id in key with master key id " + signingRing.getMasterKeyId());
} }
signatureResultBuilder.signatureKeyCertified(signingRing.getVerified() > 0); signatureResultBuilder.setSignatureKeyCertified(signingRing.getVerified() > 0);
signatureResultBuilder.setKeyExpired(signingKey.isExpired());
signatureResultBuilder.setKeyRevoked(signingKey.isRevoked());
signatureResultBuilder.setUserIds(signingKey.getUnorderedUserIds());
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
new JcaPGPContentVerifierBuilderProvider() new JcaPGPContentVerifierBuilderProvider()
@ -672,9 +678,9 @@ public class PgpDecryptVerify {
} else { } else {
// no key in our database -> return "unknown pub key" status including the first key id // no key in our database -> return "unknown pub key" status including the first key id
if (!sigList.isEmpty()) { if (!sigList.isEmpty()) {
signatureResultBuilder.signatureAvailable(true); signatureResultBuilder.setSignatureAvailable(true);
signatureResultBuilder.knownKey(false); signatureResultBuilder.setKnownKey(false);
signatureResultBuilder.keyId(sigList.get(0).getKeyID()); signatureResultBuilder.setKeyId(sigList.get(0).getKeyID());
} }
} }
@ -701,7 +707,7 @@ public class PgpDecryptVerify {
// Verify signature and check binding signatures // Verify signature and check binding signatures
boolean validSignature = signature.verify(); boolean validSignature = signature.verify();
signatureResultBuilder.validSignature(validSignature); signatureResultBuilder.setValidSignature(validSignature);
} }
result.setSignatureResult(signatureResultBuilder.build()); result.setSignatureResult(signatureResultBuilder.build());