Solved

How to obtain browser's certificates from Java?

Posted on 2009-05-18
25
2,160 Views
Last Modified: 2012-05-07
Hello,

I need to be able to obtain the installed certificates from the browser.

In a Browser you can see the list of installed certificates. How can I access that list from a servlet?

This has to work on IE and Firefox.

How do I import the browser certs into my servlet?

Thanks.
0
Comment
Question by:CarlosScheidecker
  • 8
  • 8
  • 7
25 Comments
 
LVL 86

Expert Comment

by:CEHJ
ID: 24417269
Why would you want to do that? A servlet can't access client side code anyway (apart from cookies) but ...
0
 
LVL 92

Expert Comment

by:objects
ID: 24417271
easier to pull them from the server

http://helpdesk.objects.com.au/java/how-do-i-programatically-extract-a-certificate-from-a-site-and-add-it-to-my-keystore

not sure how you would pull them from the browser or even if it is possible

0
 
LVL 92

Expert Comment

by:objects
ID: 24417274
> How do I import the browser certs into my servlet?

you don't. you import them into a keystore
0
PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

 
LVL 1

Author Comment

by:CarlosScheidecker
ID: 24421458
What I mean by Importing to my servlet is that I want something like this:


      private void checkSSLAttributes(HttpServletRequest request, StringBuffer html)
      {
 
            // security checks
            try
            {
                  String cyphersuite = (String)request.getAttribute("javax.servlet.request.cipher_suite");
 
                  if (cyphersuite != null)
                  {
                        html.append("<P>javax.servlet.request.cipher_suite is <B>").append(cyphersuite).append("</B></P>");
                  }
                        
                  cyphersuite = (String)request.getAttribute("javax.net.ssl.cipher_suite");
 
                  if (cyphersuite != null)
                  {
                        html.append("<P>javax.net.ssl.cipher_suite is <B>").append(cyphersuite).append("</B></P>");
                  }
 
                  Object o = request.getAttribute("javax.servlet.request.key_size");
                  if (o != null)
                  {
                        Integer size = (Integer)o;
 
                        html.append("<P>javax.servlet.request.key_size is <B>").append(size.intValue()).append("</B></P>");
                  }
                  else
                  {
                        html.append("<P>javax.servlet.request.key_size not present in this request</P>");
                  }
                  
                  
                  // from 2.1 spec
                  X509Certificate[] certs = (X509Certificate[])request.getAttribute("javax.net.ssl.peer_certificates");
                  
                  if (certs != null && certs.length > 0)
                  {
                        html.append("<P><B>Client Certs 2.1</B><table border='1'><tr><th>type</th></tr>");
                        for (int i=0;i<certs.length;i++)
                        {
                              X509Certificate cert = certs[i];
                              html.append("<tr><td>").append(cert.getType()).append("</td></tr>");
                        }
                        
                        html.append("</table></p>");
                  }
                  
                  
                  // from 2.2 spec
                  certs = (X509Certificate[])request.getAttribute("javax.servlet.request.X509Certificate");
                  if (certs != null && certs.length > 0)
                  {
                        html.append("<P><B>Client Certs 2.2</B><table border='1'><tr><th>type</th></tr>");
                        for (int i=0;i<certs.length;i++)
                        {
                              X509Certificate cert = certs[i];
                              html.append("<tr><td>").append(cert.getType()).append("</td></tr>");
                        }
                        
                        html.append("</table></p>");
                  }
 
            }
            catch (Exception e)
            {
                  e.printStackTrace();
                  html.append("<p>error accessing javax.servlet.request.key_size : ").append(e.getMessage()).append("</p>");
            }
      }
 
      private void checkClientCerts(HttpServletRequest request, StringBuffer html)
      {
            java.security.cert.X509Certificate[] rst = (java.security.cert.X509Certificate[])request.getAttribute( "javax.servlet.request.X509Certificate" );
            
            if (rst != null && rst.length > 0)
            {
                  html.append("<P><B>Client Certs</B><table border='1'><tr><th>Type</th></tr>");
                  for (int i=0;i<rst.length;i++)
                  {
                        java.security.cert.X509Certificate clientCert = rst[i];
                        html.append("<tr><td>").append(clientCert.getType()).append("</td></tr>");
                  }
      
                  html.append("</table></P>");
            }
      }

Open in new window

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24421615
Yes, but that's nothing to do with importing - that's looking at ssl properties. What problems are you having with the above?
0
 
LVL 92

Expert Comment

by:objects
ID: 24421647
thats just giving you whats passed in the request.  You can't get anything directly from the client, the code gets run on the server.
0
 
LVL 1

Author Comment

by:CarlosScheidecker
ID: 24422057

Well, the problem is simple. I need to iterate through all the certs installed in my browser. There are some CA certs that come with it such as Verisign, etc. But I also have some I have installed manually which are not CAs. I need to grab that and use it to pass to my authentication system. So creating the X509 object I can parse the cert and see if that is the one I have created by its name and then use it to authenticate. I have a SOAP system that takes a base64  String representation of the cert and then convert it to a X509 cert object.

Basically I need to inspect my browser for installed certificates by iterating through them. Then grab the cert I need and use it to authenticate.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24422246
All that's not possible for a servlet to do. Browsers, and what's in them, are client-side responsibilities. You'll need to use some sort of browser api to do that so if you want to inspect that situation in connection with the Web, you'll have to use a signed applet or Web Start app
0
 
LVL 1

Author Comment

by:CarlosScheidecker
ID: 24423504
So replying CEHJ:

