From a64443e71fbd5c7976b0986686deff5b1bc846e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 1 Sep 2014 00:14:59 +0200 Subject: [PATCH] Experimental support for revoked, expired keys with signatures --- .../pgp/OpenPgpSignatureResultBuilder.java | 46 +++++++++++---- .../keychain/pgp/PgpDecryptVerify.java | 56 ++++++++++--------- 2 files changed, 66 insertions(+), 36 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java index a6a15d2e9..ab88d1b4b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java @@ -21,6 +21,8 @@ import org.openintents.openpgp.OpenPgpSignatureResult; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.util.Log; +import java.util.ArrayList; + /** * 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. @@ -28,7 +30,8 @@ import org.sufficientlysecure.keychain.util.Log; public class OpenPgpSignatureResultBuilder { // OpenPgpSignatureResult private boolean mSignatureOnly = false; - private String mUserId; + private String mPrimaryUserId; + private ArrayList mUserIds = new ArrayList(); private long mKeyId; // builder @@ -36,35 +39,49 @@ public class OpenPgpSignatureResultBuilder { private boolean mKnownKey = false; private boolean mValidSignature = 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; } - public void userId(String userId) { - this.mUserId = userId; + public void setPrimaryUserId(String userId) { + this.mPrimaryUserId = userId; } - public void keyId(long keyId) { + public void setKeyId(long keyId) { this.mKeyId = keyId; } - public void knownKey(boolean knownKey) { + public void setKnownKey(boolean knownKey) { this.mKnownKey = knownKey; } - public void validSignature(boolean validSignature) { + public void setValidSignature(boolean validSignature) { this.mValidSignature = validSignature; } - public void signatureKeyCertified(boolean isSignatureKeyCertified) { + public void setSignatureKeyCertified(boolean isSignatureKeyCertified) { this.mIsSignatureKeyCertified = isSignatureKeyCertified; } - public void signatureAvailable(boolean signatureAvailable) { + public void setSignatureAvailable(boolean signatureAvailable) { this.mSignatureAvailable = signatureAvailable; } + public void setKeyRevoked(boolean keyRevoked) { + this.mIsKeyRevoked = keyRevoked; + } + + public void setKeyExpired(boolean keyExpired) { + this.mIsKeyExpired = keyExpired; + } + + public void setUserIds(ArrayList userIds) { + this.mUserIds = userIds; + } + public boolean isValidSignature() { return mValidSignature; } @@ -78,9 +95,16 @@ public class OpenPgpSignatureResultBuilder { if (mKnownKey) { if (mValidSignature) { 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"); result.setStatus(OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED); } else { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index 828bee848..11e986562 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -38,6 +38,7 @@ import org.spongycastle.openpgp.PGPUtil; import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory; import org.spongycastle.openpgp.operator.PGPDigestCalculatorProvider; 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.JcaPGPDigestCalculatorProviderBuilder; 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.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ProgressScaler; @@ -226,7 +226,7 @@ public class PgpDecryptVerify { InvalidDataException, IntegrityCheckFailedException { PgpDecryptVerifyResult result = new PgpDecryptVerifyResult(); - PGPObjectFactory pgpF = new PGPObjectFactory(in); + PGPObjectFactory pgpF = new PGPObjectFactory(in, new JcaKeyFingerprintCalculator()); PGPEncryptedDataList enc; Object o = pgpF.nextObject(); @@ -377,7 +377,7 @@ public class PgpDecryptVerify { throw new NoSecretKeyException(); } - PGPObjectFactory plainFact = new PGPObjectFactory(clear); + PGPObjectFactory plainFact = new PGPObjectFactory(clear, new JcaKeyFingerprintCalculator()); Object dataChunk = plainFact.nextObject(); OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder(); int signatureIndex = -1; @@ -390,7 +390,7 @@ public class PgpDecryptVerify { PGPCompressedData compressedData = (PGPCompressedData) dataChunk; - PGPObjectFactory fact = new PGPObjectFactory(compressedData.getDataStream()); + PGPObjectFactory fact = new PGPObjectFactory(compressedData.getDataStream(), new JcaKeyFingerprintCalculator()); dataChunk = fact.nextObject(); plainFact = fact; } @@ -421,15 +421,18 @@ public class PgpDecryptVerify { // key found in our database! signature = sigList.get(signatureIndex); - signatureResultBuilder.signatureAvailable(true); - signatureResultBuilder.knownKey(true); - signatureResultBuilder.keyId(signingRing.getMasterKeyId()); + signatureResultBuilder.setSignatureAvailable(true); + signatureResultBuilder.setKnownKey(true); + signatureResultBuilder.setKeyId(signingRing.getMasterKeyId()); try { - signatureResultBuilder.userId(signingRing.getPrimaryUserIdWithFallback()); + signatureResultBuilder.setPrimaryUserId(signingRing.getPrimaryUserIdWithFallback()); } catch (PgpGeneralException e) { 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 = new JcaPGPContentVerifierBuilderProvider() @@ -438,9 +441,9 @@ public class PgpDecryptVerify { } else { // no key in our database -> return "unknown pub key" status including the first key id if (!sigList.isEmpty()) { - signatureResultBuilder.signatureAvailable(true); - signatureResultBuilder.knownKey(false); - signatureResultBuilder.keyId(sigList.get(0).getKeyID()); + signatureResultBuilder.setSignatureAvailable(true); + signatureResultBuilder.setKnownKey(false); + signatureResultBuilder.setKeyId(sigList.get(0).getKeyID()); } } @@ -547,11 +550,11 @@ public class PgpDecryptVerify { // these are not cleartext signatures! // TODO: what about binary signatures? - signatureResultBuilder.signatureOnly(false); + signatureResultBuilder.setSignatureOnly(false); // Verify signature and check binding signatures boolean validSignature = signature.verify(messageSignature); - signatureResultBuilder.validSignature(validSignature); + signatureResultBuilder.setValidSignature(validSignature); } } @@ -596,7 +599,7 @@ public class PgpDecryptVerify { PgpDecryptVerifyResult result = new PgpDecryptVerifyResult(); OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder(); // cleartext signatures are never encrypted ;) - signatureResultBuilder.signatureOnly(true); + signatureResultBuilder.setSignatureOnly(true); ByteArrayOutputStream out = new ByteArrayOutputStream(); @@ -623,7 +626,7 @@ public class PgpDecryptVerify { mOutStream.write(clearText); 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(); if (sigList == null) { @@ -655,15 +658,18 @@ public class PgpDecryptVerify { // key found in our database! signature = sigList.get(signatureIndex); - signatureResultBuilder.signatureAvailable(true); - signatureResultBuilder.knownKey(true); - signatureResultBuilder.keyId(signingRing.getMasterKeyId()); + signatureResultBuilder.setSignatureAvailable(true); + signatureResultBuilder.setKnownKey(true); + signatureResultBuilder.setKeyId(signingRing.getMasterKeyId()); try { - signatureResultBuilder.userId(signingRing.getPrimaryUserIdWithFallback()); + signatureResultBuilder.setPrimaryUserId(signingRing.getPrimaryUserIdWithFallback()); } catch (PgpGeneralException e) { 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 = new JcaPGPContentVerifierBuilderProvider() @@ -672,9 +678,9 @@ public class PgpDecryptVerify { } else { // no key in our database -> return "unknown pub key" status including the first key id if (!sigList.isEmpty()) { - signatureResultBuilder.signatureAvailable(true); - signatureResultBuilder.knownKey(false); - signatureResultBuilder.keyId(sigList.get(0).getKeyID()); + signatureResultBuilder.setSignatureAvailable(true); + signatureResultBuilder.setKnownKey(false); + signatureResultBuilder.setKeyId(sigList.get(0).getKeyID()); } } @@ -701,7 +707,7 @@ public class PgpDecryptVerify { // Verify signature and check binding signatures boolean validSignature = signature.verify(); - signatureResultBuilder.validSignature(validSignature); + signatureResultBuilder.setValidSignature(validSignature); } result.setSignatureResult(signatureResultBuilder.build());