Hi Brian, sorry for writing the third time. That is how I try to accomplish it right now:
KeyManager keyManager = KeyChainKeyManager.fromAlias(getApplicationContext(), ht.mClientCertAlias); sslContext = SSLContext.getInstance("TLS"); sslContext.init(new KeyManager[] { keyManager }, getCustomTrustManagers(), new SecureRandom()); HttpsURLConnection urlConnection = null; URL url = new URL(this.url); urlConnection = (HttpsURLConnection) url.openConnection(); urlConnection.setConnectTimeout(5000); // 5 seconds urlConnection.setReadTimeout(10000); urlConnection.setSSLSocketFactory(sslContext.getSocketFactory()); iResponseCode = urlConnection.getResponseCode(); I get an exception:* javax.net.ssl.SSLException: Read error: ssl=0x2c5e40: I/O error during system call, Connection reset by peer* * * Do you know what this can mean. I didn't find much information in the net. best regards, jens * * Am Montag, 3. Dezember 2012 18:14:35 UTC+1 schrieb Jens Hoffmann: > > Hi Brian, > > why do I have to create my own my *own X509KeyManager*? Can't I just use > the one from the google email app? > > The *SSLUtils*.class (google email app) has a fromAlias methode which > gives back a *KeyChainKeyManager-*object. > see: (return new KeyChainKeyManager(alias, certificateChain, privateKey) > * > * > That is how I init my *SSLContext *: > > sslContext = SSLContext.getInstance("TLS"); > *sslContext.init(new KeyManager[] { keyManager }, null, null;* > * > * > => The* KeyChainKeyManager *class* *extends the* StubKeyManager *class, > which extends the * X509ExtendedKeyManager* class. > > And the methods: chooseClientAlias, getCertificateChain, getPrivateKey are > implemented there. > > best regards, > > jens. > > > > > Am Donnerstag, 29. November 2012 23:19:59 UTC+1 schrieb Brian Carlstrom: >> >> 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 <jenss...@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 <jenss...@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-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/-/lhbWus8O0loJ. 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.