use info from SecurityProblem class in health card
This commit is contained in:
parent
fed0fff9d7
commit
1e8d5bdad3
|
@ -145,7 +145,7 @@ public class PgpSecurityConstants {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
private static KeySecurityProblem getKeySecurityProblem(long masterKeyId, long subKeyId, int algorithm,
|
||||
public static KeySecurityProblem getKeySecurityProblem(long masterKeyId, long subKeyId, int algorithm,
|
||||
Integer bitStrength, String curveOid) {
|
||||
switch (algorithm) {
|
||||
case PublicKeyAlgorithmTags.RSA_GENERAL: {
|
||||
|
|
|
@ -62,6 +62,10 @@ public class KeyFormattingUtils {
|
|||
return getAlgorithmInfo(null, algorithm, keySize, oid);
|
||||
}
|
||||
|
||||
public static String getAlgorithmInfo(int algorithm) {
|
||||
return getAlgorithmInfo(null, algorithm, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on <a href="http://tools.ietf.org/html/rfc2440#section-9.1">OpenPGP Message Format</a>
|
||||
*/
|
||||
|
|
|
@ -32,6 +32,10 @@ import android.widget.ImageView;
|
|||
import android.widget.TextView;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureBitStrength;
|
||||
import org.sufficientlysecure.keychain.pgp.SecurityProblem.KeySecurityProblem;
|
||||
import org.sufficientlysecure.keychain.pgp.SecurityProblem.NotWhitelistedCurve;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.ui.widget.KeyHealthPresenter.KeyHealthClickListener;
|
||||
import org.sufficientlysecure.keychain.ui.widget.KeyHealthPresenter.KeyHealthMvpView;
|
||||
import org.sufficientlysecure.keychain.ui.widget.KeyHealthPresenter.KeyHealthStatus;
|
||||
|
@ -45,6 +49,9 @@ public class KeyHealthCardView extends CardView implements KeyHealthMvpView, OnC
|
|||
private final ImageView vExpander;
|
||||
private final KeyStatusList vKeyStatusList;
|
||||
private final View vKeyStatusDivider;
|
||||
private final View vInsecureLayout;
|
||||
private final TextView vInsecureProblem;
|
||||
private final TextView vInsecureSolution;
|
||||
|
||||
private KeyHealthClickListener keyHealthClickListener;
|
||||
|
||||
|
@ -63,9 +70,13 @@ public class KeyHealthCardView extends CardView implements KeyHealthMvpView, OnC
|
|||
|
||||
vKeyStatusDivider = view.findViewById(R.id.key_health_divider);
|
||||
vKeyStatusList = (KeyStatusList) view.findViewById(R.id.key_health_status_list);
|
||||
|
||||
vInsecureLayout = view.findViewById(R.id.key_insecure_layout);
|
||||
vInsecureProblem = (TextView) view.findViewById(R.id.key_insecure_problem);
|
||||
vInsecureSolution = (TextView) view.findViewById(R.id.key_insecure_solution);
|
||||
}
|
||||
|
||||
enum KeyHealthDisplayStatus {
|
||||
private enum KeyHealthDisplayStatus {
|
||||
OK (R.string.key_health_ok_title, R.string.key_health_ok_subtitle,
|
||||
R.drawable.ic_check_black_24dp, R.color.android_green_light),
|
||||
DIVERT (R.string.key_health_divert_title, R.string.key_health_divert_subtitle,
|
||||
|
@ -134,6 +145,26 @@ public class KeyHealthCardView extends CardView implements KeyHealthMvpView, OnC
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrimarySecurityProblem(KeySecurityProblem securityProblem) {
|
||||
vInsecureLayout.setVisibility(View.VISIBLE);
|
||||
|
||||
if (securityProblem instanceof InsecureBitStrength) {
|
||||
InsecureBitStrength insecureBitStrength = (InsecureBitStrength) securityProblem;
|
||||
vInsecureProblem.setText(getResources().getString(R.string.key_insecure_bitstrength_2048_problem,
|
||||
KeyFormattingUtils.getAlgorithmInfo(insecureBitStrength.algorithm),
|
||||
Integer.toString(insecureBitStrength.bitStrength)));
|
||||
vInsecureSolution.setText(R.string.key_insecure_bitstrength_2048_solution);
|
||||
} else if (securityProblem instanceof NotWhitelistedCurve) {
|
||||
NotWhitelistedCurve notWhitelistedCurve = (NotWhitelistedCurve) securityProblem;
|
||||
|
||||
String curveName = KeyFormattingUtils.getCurveInfo(getContext(), notWhitelistedCurve.curveOid);
|
||||
vInsecureProblem.setText(getResources().getString(R.string.key_insecure_unknown_curve_problem, curveName));
|
||||
vInsecureSolution.setText(R.string.key_insecure_unknown_curve_solution);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (keyHealthClickListener != null) {
|
||||
|
|
|
@ -27,6 +27,7 @@ import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
|||
import android.support.v4.content.Loader;
|
||||
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
|
||||
import org.sufficientlysecure.keychain.pgp.SecurityProblem.KeySecurityProblem;
|
||||
import org.sufficientlysecure.keychain.ui.widget.KeyStatusList.KeyDisplayStatus;
|
||||
import org.sufficientlysecure.keychain.ui.widget.SubkeyStatusLoader.KeySubkeyStatus;
|
||||
import org.sufficientlysecure.keychain.ui.widget.SubkeyStatusLoader.SubKeyItem;
|
||||
|
@ -45,8 +46,8 @@ public class KeyHealthPresenter implements LoaderCallbacks<KeySubkeyStatus> {
|
|||
if (usability != 0) {
|
||||
return usability;
|
||||
}
|
||||
if (one.mIsSecure ^ two.mIsSecure) {
|
||||
return one.mIsSecure ? -1 : 1;
|
||||
if ((one.mSecurityProblem == null) ^ (two.mSecurityProblem == null)) {
|
||||
return one.mSecurityProblem == null ? -1 : 1;
|
||||
}
|
||||
// otherwise, the newer one comes first
|
||||
return one.newerThan(two) ? -1 : 1;
|
||||
|
@ -94,11 +95,19 @@ public class KeyHealthPresenter implements LoaderCallbacks<KeySubkeyStatus> {
|
|||
this.subkeyStatus = subkeyStatus;
|
||||
|
||||
KeyHealthStatus keyHealthStatus = determineKeyHealthStatus(subkeyStatus);
|
||||
boolean forceExpanded = keyHealthStatus == KeyHealthStatus.INSECURE;
|
||||
if (forceExpanded) {
|
||||
view.setKeyStatus(keyHealthStatus);
|
||||
view.setShowExpander(false);
|
||||
displayExpandedInfo(false);
|
||||
|
||||
boolean isInsecure = keyHealthStatus == KeyHealthStatus.INSECURE;
|
||||
if (isInsecure) {
|
||||
boolean primaryKeySecurityProblem = subkeyStatus.keyCertify.mSecurityProblem != null;
|
||||
if (primaryKeySecurityProblem) {
|
||||
view.setKeyStatus(keyHealthStatus);
|
||||
view.setPrimarySecurityProblem(subkeyStatus.keyCertify.mSecurityProblem);
|
||||
view.setShowExpander(false);
|
||||
} else {
|
||||
view.setKeyStatus(keyHealthStatus);
|
||||
view.setShowExpander(false);
|
||||
displayExpandedInfo(false);
|
||||
}
|
||||
} else {
|
||||
view.setKeyStatus(keyHealthStatus);
|
||||
view.setShowExpander(
|
||||
|
@ -116,7 +125,7 @@ public class KeyHealthPresenter implements LoaderCallbacks<KeySubkeyStatus> {
|
|||
return KeyHealthStatus.EXPIRED;
|
||||
}
|
||||
|
||||
if (!keyCertify.mIsSecure) {
|
||||
if (keyCertify.mSecurityProblem != null) {
|
||||
return KeyHealthStatus.INSECURE;
|
||||
}
|
||||
|
||||
|
@ -126,7 +135,7 @@ public class KeyHealthPresenter implements LoaderCallbacks<KeySubkeyStatus> {
|
|||
return KeyHealthStatus.SPECIAL;
|
||||
}
|
||||
|
||||
if (!keySign.mIsSecure) {
|
||||
if (keySign.mSecurityProblem != null) {
|
||||
return KeyHealthStatus.INSECURE;
|
||||
}
|
||||
|
||||
|
@ -140,8 +149,8 @@ public class KeyHealthPresenter implements LoaderCallbacks<KeySubkeyStatus> {
|
|||
SubKeyItem keySign = subkeyStatus.keysSign.get(0);
|
||||
SubKeyItem keyEncrypt = subkeyStatus.keysEncrypt.get(0);
|
||||
|
||||
if (!keySign.mIsSecure && keySign.isValid()
|
||||
|| !keyEncrypt.mIsSecure && keyEncrypt.isValid()) {
|
||||
if (keySign.mSecurityProblem != null && keySign.isValid()
|
||||
|| keyEncrypt.mSecurityProblem != null && keyEncrypt.isValid()) {
|
||||
return KeyHealthStatus.INSECURE;
|
||||
}
|
||||
|
||||
|
@ -224,7 +233,7 @@ public class KeyHealthPresenter implements LoaderCallbacks<KeySubkeyStatus> {
|
|||
if (subKeyItem.mIsExpired) {
|
||||
return KeyDisplayStatus.EXPIRED;
|
||||
}
|
||||
if (!subKeyItem.mIsSecure) {
|
||||
if (subKeyItem.mSecurityProblem != null) {
|
||||
return KeyDisplayStatus.INSECURE;
|
||||
}
|
||||
if (subKeyItem.mSecretKeyType == SecretKeyType.GNU_DUMMY) {
|
||||
|
@ -243,13 +252,14 @@ public class KeyHealthPresenter implements LoaderCallbacks<KeySubkeyStatus> {
|
|||
|
||||
interface KeyHealthMvpView {
|
||||
void setKeyStatus(KeyHealthStatus keyHealthStatus);
|
||||
void setShowExpander(boolean showExpander);
|
||||
void setOnHealthClickListener(KeyHealthClickListener keyHealthClickListener);
|
||||
void setPrimarySecurityProblem(KeySecurityProblem securityProblem);
|
||||
|
||||
void setShowExpander(boolean showExpander);
|
||||
void showExpandedState(KeyDisplayStatus certifyStatus, KeyDisplayStatus signStatus,
|
||||
KeyDisplayStatus encryptStatus);
|
||||
|
||||
void hideExpandedInfo();
|
||||
|
||||
void setOnHealthClickListener(KeyHealthClickListener keyHealthClickListener);
|
||||
}
|
||||
|
||||
interface KeyStatusMvpView {
|
||||
|
|
|
@ -16,6 +16,8 @@ import android.util.Log;
|
|||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants;
|
||||
import org.sufficientlysecure.keychain.pgp.SecurityProblem.KeySecurityProblem;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
||||
import org.sufficientlysecure.keychain.ui.widget.SubkeyStatusLoader.KeySubkeyStatus;
|
||||
|
||||
|
@ -30,7 +32,9 @@ class SubkeyStatusLoader extends AsyncTaskLoader<KeySubkeyStatus> {
|
|||
Keys.HAS_SECRET,
|
||||
Keys.EXPIRY,
|
||||
Keys.IS_REVOKED,
|
||||
Keys.IS_SECURE
|
||||
Keys.ALGORITHM,
|
||||
Keys.KEY_SIZE,
|
||||
Keys.KEY_CURVE_OID
|
||||
};
|
||||
private static final int INDEX_KEY_ID = 0;
|
||||
private static final int INDEX_CREATION = 1;
|
||||
|
@ -40,7 +44,9 @@ class SubkeyStatusLoader extends AsyncTaskLoader<KeySubkeyStatus> {
|
|||
private static final int INDEX_HAS_SECRET = 5;
|
||||
private static final int INDEX_EXPIRY = 6;
|
||||
private static final int INDEX_IS_REVOKED = 7;
|
||||
private static final int INDEX_IS_SECURE = 8;
|
||||
private static final int INDEX_ALGORITHM = 8;
|
||||
private static final int INDEX_KEY_SIZE = 9;
|
||||
private static final int INDEX_KEY_CURVE_OID = 10;
|
||||
|
||||
|
||||
private final ContentResolver contentResolver;
|
||||
|
@ -71,7 +77,7 @@ class SubkeyStatusLoader extends AsyncTaskLoader<KeySubkeyStatus> {
|
|||
ArrayList<SubKeyItem> keysSign = new ArrayList<>();
|
||||
ArrayList<SubKeyItem> keysEncrypt = new ArrayList<>();
|
||||
while (cursor.moveToNext()) {
|
||||
SubKeyItem ski = new SubKeyItem(cursor);
|
||||
SubKeyItem ski = new SubKeyItem(masterKeyId, cursor);
|
||||
|
||||
if (ski.mKeyId == masterKeyId) {
|
||||
keyCertify = ski;
|
||||
|
@ -138,9 +144,9 @@ class SubkeyStatusLoader extends AsyncTaskLoader<KeySubkeyStatus> {
|
|||
final SecretKeyType mSecretKeyType;
|
||||
final boolean mIsRevoked, mIsExpired;
|
||||
final boolean mCanCertify, mCanSign, mCanEncrypt;
|
||||
final boolean mIsSecure;
|
||||
final KeySecurityProblem mSecurityProblem;
|
||||
|
||||
SubKeyItem(Cursor cursor) {
|
||||
SubKeyItem(long masterKeyId, Cursor cursor) {
|
||||
mPosition = cursor.getPosition();
|
||||
|
||||
mKeyId = cursor.getLong(INDEX_KEY_ID);
|
||||
|
@ -159,7 +165,12 @@ class SubkeyStatusLoader extends AsyncTaskLoader<KeySubkeyStatus> {
|
|||
mCanSign = cursor.getInt(INDEX_CAN_SIGN) > 0;
|
||||
mCanEncrypt = cursor.getInt(INDEX_CAN_ENCRYPT) > 0;
|
||||
|
||||
mIsSecure = cursor.getInt(INDEX_IS_SECURE) > 0;
|
||||
int algorithm = cursor.getInt(INDEX_ALGORITHM);
|
||||
Integer bitStrength = cursor.isNull(INDEX_KEY_SIZE) ? null : cursor.getInt(INDEX_KEY_SIZE);
|
||||
String curveOid = cursor.getString(INDEX_KEY_CURVE_OID);
|
||||
|
||||
mSecurityProblem = PgpSecurityConstants.getKeySecurityProblem(
|
||||
masterKeyId, mKeyId, algorithm, bitStrength, curveOid);
|
||||
}
|
||||
|
||||
boolean newerThan(SubKeyItem other) {
|
||||
|
|
|
@ -79,6 +79,52 @@
|
|||
android:id="@+id/key_health_divider"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:id="@+id/key_insecure_layout"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="Security Problem"
|
||||
android:textAppearance="@style/SectionHeader"
|
||||
android:layout_marginBottom="4dp"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:id="@+id/key_insecure_problem"
|
||||
tools:text="@string/key_insecure_bitstrength_2048_problem" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="Suggested Solution"
|
||||
android:textAppearance="@style/SectionHeader"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:id="@+id/key_insecure_solution"
|
||||
tools:text="@string/key_insecure_bitstrength_2048_solution" />
|
||||
</LinearLayout>
|
||||
|
||||
<org.sufficientlysecure.keychain.ui.widget.KeyStatusList
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -88,8 +134,8 @@
|
|||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
/>
|
||||
<!--tools:visibility="visible"-->
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
|
|
@ -1855,4 +1855,10 @@
|
|||
<string name="key_health_partial_stripped_title">"Healthy (Partially Stripped)"</string>
|
||||
<string name="key_health_partial_stripped_subtitle">"Click for details"</string>
|
||||
|
||||
<string name="key_insecure_bitstrength_2048_problem">"This key uses the <b>%1$s</b> algorithm with a strength of <b>%2$s bits</b>. A secure key should have a strength of 2048 bits."</string>
|
||||
<string name="key_insecure_bitstrength_2048_solution">"This key can\'t be upgraded. For secure communication, the owner must generate a new key."</string>
|
||||
|
||||
<string name="key_insecure_unknown_curve_problem">"This key uses the <b>%1$s</b> algorithm, which is not whitelisted."</string>
|
||||
<string name="key_insecure_unknown_curve_solution">"This key can\'t be upgraded. For secure communication, the owner must generate a new key."</string>
|
||||
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue