1
0
Fork 0
mirror of https://github.com/M66B/FairEmail.git synced 2024-12-21 23:32:51 +00:00

Show public key usage

This commit is contained in:
M66B 2024-12-21 08:18:13 +01:00
parent 99c07f6b60
commit 1d39f2f40f
4 changed files with 73 additions and 25 deletions

View file

@ -23,6 +23,7 @@ import android.content.Context;
import android.graphics.Typeface;
import android.os.Bundle;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan;
import android.view.LayoutInflater;
@ -68,6 +69,7 @@ public class AdapterCertificate extends RecyclerView.Adapter<AdapterCertificate.
private TextView tvEmail;
private ImageView ivIntermediate;
private TextView tvSubject;
private TextView tvKeyUsage;
private TextView tvAfter;
private TextView tvBefore;
private TextView tvExpired;
@ -81,6 +83,7 @@ public class AdapterCertificate extends RecyclerView.Adapter<AdapterCertificate.
tvEmail = itemView.findViewById(R.id.tvEmail);
ivIntermediate = itemView.findViewById(R.id.ivIntermediate);
tvSubject = itemView.findViewById(R.id.tvSubject);
tvKeyUsage = itemView.findViewById(R.id.tvKeyUsage);
tvAfter = itemView.findViewById(R.id.tvAfter);
tvBefore = itemView.findViewById(R.id.tvBefore);
tvExpired = itemView.findViewById(R.id.tvExpired);
@ -195,11 +198,19 @@ public class AdapterCertificate extends RecyclerView.Adapter<AdapterCertificate.
tvEmail.setText(certificate.email);
tvEmail.setTypeface(certificate.intermediate ? Typeface.DEFAULT : Typeface.DEFAULT_BOLD);
ivIntermediate.setVisibility(certificate.intermediate ? View.VISIBLE : View.INVISIBLE);
String subject = certificate.subject;
String algo = certificate.getSigAlgName();
if (algo != null)
subject = algo.replaceAll("(?i)With", "/") + " " + subject;
tvSubject.setText(subject);
List<String> usage = certificate.getKeyUsage();
if (certificate.isSelfSigned())
usage.add(0, "selfSigned");
tvKeyUsage.setText(TextUtils.join(", ", usage));
tvKeyUsage.setVisibility(usage.isEmpty() ? View.GONE : View.VISIBLE);
tvAfter.setText(certificate.after == null ? null : TF.format(certificate.after));
tvBefore.setText(certificate.before == null ? null : TF.format(certificate.before));
tvExpired.setVisibility(certificate.isExpired() ? View.VISIBLE : View.GONE);

View file

@ -49,6 +49,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
@ -126,6 +127,47 @@ public class EntityCertificate {
}
}
List<String> getKeyUsage() {
List<String> result = new ArrayList<>();
try {
X509Certificate cert = getCertificate();
boolean[] usage = cert.getKeyUsage();
if (usage == null)
return result;
if (usage.length > 0 && usage[0])
result.add("digitalSignature");
if (usage.length > 1 && usage[1])
result.add("nonRepudiation");
if (usage.length > 2 && usage[2])
result.add("keyEncipherment");
if (usage.length > 3 && usage[3])
result.add("dataEncipherment");
if (usage.length > 4 && usage[4])
result.add("keyAgreement");
if (usage.length > 5 && usage[5])
result.add("keyCertSign");
if (usage.length > 6 && usage[6])
result.add("cRLSign");
if (usage.length > 7 && usage[7])
result.add("encipherOnly");
if (usage.length > 8 && usage[8])
result.add("decipherOnly");
} catch (Throwable ex) {
Log.e(ex);
}
return result;
}
Boolean isSelfSigned() {
try {
X509Certificate cert = getCertificate();
return (cert.getIssuerX500Principal().equals(cert.getSubjectX500Principal()));
} catch (Throwable ex) {
Log.e(ex);
return null;
}
}
String getPem() throws CertificateException, IOException {
StringWriter writer = new StringWriter();
JcaPEMWriter pemWriter = new JcaPEMWriter(writer);

View file

@ -10719,30 +10719,15 @@ public class FragmentMessages extends FragmentBase
for (Certificate c : certs)
try {
X509Certificate cert = (X509Certificate) c;
boolean[] usage = cert.getKeyUsage();
boolean digitalSignature = (usage != null && usage.length > 0 && usage[0]);
boolean nonRepudiation = (usage != null && usage.length > 1 && usage[1]);
boolean keyEncipherment = (usage != null && usage.length > 2 && usage[2]);
boolean dataEncipherment = (usage != null && usage.length > 3 && usage[4]);
boolean keyAgreement = (usage != null && usage.length > 4 && usage[4]);
boolean keyCertSign = (usage != null && usage.length > 5 && usage[5]);
boolean cRLSign = (usage != null && usage.length > 6 && usage[6]);
boolean encipherOnly = (usage != null && usage.length > 7 && usage[7]);
boolean decipherOnly = (usage != null && usage.length > 8 && usage[8]);
boolean selfSigned = cert.getIssuerX500Principal().equals(cert.getSubjectX500Principal());
EntityCertificate record = EntityCertificate.from(cert, null);
trace.add(record.subject +
" (" + (selfSigned ? "selfSigned" : cert.getIssuerX500Principal()) + ")" +
(digitalSignature ? " (digitalSignature)" : "") +
(nonRepudiation ? " (nonRepudiation)" : "") +
(keyEncipherment ? " (keyEncipherment)" : "") +
(dataEncipherment ? " (dataEncipherment)" : "") +
(keyAgreement ? " (keyAgreement)" : "") +
(keyCertSign ? " (keyCertSign)" : "") +
(cRLSign ? " (cRLSign)" : "") +
(encipherOnly ? " (encipherOnly)" : "") +
(decipherOnly ? " (decipherOnly)" : "") +
(ks != null && ks.getCertificateAlias(cert) != null ? " (Android)" : ""));
StringBuilder sb = new StringBuilder();
sb.append(record.subject);
sb.append(" (").append(record.isSelfSigned() ? "selfSigned" : cert.getIssuerX500Principal()).append(")");
for (String usage : record.getKeyUsage())
sb.append(" (").append(usage).append(")");
if (ks != null && ks.getCertificateAlias(cert) != null)
sb.append(" (Android)");
trace.add(sb.toString());
} catch (Throwable ex) {
Log.e(ex);
trace.add(new ThrowableWrapper(ex).toSafeString());

View file

@ -48,6 +48,16 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/barrier" />
<TextView
android:id="@+id/tvKeyUsage"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Key usage"
android:textAppearance="@android:style/TextAppearance.Small"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvSubject" />
<TextView
android:id="@+id/tvAfter"
android:layout_width="0dp"
@ -56,7 +66,7 @@
android:textAppearance="@android:style/TextAppearance.Small"
app:layout_constraintEnd_toStartOf="@+id/tvBefore"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvSubject" />
app:layout_constraintTop_toBottomOf="@+id/tvKeyUsage" />
<TextView
android:id="@+id/tvBefore"
@ -67,7 +77,7 @@
android:textAppearance="@android:style/TextAppearance.Small"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tvAfter"
app:layout_constraintTop_toBottomOf="@+id/tvSubject" />
app:layout_constraintTop_toBottomOf="@+id/tvKeyUsage" />
<TextView
android:id="@+id/tvExpired"