With the above code above, when the servlet calls checkSSLAttributes the certs X509 array variable which is populated via X509Certificate[])request.getAttribute("javax.servlet.request.X509Certificate") or (X509Certificate[])request.getAttribute("javax.net.ssl.peer_certificates"); returns null.

0
 
LVL 1

Author Comment

by:CarlosScheidecker
ID: 24423531
According to the doc regarding the attribute javax.net.ssl.peer_certificates :

The chain of X.509 certificates which authenticates the client. This is only available when SSL is used with client authentication is used.
0
 
LVL 1

Author Comment

by:CarlosScheidecker
ID: 24423890
I have also tried this without success:
SSLContext sc = SSLContext.getInstance("SSL");
            	
            	String sessionId = request.getSession().getId();
            	
            	SSLSessionContext sslSessionContext = sc.getClientSessionContext();
            	sslSessionContext.getSession(sessionId.getBytes()).getPeerCertificateChain();
            	X509Certificate[] certs1 = sslSessionContext.getSession(sessionId.getBytes()).getPeerCertificateChain();
            	X509Certificate cert1;
            	if (certs1 != null && certs1.length > 0)
                {
                      html.append("<P><B>Client Certs</B><table border='1'><tr><th>type</th></tr>");
                      for (int i=0;i<certs1.length;i++)
                      {
                            cert1 = certs1[i];
                            html.append("<tr><td>").append(cert1.getIssuerDN()).append("</td></tr>");
                      }
                      
                      html.append("</table></p>");
                }

Open in new window

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24423945
>>The chain of X.509 certificates which authenticates the client. This is only available when SSL is used with client authentication is used.

Yes, and also that's not what you're looking for. All that code will do for you is inspect the chain of the particular cert that the client happens to be using at the time - it's not going to cycle through all the browser certs
0
 
LVL 1

Author Comment

by:CarlosScheidecker
ID: 24426191

CEHJ, is there a way to access the Browser' s trustore then? Not the one on the JVM which I know how to do it. Would an applet be able to have access to the browser's truststore or would it only be limited to those certificates on the JVM's trustore.

That is, how to solve this problem? Do I would eventually have to check for Firefox and IE and then call some sort of API to get that stuff?

Thanks.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24426310
>>would eventually have to check for Firefox and IE and then call some sort of API to get that stuff?

That's right
0
 
LVL 1

Author Comment

by:CarlosScheidecker
ID: 24427019
CEHJ,

How about reading the keystore .db files from Firefox?

Something like this:


private static KeyStore openStore(String keystorePassword) throws Exception
    {
String jceprovider = null;
String keyStoreType = null;
KeyStore keystore = null;
 
String keyStoreURL = "C:/Documents and Settings/<user>/Application Data/Mozilla/Firefox/Profiles/l3rm9kk1.default/cert8.db";
 
if (jceprovider.startsWith("SunPKCS11"))
      {
         keystore = KeyStore.getInstance("PKCS11");
         System.out.println(keystore.getProvider());
         System.out.println("Trying to load keystore");
         keystore.load(null, keystorePassword.toCharArray());
         //keystore.load(new FileInputStream(keyStoreURL), keystorePassword.toCharArray());
         System.out.println("keystore loaded");
 
      }
      else // SunJCE, BC, etc.
      {
         keystore = KeyStore.getInstance("JKS");
         //keystore = KeyStore.getInstance("PKCS11");
         System.out.println(keystore.getProvider());
         keystore.load(new FileInputStream(keyStoreURL), keystorePassword.toCharArray());
         //keystore.load(null, keystorePassword.toCharArray());
      }
         return keystore;
   }

Open in new window

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24427048
A possibility - given signed code, yes. Might be better to use the registry though or you'll probably have to recurse the fs
0
 
LVL 92

Expert Comment

by:objects
ID: 24427424
>Would an applet be able to have access to the browser's truststore or would it only be limited to those certificates on the JVM's trustore.

A signed applet can access whatever you want. Your problem will be fining the keystores as not every user will have them in the same location

0
 
LVL 92

Expert Comment

by:objects
ID: 24427427
Plus getting users permission to access their ketstores and disk

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24484272
Considerable guidance provided on this.
0
 
LVL 92

Expert Comment

by:objects
ID: 24488751
you cannot do what you are attempting as I explained above

0
 
LVL 92

Expert Comment

by:objects
ID: 24511160
split

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 24511611
Yes, split please
0
 
LVL 1

Accepted Solution

by:
CarlosScheidecker earned 0 total points
ID: 24538603
It seems to me that there is a solution, albeit not elegant:

It is here http://finger-in-the-eye.blogspot.com/2007/03/cmo-acceder-al-keystore-de-firefox-con.html

The problem is that you need to load the NSS libraries.

However, looking insider sunpcks11.jar  that there might be a better solution.
0

Featured Post

Efficient way to get backups off site to Azure

This user guide provides instructions on how to deploy and configure both a StoneFly Scale Out NAS Enterprise Cloud Drive virtual machine and Veeam Cloud Connect in the Microsoft Azure Cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
print map entry 34 68
even odd program using while loop 3 40
type mismatch (Object[] to double[] 4 24
Which non-HTML GUI front end to use with Java? 3 22
Java had always been an easily readable and understandable language.  Some relatively recent changes in the language seem to be changing this pretty fast, and anyone that had not seen any Java code for the last 5 years will possibly have issues unde…
This was posted to the Netbeans forum a Feb, 2010 and I also sent it to Verisign. Who didn't help much in my struggles to get my application signed. ------------------------- Start The idea here is to target your cell phones with the correct…
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question