Use key ID instead of fingerprint when possible

This commit is contained in:
M66B 2020-01-31 20:20:44 +01:00
parent 72eeb98389
commit f920601a22
2 changed files with 48 additions and 12 deletions

View File

@ -20,7 +20,10 @@ import net.openid.appauth.ClientAuthentication;
import net.openid.appauth.ClientSecretPost;
import net.openid.appauth.NoClientAuthentication;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
@ -306,7 +309,7 @@ public class EmailService implements AutoCloseable {
Throwable ce = ex;
while (ce != null) {
if (factory != null && ce instanceof CertificateException)
throw new UntrustedException(factory.getFingerPrint(), ex);
throw new UntrustedException(factory.getFingerPrintSelect(), ex);
if (ce instanceof IOException)
ioError = true;
ce = ce.getCause();
@ -563,6 +566,8 @@ public class EmailService implements AutoCloseable {
final X509TrustManager rtm = (X509TrustManager) tms[0];
X509TrustManager tm = new X509TrustManager() {
// openssl s_client -connect <host>
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
if (secure)
@ -574,16 +579,8 @@ public class EmailService implements AutoCloseable {
certificate = chain[0];
if (secure) {
// Get certificate fingerprint
String fingerprint;
try {
fingerprint = getFingerPrint(certificate);
} catch (Throwable ex) {
throw new CertificateException(ex);
}
// Check if selected fingerprint
if (fingerprint.equals(trustedFingerprint)) {
if (trustedFingerprint != null && matches(certificate, trustedFingerprint)) {
Log.i("Trusted selected fingerprint");
return;
}
@ -731,13 +728,48 @@ public class EmailService implements AutoCloseable {
return result;
}
private static boolean matches(X509Certificate certificate, @NonNull String trustedFingerprint) {
// Get certificate fingerprint
try {
String fingerprint = getFingerPrint(certificate);
int slash = trustedFingerprint.indexOf('/');
if (slash < 0)
return trustedFingerprint.equals(fingerprint);
else {
String keyId = getKeyId(certificate);
if (trustedFingerprint.substring(slash + 1).equals(keyId))
return true;
return trustedFingerprint.substring(0, slash).equals(fingerprint);
}
} catch (Throwable ex) {
Log.w(ex);
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 getFingerPrint() {
String getFingerPrintSelect() {
try {
return getFingerPrint(certificate);
String keyId = getKeyId(certificate);
String fingerPrint = getFingerPrint(certificate);
return fingerPrint + (keyId == null ? "" : "/" + keyId);
} catch (Throwable ex) {
Log.e(ex);
return null;

View File

@ -829,6 +829,10 @@ public class Helper {
static String sha(String digest, byte[] data) throws NoSuchAlgorithmException {
byte[] bytes = MessageDigest.getInstance(digest).digest(data);
return hex(bytes);
}
static String hex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes)
sb.append(String.format("%02x", b));