Reputation: 1
2 weeks ago, I wanted to port my go functionality of an MTS-fetch using a self-singing X509Certificate to Android because we want to support android for a side project of mine.
func (a *App) MTLSFetch(method string, path string, body string, csr string, privateKey string) MTLSFetchResponse { ...
This is probably not the most efficient approach, but it works.
Now to my problem, I tried the straight forward implementation with no external libs and used something like this
KeyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.setKeyEntry(this.alias, privateKey, null, new Certificate[]{originalCert});
CustomX509TrustManager trustManager = new CustomX509TrustManager(getCertificate()); //the trust store simply trusts everything [1],[2] TrustManager[] trustManagers
TrustManager[] trustManagers = {trustManager};
SSLContext sslContext = SSLContext.getInstance("TLS");
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("PKIX");
keyManagerFactory.init(this.keyStore, null);
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagers, null);
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
HttpsURLConnection ctx;
InputStream o;
URL url2 = new URL(url);
ctx = (HttpsURLConnection) url2.openConnection();
ctx.setSSLSocketFactory(sslSocketFactory);
ctx.setHostnameVerifier((hostname, session) -> true);
ctx.setRequestMethod(method);
ctx.connect();
custom trust store 1 custom trust store 2
in the end, I always get the following error:
javax.net.ssl.SSLHandshakeException: Error configuring certificate: ssl=0x7661414de2d8: 06-04 12:36:35.697 12178 12196 E Blockguard: error:1000012e:SSL routines:OPENSSL_internal:KEY_USAGE_BIT_INCORRECT (external/boringssl/src/ssl/ssl_cert.cc:605 0x76605a5d1112:0x00000000)
depending on which provider or setup, I also get this:
06-04 12:36:35.697 12178 12196 E Blockguard: error:100000e4:SSL routines:OPENSSL_internal:UNKNOWN_CERTIFICATE_TYPE (external/boringssl/src/ssl/ssl_cert.cc:249 0x76605a5d1112:0x00000000)
for my testing, I used the following
@RequiresPermission(Manifest.permission.INTERNET)
@Test
public void mtlsTest() throws Exception{
As well as setting the permission in the manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<application>
<service android:name=".plugin.MyVpnService" android:permission="android.permission.BIND_VPN_SERVICE" <--- this is for later establishing a vpn contection
android:exported="true">
<intent-filter>
<action android:name="android.net.VpnService" />
</intent-filter>
</service>
</application>
</manifest>
I played around by parsing the cert and Pk in all sorts of different ways, and even building a new pair at runtime, just to make sure my cert and Pk were wrong (which I still cannot completely rule out, but I mean the same cert Pk combo works in go, so who knows, you ?).
For the BC packages, I always used the bcXXX-jdk18on:1.78.1.
I also changed all sorts of providers from BC to bcjsse, changed the keystore and KeyManagerFactory providers, tried the X509v3CertificateBuilder and then converting back to an X509Certificate from there just to set different extensions, double-checked that all the extensions were correct.
In my understanding I need the following extensions which are all set in my setup:
X509v3 extensions:
X509v3 Key Usage: critical
Key Encipherment, Data Encipherment
X509v3 Extended Key Usage:
TLS Web Client Authentication
X509v3 Basic Constraints: critical
CA:FALSE
For the https connection, I tried
HttpsURLConnection (Android) OkHttps (OkHttp:4.12.0') OkHttps in Retrofit (Retrofit:2.11.0) Probably the same.
At some point I tried the raw socket implementation, but that did not work either
I am far from being an experienced Android developer, so I hope this is a painful 2-week mistake by not setting some android permissions, but it seems to me that I must be doing something fundamentally wrong, because setting up an MTS-Fetch with a self-signed certificate cannot be that uncommon.
To stop the answers that I need to just install the certificates on the device and just load the certificate from the device, this is not possible for this type of application, the certificate needs to be generated at runtime.
Upvotes: 0
Views: 174