mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-12-24 07:58:50 -05:00
Big error screen if signature is invalid or key is revoked/expired, also fixes signature status for expired and revoked keys
This commit is contained in:
parent
2eb776594f
commit
0d6d4653b4
@ -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();
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
|
@ -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?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,73 +6,109 @@
|
||||
|
||||
<include layout="@layout/decrypt_result_include" />
|
||||
|
||||
<ScrollView
|
||||
android:fillViewport="true"
|
||||
android:paddingTop="8dp"
|
||||
android:layout_width="match_parent"
|
||||
android:scrollbars="vertical"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/decrypt_text_plaintext"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
android:hint=""
|
||||
android:textIsSelectable="true" />
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dip"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/action_decrypt_share_plaintext"
|
||||
android:visibility="gone"
|
||||
android:id="@+id/decrypt_text_valid"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:clickable="true"
|
||||
style="@style/SelectableItem"
|
||||
android:orientation="horizontal">
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:text="@string/btn_add_share_decrypted_text"
|
||||
android:drawableRight="@drawable/ic_action_share"
|
||||
android:drawablePadding="8dp"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_weight="1" />
|
||||
<ScrollView
|
||||
android:fillViewport="true"
|
||||
android:paddingTop="8dp"
|
||||
android:layout_width="match_parent"
|
||||
android:scrollbars="vertical"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/decrypt_text_plaintext"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
android:hint=""
|
||||
android:textIsSelectable="true" />
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<View
|
||||
android:layout_width="1dip"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="right"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dip"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/action_decrypt_copy_plaintext"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_action_copy"
|
||||
android:layout_gravity="center_vertical"
|
||||
style="@style/SelectableItem" />
|
||||
<LinearLayout
|
||||
android:id="@+id/action_decrypt_share_plaintext"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:clickable="true"
|
||||
style="@style/SelectableItem"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:text="@string/btn_add_share_decrypted_text"
|
||||
android:drawableRight="@drawable/ic_action_share"
|
||||
android:drawablePadding="8dp"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<View
|
||||
android:layout_width="1dip"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="right"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/action_decrypt_copy_plaintext"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_action_copy"
|
||||
android:layout_gravity="center_vertical"
|
||||
style="@style/SelectableItem" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:visibility="gone"
|
||||
android:id="@+id/decrypt_text_invalid"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:text="@string/decrypt_invalid_text"
|
||||
android:padding="8dp"
|
||||
android:layout_gravity="center"
|
||||
android:textColor="@color/android_red_dark" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/decrypt_text_invalid_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/button_edgy"
|
||||
android:textColor="@color/android_red_dark"
|
||||
android:text="@string/decrypt_invalid_button"
|
||||
android:layout_gravity="center_horizontal" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
@ -277,6 +277,8 @@
|
||||
<string name="decrypt_result_not_encrypted">"Not Encrypted"</string>
|
||||
<string name="decrypt_result_action_show">"Show"</string>
|
||||
<string name="decrypt_result_action_Lookup">"Lookup"</string>
|
||||
<string name="decrypt_invalid_text">"Either the signature is invalid or the key has been revoked/is expired. You can not be sure who wrote the text. Do you still want to display it?"</string>
|
||||
<string name="decrypt_invalid_button">"I understand the risks, display it!"</string>
|
||||
|
||||
<!-- Add keys -->
|
||||
<string name="add_keys_section_secure_exchange">"Exchange"</string>
|
||||
|
Loading…
Reference in New Issue
Block a user