Android and client certificates


Anthony B Code

I've been searching for weeks and can't seem to find an answer anywhere. I am trying to do the following for Android. The code is from a C# app I wrote but am porting it to Android. Web endpoints require certificates to be attached to mutual authentication requests for web service calls.

        string certThumbprint = "E1313F6A2D770783868755D016CE748F6A9B0028";
        X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        try
        {
            certStore.Open(OpenFlags.ReadOnly);
        }
        catch (Exception e)
        {
            if (e is CryptographicException)
            {
                Console.WriteLine("Error: The store is unreadable.");
            }
            else if (e is SecurityException)
            {
                Console.WriteLine("Error: You don't have the required permission.");
            }
            else if (e is ArgumentException)
            {
                Console.WriteLine("Error: Invalid values in the store.");
            }
            else
            {
                throw;
            }
        }
        X509Certificate2Collection certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, certThumbprint, false);
        certStore.Close();
        if (0 == certCollection.Count)
        {
            throw new Exception("Error: No certificate found containing thumbprint " + certThumbprint);
        }
        X509Certificate2 certificate = certCollection[0];
        return certificate;

Then, I'm doing this (the request is an HttpWebRequest):

request.ClientCertificates.Add(cert);

This works fine in C#, but when I go to Android I get a "file not found" error on the getInputStream() call. Here is my Android code:

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();

        StrictMode.setThreadPolicy(policy);
        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        InputStream caInput = new BufferedInputStream(new FileInputStream("/sdcard/Certificate.pfx"));
        KeyHelper kh = new KeyHelper();
        Certificate ca = kh.GetKey("Password");
        String keyStoreType = KeyStore.getDefaultType();
        keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(keyStore, "Password".toCharArray());
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(kmf.getKeyManagers(),null,new SecureRandom());
        HttpsURLConnection urlConnection =
                (HttpsURLConnection)url.openConnection();
        urlConnection.setRequestProperty("x-ms-version",AZURE_REST_VERSION);
        urlConnection.setDoInput(true);
        urlConnection.setDoOutput(true);
        urlConnection.setRequestMethod("GET");
        urlConnection.setSSLSocketFactory(context.getSocketFactory());
        urlConnection.connect();

        InputStream in = new BufferedInputStream(urlConnection.getInputStream()); //<-----Blows up here

    } catch (KeyStoreException e) {
        throw new KeyStoreException("Keystore Exception",e);
    } catch (NoSuchAlgorithmException e) {
        throw new NoSuchAlgorithmException("Algorithm exception",e);
    } catch (KeyManagementException e) {
        throw new KeyManagementException("Key Exception", e);
    }

I tried putting fiddler between the emulator and the endpoint and it returned 200. I think this is because my certificates are in a local private store on the development machine. Any ideas?

Anthony B Code

Row. I found the answer. The problem is that the self-signed certificate cannot be used unless it exists in the Android TrustStore. However, the default TrustStore is read-only after the app starts, making it difficult to modify it. I'm building my own custom truststore, but the root certificate is not part of it, so any calls to https will fail. The solution comes from this blog post:

http://nelenkov.blogspot.com/2011/12/using-custom-certificate-trust-store-on.html

In short, set up a custom TrustStore containing self-signed certificates, then export all certificates from the default truststore and import them into the custom truststore. Then, use that truststore to set up your SSL context (you will also need to use a custom keystore since the client certificate needs to be appended to the request as well). I believe that if I don't allow self-signed certificates then it won't be a big deal, since the root certificate for the client certificate will be present in the default TrustStore (or at least hope so).

Related


Android and client certificates

Anthony B Code I've been searching for weeks and can't seem to find an answer anywhere. I am trying to do the following for Android. The code is from a C# app I wrote but am porting it to Android. Web endpoints require certificates to be attached to mutual aut

OCSP revocation of client certificates

gtrak: How to manually check certificate revocation status in Java using OCSP, considering only the client's java.security.cert.X509Certificate? I can't see a clear way to do it. Alternatively, I can have tomcat do this for me automatically, how do you know yo

Client certificates and identities in iOS

lipoprotein: I have used SecKeyGeneratePairfunctions to generate private and public keys for a Swift based iOS app . I then generated a "Certificate Signing Request" using the iOS CSR and my server replied with a certificate chain in PEM format. I use the foll

Compare client certificates in go

User1791139: My use case looks like I know the client's public certificate and just want to allow them. I have a go server configured based on gin and TLS where a method has been assigned to the property "VerifyPeerCertificate". The function looks like func cu

OCSP revocation of client certificates

gtrak: How to manually check certificate revocation status in Java using OCSP, considering only the client's java.security.cert.X509Certificate? I can't see a clear way to do it. Alternatively, I can have tomcat do this for me automatically, how do you know yo

Compare client certificates in go

User1791139: My use case looks like I know the client's public certificate and just want to allow them. I have a go server configured based on gin and TLS where a method has been assigned to the property "VerifyPeerCertificate". The function looks like func cu

Client certificates and identities in iOS

