From 0d6d4653b43fcf1389b470afd7364854505d96c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 8 Oct 2014 18:31:31 +0200 Subject: [PATCH] Big error screen if signature is invalid or key is revoked/expired, also fixes signature status for expired and revoked keys --- .../keychain/pgp/CanonicalizedKeyRing.java | 11 ++ .../pgp/OpenPgpSignatureResultBuilder.java | 11 +- .../keychain/ui/DecryptFragment.java | 77 +++++---- .../keychain/ui/DecryptTextFragment.java | 27 ++- .../main/res/layout/decrypt_text_fragment.xml | 156 +++++++++++------- OpenKeychain/src/main/res/values/strings.xml | 2 + 6 files changed, 188 insertions(+), 96 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java index 905cae17e..b1e7eaeb5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java @@ -25,6 +25,7 @@ import org.sufficientlysecure.keychain.util.IterableIterator; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Date; /** A generic wrapped PGPKeyRing object. * @@ -76,6 +77,16 @@ public abstract class CanonicalizedKeyRing extends KeyRing { return getRing().getPublicKey().isRevoked(); } + public boolean isExpired() throws PgpGeneralException { + // Is the master key expired? + Date creationDate = getRing().getPublicKey().getCreationTime(); + Date expiryDate = getRing().getPublicKey().getValidSeconds() > 0 + ? new Date(creationDate.getTime() + getRing().getPublicKey().getValidSeconds() * 1000) : null; + + Date now = new Date(); + return creationDate.after(now) || (expiryDate != null && expiryDate.before(now)); + } + public boolean canCertify() throws PgpGeneralException { return getRing().getPublicKey().isEncryptionKey(); } 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 3d41c928b..c7241c723 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java @@ -103,9 +103,14 @@ public class OpenPgpSignatureResultBuilder { Log.d(Constants.TAG, "signingRing.getUnorderedUserIds(): " + signingRing.getUnorderedUserIds()); setUserIds(signingRing.getUnorderedUserIds()); - // from KEY - setKeyExpired(signingKey.isExpired()); - setKeyRevoked(signingKey.isRevoked()); + // either master key is expired/revoked or this specific subkey is expired/revoked + try { + setKeyExpired(signingRing.isExpired() || signingKey.isExpired()); + setKeyRevoked(signingRing.isRevoked() || signingKey.isRevoked()); + } catch (PgpGeneralException e) { + Log.e(Constants.TAG, "shouldn't happen!"); + setKeyRevoked(true); + } } public OpenPgpSignatureResult build() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java index 3bd028da4..b7d204851 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java @@ -112,9 +112,15 @@ public abstract class DecryptFragment extends Fragment { startActivityForResult(intent, REQUEST_CODE_NFC_DECRYPT); } - protected void onResult(DecryptVerifyResult decryptVerifyResult) { + /** + * + * @return returns false if signature is invalid, key is revoked or expired. + */ + protected boolean onResult(DecryptVerifyResult decryptVerifyResult) { final OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult(); + boolean valid = false; + mSignatureKeyId = 0; mResultLayout.setVisibility(View.VISIBLE); if (signatureResult != null) { @@ -147,14 +153,9 @@ public abstract class DecryptFragment extends Fragment { KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_VERIFIED); setSignatureLayoutVisibility(View.VISIBLE); - mSignatureAction.setText(R.string.decrypt_result_action_show); - mSignatureAction.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_action_accounts, 0); - mSignatureLayout.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - showKey(mSignatureKeyId); - } - }); + setShowAction(mSignatureKeyId); + + valid = true; break; } @@ -163,25 +164,9 @@ public abstract class DecryptFragment extends Fragment { KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_UNVERIFIED); setSignatureLayoutVisibility(View.VISIBLE); - setShowAction(mSignatureAction, mSignatureKeyId); - break; - } + setShowAction(mSignatureKeyId); - case OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED: { - mSignatureText.setText(R.string.decrypt_result_signature_expired_key); - KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_EXPIRED); - - setSignatureLayoutVisibility(View.VISIBLE); - setShowAction(mSignatureAction, mSignatureKeyId); - break; - } - - case OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED: { - mSignatureText.setText(R.string.decrypt_result_signature_revoked_key); - KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_REVOKED); - - setSignatureLayoutVisibility(View.VISIBLE); - setShowAction(mSignatureAction, mSignatureKeyId); + valid = true; break; } @@ -198,6 +183,30 @@ public abstract class DecryptFragment extends Fragment { lookupUnknownKey(mSignatureKeyId); } }); + + valid = true; + break; + } + + case OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED: { + mSignatureText.setText(R.string.decrypt_result_signature_expired_key); + KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_EXPIRED); + + setSignatureLayoutVisibility(View.VISIBLE); + setShowAction(mSignatureKeyId); + + valid = false; + break; + } + + case OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED: { + mSignatureText.setText(R.string.decrypt_result_signature_revoked_key); + KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_REVOKED); + + setSignatureLayoutVisibility(View.VISIBLE); + setShowAction(mSignatureKeyId); + + valid = false; break; } @@ -206,6 +215,8 @@ public abstract class DecryptFragment extends Fragment { KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_INVALID); setSignatureLayoutVisibility(View.GONE); + + valid = false; break; } } @@ -216,7 +227,11 @@ public abstract class DecryptFragment extends Fragment { KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_NOT_SIGNED); mEncryptionText.setText(R.string.decrypt_result_encrypted); KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, KeyFormattingUtils.STATE_ENCRYPTED); + + valid = true; } + + return valid; } private void setSignatureLayoutVisibility(int visibility) { @@ -225,10 +240,10 @@ public abstract class DecryptFragment extends Fragment { mSignatureDivider2.setVisibility(visibility); } - private void setShowAction(TextView signatureAction, final long signatureKeyId) { - signatureAction.setText(R.string.decrypt_result_action_show); - signatureAction.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_action_accounts, 0); - signatureAction.setOnClickListener(new View.OnClickListener() { + private void setShowAction(final long signatureKeyId) { + mSignatureAction.setText(R.string.decrypt_result_action_show); + mSignatureAction.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_action_accounts, 0); + mSignatureLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showKey(signatureKeyId); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java index 4f25126ee..78345e11c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java @@ -27,6 +27,8 @@ import android.text.method.ScrollingMovementMethod; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; +import android.widget.LinearLayout; import android.widget.TextView; import org.openintents.openpgp.util.OpenPgpApi; @@ -44,6 +46,9 @@ public class DecryptTextFragment extends DecryptFragment { public static final String ARG_CIPHERTEXT = "ciphertext"; // view + private LinearLayout mValidLayout; + private LinearLayout mInvalidLayout; + private Button mInvalidButton; private TextView mText; private View mShareButton; private View mCopyButton; @@ -71,7 +76,9 @@ public class DecryptTextFragment extends DecryptFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.decrypt_text_fragment, container, false); - + mValidLayout = (LinearLayout) view.findViewById(R.id.decrypt_text_valid); + mInvalidLayout = (LinearLayout) view.findViewById(R.id.decrypt_text_invalid); + mInvalidButton = (Button) view.findViewById(R.id.decrypt_text_invalid_button); mText = (TextView) view.findViewById(R.id.decrypt_text_plaintext); mShareButton = view.findViewById(R.id.action_decrypt_share_plaintext); mCopyButton = view.findViewById(R.id.action_decrypt_copy_plaintext); @@ -87,6 +94,13 @@ public class DecryptTextFragment extends DecryptFragment { copyToClipboard(mText.getText().toString()); } }); + mInvalidButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mInvalidLayout.setVisibility(View.GONE); + mValidLayout.setVisibility(View.VISIBLE); + } + }); return view; } @@ -186,9 +200,18 @@ public class DecryptTextFragment extends DecryptFragment { pgpResult.createNotify(getActivity()).show(); // display signature result in activity - onResult(pgpResult); + boolean valid = onResult(pgpResult); + + if (valid) { + mInvalidLayout.setVisibility(View.GONE); + mValidLayout.setVisibility(View.VISIBLE); + } else { + mInvalidLayout.setVisibility(View.VISIBLE); + mValidLayout.setVisibility(View.GONE); + } } else { pgpResult.createNotify(getActivity()).show(); + // TODO: show also invalid layout with different text? } } } diff --git a/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml b/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml index 3bd144fbf..c58e2d7e6 100644 --- a/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml +++ b/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml @@ -6,73 +6,109 @@ - - - - - - - - + android:layout_height="match_parent" + android:orientation="vertical"> - + + + + + - + + + + + + + + + + + + + + +