From adfcc4b3917320fbcea044e7f6cbf1a4de9aaf8a Mon Sep 17 00:00:00 2001 From: M66B Date: Sat, 14 Aug 2021 07:06:48 +0200 Subject: [PATCH] Untrusted: refactoring --- .../java/eu/faircode/email/ActivitySetup.java | 2 +- .../java/eu/faircode/email/EmailService.java | 64 ++++++------------- .../eu/faircode/email/EntityCertificate.java | 27 +++++++- .../eu/faircode/email/FragmentMessages.java | 4 +- 4 files changed, 47 insertions(+), 50 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/ActivitySetup.java b/app/src/main/java/eu/faircode/email/ActivitySetup.java index 102415ec30..3b298d0072 100644 --- a/app/src/main/java/eu/faircode/email/ActivitySetup.java +++ b/app/src/main/java/eu/faircode/email/ActivitySetup.java @@ -1443,7 +1443,7 @@ public class ActivitySetup extends ActivityBase implements FragmentManager.OnBac } } - String fingerprint = EntityCertificate.getFingerprint(cert); + String fingerprint = EntityCertificate.getFingerprintSha256(cert); List emails = EntityCertificate.getEmailAddresses(cert); if (emails.size() == 0) diff --git a/app/src/main/java/eu/faircode/email/EmailService.java b/app/src/main/java/eu/faircode/email/EmailService.java index 97167d9082..678c32fd0b 100644 --- a/app/src/main/java/eu/faircode/email/EmailService.java +++ b/app/src/main/java/eu/faircode/email/EmailService.java @@ -40,10 +40,6 @@ import com.sun.mail.smtp.SMTPTransport; import com.sun.mail.util.MailConnectException; import com.sun.mail.util.SocketConnectException; -import org.bouncycastle.asn1.DEROctetString; -import org.bouncycastle.asn1.x509.Extension; -import org.bouncycastle.asn1.x509.SubjectKeyIdentifier; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -58,10 +54,8 @@ import java.net.SocketException; import java.net.UnknownHostException; import java.security.GeneralSecurityException; import java.security.KeyStore; -import java.security.NoSuchAlgorithmException; import java.security.Principal; import java.security.PrivateKey; -import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; @@ -490,7 +484,7 @@ public class EmailService implements AutoCloseable { Throwable ce = ex; while (ce != null) { if (factory != null && ce instanceof CertificateException) - throw new UntrustedException(factory.getFingerPrintSelect(), ex); + throw new UntrustedException(factory.certificate, ex); if (ce instanceof IOException) ioError = true; ce = ce.getCause(); @@ -989,12 +983,12 @@ public class EmailService implements AutoCloseable { private static boolean matches(X509Certificate certificate, @NonNull String trustedFingerprint) { // Get certificate fingerprint try { - String fingerprint = getFingerPrint(certificate); + String fingerprint = EntityCertificate.getFingerprintSha1(certificate); int slash = trustedFingerprint.indexOf('/'); if (slash < 0) return trustedFingerprint.equals(fingerprint); else { - String keyId = getKeyId(certificate); + String keyId = EntityCertificate.getKeyId(certificate); if (trustedFingerprint.substring(slash + 1).equals(keyId)) return true; return trustedFingerprint.substring(0, slash).equals(fingerprint); @@ -1004,37 +998,6 @@ public class EmailService implements AutoCloseable { return false; } } - - private static String getKeyId(X509Certificate certificate) { - try { - byte[] extension = certificate.getExtensionValue(Extension.subjectKeyIdentifier.getId()); - if (extension == null) - return null; - byte[] bytes = DEROctetString.getInstance(extension).getOctets(); - SubjectKeyIdentifier keyId = SubjectKeyIdentifier.getInstance(bytes); - return Helper.hex(keyId.getKeyIdentifier()); - } catch (Throwable ex) { - Log.e(ex); - return null; - } - } - - private static String getFingerPrint(X509Certificate certificate) throws CertificateEncodingException, NoSuchAlgorithmException { - return Helper.sha1(certificate.getEncoded()); - } - - String getFingerPrintSelect() { - try { - if (certificate == null) - return null; - String keyId = getKeyId(certificate); - String fingerPrint = getFingerPrint(certificate); - return fingerPrint + (keyId == null ? "" : "/" + keyId); - } catch (Throwable ex) { - Log.e(ex); - return null; - } - } } private static void configureSocketOptions(Socket socket) throws SocketException { @@ -1075,15 +1038,28 @@ public class EmailService implements AutoCloseable { } class UntrustedException extends MessagingException { - private String fingerprint; + private X509Certificate certificate; - UntrustedException(@NonNull String fingerprint, @NonNull Exception cause) { + UntrustedException(@NonNull X509Certificate certificate, @NonNull Exception cause) { super("Untrusted", cause); - this.fingerprint = fingerprint; + this.certificate = certificate; + } + + X509Certificate getCertificate() { + return certificate; } String getFingerprint() { - return fingerprint; + try { + if (certificate == null) + return null; + String keyId = EntityCertificate.getKeyId(certificate); + String fingerPrint = EntityCertificate.getFingerprintSha1(certificate); + return fingerPrint + (keyId == null ? "" : "/" + keyId); + } catch (Throwable ex) { + Log.e(ex); + return null; + } } @NonNull diff --git a/app/src/main/java/eu/faircode/email/EntityCertificate.java b/app/src/main/java/eu/faircode/email/EntityCertificate.java index 726ae9f9db..4659a50cc7 100644 --- a/app/src/main/java/eu/faircode/email/EntityCertificate.java +++ b/app/src/main/java/eu/faircode/email/EntityCertificate.java @@ -27,11 +27,14 @@ import androidx.room.Index; import androidx.room.PrimaryKey; import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.x500.AttributeTypeAndValue; import org.bouncycastle.asn1.x500.RDN; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.style.BCStyle; +import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.asn1.x509.SubjectKeyIdentifier; import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; import org.json.JSONException; import org.json.JSONObject; @@ -85,7 +88,7 @@ public class EntityCertificate { static EntityCertificate from(X509Certificate certificate, boolean intermediate, String email) throws CertificateEncodingException, NoSuchAlgorithmException { EntityCertificate record = new EntityCertificate(); - record.fingerprint = getFingerprint(certificate); + record.fingerprint = getFingerprintSha256(certificate); record.intermediate = intermediate; record.email = email; record.subject = getSubject(certificate); @@ -118,10 +121,28 @@ public class EntityCertificate { return ((this.after != null && now <= this.after) || (this.before != null && now > this.before)); } - static String getFingerprint(X509Certificate certificate) throws CertificateEncodingException, NoSuchAlgorithmException { + static String getFingerprintSha256(X509Certificate certificate) throws CertificateEncodingException, NoSuchAlgorithmException { return Helper.sha256(certificate.getEncoded()); } + static String getFingerprintSha1(X509Certificate certificate) throws CertificateEncodingException, NoSuchAlgorithmException { + return Helper.sha1(certificate.getEncoded()); + } + + static String getKeyId(X509Certificate certificate) { + try { + byte[] extension = certificate.getExtensionValue(Extension.subjectKeyIdentifier.getId()); + if (extension == null) + return null; + byte[] bytes = DEROctetString.getInstance(extension).getOctets(); + SubjectKeyIdentifier keyId = SubjectKeyIdentifier.getInstance(bytes); + return Helper.hex(keyId.getKeyIdentifier()); + } catch (Throwable ex) { + Log.e(ex); + return null; + } + } + static String getSubject(X509Certificate certificate) { return certificate.getSubjectX500Principal().getName(X500Principal.RFC2253); } @@ -199,7 +220,7 @@ public class EntityCertificate { certificate.data = json.getString("data"); X509Certificate cert = certificate.getCertificate(); - certificate.fingerprint = getFingerprint(cert); + certificate.fingerprint = getFingerprintSha256(cert); certificate.subject = getSubject(cert); Date after = cert.getNotBefore(); diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index a6d51bba61..af82b96b35 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -7018,7 +7018,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. if (s.verify(verifier)) { boolean known = true; - String fingerprint = EntityCertificate.getFingerprint(cert); + String fingerprint = EntityCertificate.getFingerprintSha256(cert); List emails = EntityCertificate.getEmailAddresses(cert); for (String email : emails) { EntityCertificate record = db.certificate().getCertificate(fingerprint, email); @@ -7349,7 +7349,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. if (message == null) return null; - String fingerprint = EntityCertificate.getFingerprint(cert); + String fingerprint = EntityCertificate.getFingerprintSha256(cert); List emails = EntityCertificate.getEmailAddresses(cert); for (String email : emails) { EntityCertificate record = db.certificate().getCertificate(fingerprint, email);