So if your really need to get certs from the system keystore daemon, then KeyChain is what you want. You don't want to use KeyManagerFactory, but make your own X509KeyManager and pass that when you create your SSLContext. You can put logging there to verify is getting called and of course have the code to return the PrivateKey and certificate chain you received from the KeyChain. the logging will ensure that the SSL handshake is attempting to call the KeyManager to get the client certificate and key information.
if that seems to be working, but you are still getting 403, I would look with tcpdump/wireshark to confirm that the client certificate is being sent during the handshake, as well as the server logs for what information they provide about the cause of failure. but i'm guessing the cert isn't being sent from the client at all. -bri On Thu, Nov 29, 2012 at 1:10 AM, Jens Hoffmann <jenssap2...@gmail.com> wrote: > Hi Brian. > > I use the KeyChain Api to set the necessary permissions to the certificate. > > // That methode opens a view where the user can choose the certificate an > allow it. > private void setPermissionsForCertificate() { > KeyChain.choosePrivateKeyAlias(this, new KeyChainAliasCallback() { > > public void alias(String alias) { > // Credential alias selected. Remember the alias selection for > // future use. > > } > }, null, // List of acceptable key types. null for any new String[] > // {"RSA"} > null, // issuer, null for any > null, // host name of server requesting the cert, null if > // unavailable > -1, // port of server requesting the cert, -1 if unavailable > null); // alias to preselect, null if unavailable > } > > The client certs are pre-installed on each device. > (It comes with a special software which is installed on the devices) > => So the client certficates are installed in the existing keystore of the > device. > > > > Thats the code from: > http://developer.android.com/reference/javax/net/ssl/HttpsURLConnection.html > > KeyStore keyStore = ...; > KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509"); > kmf.init(keyStore); > SSLContext context = SSLContext.getInstance("TLS"); > context.init(kmf.getKeyManagers(), null, null); > > > So I need to have a KeyStore. Instead of creating a custom KeyStore > I wanted to use the existing KeyStore. > That's why I have to use the KeyChain Api, to read the chain and the private > key from the store. > Is this correct? > > > I already tried the example with the HttpsULRConnection, but I still get a > forbidden exception. > > best regards, > > jens. > > > > 2012/11/28 Brian Carlstrom <b...@google.com> >> >> It doesn't sound like you need to use KeyChain at all, but just >> HttpsURLConnection, which isn't Android specific, there are lots of examples >> of doing this with Java in general. >> >> >> http://developer.android.com/reference/javax/net/ssl/HttpsURLConnection.html >> >> how are you distributing the client cert? are you going to have them type >> their other credentials (such as password) once, and then download the >> client cert to the app? >> >> -bri >> >> >> >> On Wed, Nov 28, 2012 at 1:45 PM, Jens Hoffmann <jenssap2...@gmail.com> >> wrote: >>> >>> Hi Brian, >>> >>> every user of my app has its own client certificate installed: for >>> example CN=N127391 >>> These client certificates are signed by the root authority (This >>> certificate is also installed on the device) >>> The problem is that I still get the 403 forbidden error (authentication >>> fails), when I connect with an android device.. >>> With a windows device (for example with the internet explorer or chrom), >>> it works. >>> >>> first use case: authentication (Single Sign On, so that android user does >>> not have to type in his password) >>> The use case is that I want to authenticate the android clients to the >>> server (WCF Service). >>> In the WCF Service I can then extract the Number ("N127391") and use for >>> example ASP Membership. >>> >>> So for the first use case I would need class which transfers the >>> certificate to the server. In the google code I >>> have found the SSLSocketFactory: >>> >>> * SSLSocketFactory will enable client authentication when supplied with >>> a >>> * {@link KeyStore keystore} file containg a private key/public >>> certificate >>> * pair. The client secure socket will use the private key to >>> authenticate >>> * itself to the target HTTPS server during the SSL session handshake if >>> * requested to do so by the server. The target HTTPS server will in its >>> turn >>> * verify the certificate presented by the client in order to establish >>> client's >>> * authenticity >>> >>> So I guess I have to use this class for the authentication? >>> >>> seconde use case: encryption >>> The traffic should be encrypted (SSL). That's why I need the server >>> certificate. >>> >>> Is there a simple way how I can achieve these two use cases. >>> I am new to android and I am trying to accomplish this for weeks :(. >>> >>> I hope you can help me. >>> >>> best regards, >>> jens >>> >>> >>> >>> Am Mittwoch, 28. November 2012 19:29:13 UTC+1 schrieb Brian Carlstrom: >>>> >>>> I don't recall the exact reasons why the Email code is the way it is. I >>>> think the primary reason is that they don't know ahead of time if the >>>> server >>>> is going to want a client cert, so they install a manager to record the >>>> fact >>>> that a cert was requested, then do some UI to ask the user what they want >>>> to >>>> use, then use a different one configured with the users choice. >>>> >>>> it's much simpler in an app where you know ahead of time what client >>>> cert to use. is that your case? if so, I'd ignore the email example code as >>>> overly convoluted for your use case. >>>> >>>> -bri >>>> >>>> >>>> On Wed, Nov 28, 2012 at 4:31 AM, Jens Hoffmann <jenss...@gmail.com> >>>> wrote: >>>>> >>>>> Hi Brian, >>>>> yes, I took a look at the SSLUtils.class. >>>>> The class TrackingKeyManager (static class inside the SSLUtils) extends >>>>> the class StubKeyManager which extends the class X509ExtendedKeyManager. >>>>> But why do I need this class? I tried to use the >>>>> SSLCertificateSocketFactory instead (It has X509KeyManager Object inside) >>>>> . >>>>> But unfortunately I got an 403 response, access forbidden. >>>>> >>>>> It also throws an exception: >>>>> >>>>> java.io.FileNotFoundException: >>>>> https://nameoftheserver/MyService/Service.svc/rest/GetDNumber >>>>> >>>>> >>>>> >>>>> I have tested the WCF Service with the Internet Explorer and it works >>>>> just fine. >>>>> Is my client certificate may be not transferred, so that the server >>>>> does not get the public key? >>>>> >>>>> >>>>> Code: >>>>> SSLCertificateSocketFactory sslCertificateSocketFactory = null; >>>>> try { >>>>> KeyManager keyManager = KeyChainKeyManager.fromAlias( >>>>> getApplicationContext(), ht.mClientCertAlias); >>>>> >>>>> >>>>> sslCertificateSocketFactory = SSLUtils.getSSLSocketFactory(false); >>>>> // use SSL >>>>> >>>>> >>>>> sslCertificateSocketFactory >>>>> .setKeyManagers(new KeyManager[] { keyManager }); >>>>> >>>>> >>>>> } catch (CertificateException e1).. >>>>> >>>>> >>>>> URL url = null; >>>>> try { >>>>> url = new URL(this.url); >>>>> } catch (MalformedURLException e).. >>>>> >>>>> >>>>> HttpsURLConnection urlConnection = null; >>>>> try { >>>>> urlConnection = (HttpsURLConnection) url.openConnection(); >>>>> urlConnection.setSSLSocketFactory(sslCertificateSocketFactory); >>>>> } catch (IOException e).. >>>>> >>>>> >>>>> try { >>>>> iResponseCode = urlConnection.getResponseCode(); >>>>> if(iResponseCode == 403) >>>>> { >>>>> Log.d(TAG, "Response Code is 403, Access forbidden."); >>>>> } >>>>> InputStream in = urlConnection.getInputStream(); >>>>> } catch (IOException e).. >>>>> >>>>> I hope you can help me. Thanks in advance. >>>>> >>>>> best regards, >>>>> jens >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> Am Dienstag, 27. November 2012 09:29:46 UTC+1 schrieb Jens Hoffmann: >>>>>> >>>>>> Hi everybody, >>>>>> >>>>>> I am developing an android application which querys a WCF Webservice >>>>>> (SSL + Authentication). >>>>>> On this link >>>>>> (http://android-developers.blogspot.de/2012/03/unifying-key-store-access-in-ics.html) >>>>>> I found the following: >>>>>> >>>>>> "A common use of the private key is for SSL client authentication. >>>>>> This can be implemented by >>>>>> using an HttpsURLConnection with a custom X509KeyManager that returns >>>>>> the PrivateKey >>>>>> retrieved from the KeyChain API. The open source Email application for >>>>>> ICS uses KeyChain >>>>>> with an X509ExtendedKeyManager. To learn more, have a look at the >>>>>> source code (in SSLUtils.java)." >>>>>> >>>>>> So I looked into this google code and tried to use the classes. But it >>>>>> doesn't work. >>>>>> I always get an 403 Error - Forbbiden. I really hope you can help me. >>>>>> >>>>>> Here is some code: >>>>>> >>>>>> >>>>>> Android: >>>>>> >>>>>> private void setHttpsAdvanced() { >>>>>> HostAuth ht = new HostAuth(); >>>>>> ht.mPort = 443; >>>>>> ht.mClientCertAlias = "jensZert"; >>>>>> >>>>>> HttpParams params = getHttpParams(); >>>>>> MyThreadSafeClientConnManager ccm = MyThreadSafeClientConnManager >>>>>> .newInstance(params, true, 443); >>>>>> >>>>>> try { >>>>>> ccm.registerClientCert(getApplicationContext(), ht); >>>>>> } catch (CertificateException e) { >>>>>> e.printStackTrace(); >>>>>> } >>>>>> >>>>>> this.httpclient = new DefaultHttpClient(ccm, params); >>>>>> >>>>>> connectionInfo = this.getConnectionInfo(); >>>>>> >>>>>> this.url = String.format("%1$s://%2$s/%3$s/%4$s", >>>>>> connectionInfo.Protocol, connectionInfo.ServerName, >>>>>> connectionInfo.WebserviceName, connectionInfo.Path); >>>>>> >>>>>> httpGet = new HttpGet(url); >>>>>> } >>>>>> >>>>>> private String callTheWebserviceCertificate() { >>>>>> this.setupClient(); >>>>>> String result = ""; >>>>>> >>>>>> HttpResponse response = null; >>>>>> try { >>>>>> response = (HttpResponse) this.httpclient.execute(httpGet); >>>>>> result = EntityUtils.toString(response.getEntity()); >>>>>> >>>>>> } catch (ClientProtocolException e) { >>>>>> >>>>>> e.printStackTrace(); >>>>>> } catch (IOException e) { >>>>>> Log.d(TAG, result); >>>>>> } >>>>>> return result; >>>>>> } >>>>>> >>>>>> >>>>>> >>>>>> My WCF Service web.config: >>>>>> >>>>>> <behavior name="ServCertificatBehavior"> >>>>>> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /> >>>>>> <serviceDebug includeExceptionDetailInFaults="true" /> >>>>>> <serviceAuthorization principalPermissionMode="UseWindowsGroups" /> >>>>>> <serviceCredentials> >>>>>> <clientCertificate> >>>>>> <authentication certificateValidationMode="PeerOrChainTrust" /> >>>>>> </clientCertificate> >>>>>> <serviceCertificate findValue="02 00 0b 30" >>>>>> storeLocation="LocalMachine" storeName="My" >>>>>> x509FindType="FindBySerialNumber" /> >>>>>> </serviceCredentials> >>>>>> </behavior> >>>>>> >>>>>> Best regards, >>>>>> jens >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>> -- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "Android Security Discussions" group. >>>>> To view this discussion on the web visit >>>>> https://groups.google.com/d/msg/android-security-discuss/-/qKI0PaZewBoJ. >>>>> >>>>> To post to this group, send email to android-secu...@googlegroups.com. >>>>> >>>>> To unsubscribe from this group, send email to >>>>> android-security-discuss+unsubscr...@googlegroups.com. >>>>> For more options, visit this group at >>>>> http://groups.google.com/group/android-security-discuss?hl=en. >>>> >>>> >>> -- >>> You received this message because you are subscribed to the Google Groups >>> "Android Security Discussions" group. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msg/android-security-discuss/-/mtzvEGj2YEAJ. >>> >>> To post to this group, send email to >>> android-security-discuss@googlegroups.com. >>> >>> To unsubscribe from this group, send email to >>> android-security-discuss+unsubscr...@googlegroups.com. >>> For more options, visit this group at >>> http://groups.google.com/group/android-security-discuss?hl=en. >> >> > -- You received this message because you are subscribed to the Google Groups "Android Security Discussions" group. To post to this group, send email to android-security-discuss@googlegroups.com. To unsubscribe from this group, send email to android-security-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/android-security-discuss?hl=en.