lipoprotein: I have used SecKeyGeneratePairfunctions to generate private and public keys for a Swift based iOS app . I then generated a "Certificate Signing Request" using the iOS CSR and my server replied with a certificate chain in PEM format. I use the foll

Dynamically request client certificates

user 93353 The web server has settings for requesting client certificates - eg. SSLVerifyClient requireIn Apache, use other settings in IIS etc. If this setting is set, the browser will pop up a dialog asking you to select a certificate. Is it possible to requ

OCSP revocation of client certificates

gtrak: How to manually check certificate revocation status in Java using OCSP, considering only the client's java.security.cert.X509Certificate? I can't see a clear way to do it. Alternatively, I can have tomcat do this for me automatically, how do you know yo

Compare client certificates in go

User1791139: My use case looks like I know the client's public certificate and just want to allow them. I have a go server configured based on gin and TLS where a method has been assigned to the property "VerifyPeerCertificate". The function looks like func cu

Client certificates and identities in iOS

lipoprotein: I have used SecKeyGeneratePairfunctions to generate private and public keys for a Swift based iOS app . I then generated a "Certificate Signing Request" using the iOS CSR and my server replied with a certificate chain in PEM format. I use the foll

Dynamically request client certificates

user 93353 The web server has settings for requesting client certificates - eg. SSLVerifyClient requireIn Apache, use other settings in IIS etc. If this setting is set, the browser will pop up a dialog asking you to select a certificate. Is it possible to requ

Using Client Certificates in Curl Commands

sunsin1985 : curl command: curl -k -vvvv --request POST --header "Content-Type: application/json" --cert client.pem:password --key key.pem "https://test.com:8443/testing" I am trying to send a client certificate using the Curl command specified above. I would

WSDL client authentication and multiple certificates

other: So I'm having issues with wsdls here, with multiple certificates selected in Java. For example, a smart card has multiple certificates on it for signing, encryption and identification. I have a WSDL that generates code for client auth connections, but a

Using Client Certificates in Alamofire 2.0

Paul On Alamofire 1 and Swift 1.2, I use the following code to make a request and submit my own client certificate: Alamofire.request(.POST, url!, parameters: params, encoding: .JSON) .authenticate(usingCredential: credential) .responseJSON { (request,

Using Client Certificates in Curl Commands

sunsin1985 : curl command: curl -k -vvvv --request POST --header "Content-Type: application/json" --cert client.pem:password --key key.pem "https://test.com:8443/testing" I am trying to send a client certificate using the Curl command specified above. I would

WSDL client authentication and multiple certificates

other: So I'm having issues with wsdls here, with multiple certificates selected in Java. For example, a smart card has multiple certificates on it for signing, encryption and identification. I have a WSDL that generates code for client auth connections, but a

AWS Multiple VPN Client Certificates

Ludo21 South With AWS, I need to make sure I have multiple clients using the VPN network. Each client will use the same server certificate I created earlier. Now, using this document, I managed to set up my own VPN and was able to connect to it using the gener

Client Certificates on Google Cloud Functions

microphone From my google cloud function, I try to request another api that requires a dummy certificate in the test environment. So my server is the client here. Is there a way to send client certificate in google cloud function? I managed to make it work in

Using Client Certificates in Alamofire 2.0

Paul On Alamofire 1 and Swift 1.2, I use the following code to make a request and submit my own client certificate: Alamofire.request(.POST, url!, parameters: params, encoding: .JSON) .authenticate(usingCredential: credential) .responseJSON { (request,

Client certificates in Dotnet Core on Ubuntu

mdavisi All - I wrote a dotnet core API set which works flawlessly on Windows. On Ubuntu 14.04 everything works fine except for one SOAP request to a vendor that uses client certificates for authentication. The request always times out. Netstat trace shows tha

Filter client certificates (like browsers)

Mika Hoover I have a smart card reader. When I try to access a website that accepts client certificates, the browser presents me with a list of 2 or 3 client certificates. All of these certificate options are tied closely to the card used on my machine. When I

Client Certificates on Google Cloud Functions

microphone From my google cloud function, I try to request another api that requires a dummy certificate in the test environment. So my server is the client here. Is there a way to send client certificate in google cloud function? I managed to make it work in

AWS Multiple VPN Client Certificates

Ludo21 South With AWS, I need to make sure I have multiple clients using the VPN network. Each client will use the same server certificate I created earlier. Now, using this document, I managed to set up my own VPN and was able to connect to it using the gener

How do client certificates work?

Sunil I'm working with a REST service provider and they want me to use the client certificate they provide when making HTTP calls. How do client certificates implement authentication? If someone has a copy of the client certificate, then they can also authenti

Generate client certificates for TLS asterisks

Duckett I'm trying to enable TLS b/w (voip server and client (Android device) powered by asterisk) following the guide mentioned here . Used to generate client certificates ./ast_tls_cert -m client -c /etc/asterisk/keys/ca.crt -k /etc/asterisk/keys/ca.key -C p

Using Client Certificates in Curl Commands

sunsin1985 : curl command: curl -k -vvvv --request POST --header "Content-Type: application/json" --cert client.pem:password --key key.pem "https://test.com:8443/testing" I am trying to send a client certificate using the Curl command specified above. I would