views:

3949

answers:

8

I'm bascially looking for someplace to start learning how to interface with a government CAC card using java.

Ultimately, my goal is to find out how to use CAC card authentication (by PIN number) to authorize access to a website hosted using a Tomcat/J2EE server.

But I'll need somewhere to start. So I figure I'd start by writing a small java program to simply read the CAC card information from the CAC card which is inserted into a card reader on my keyboard (DELL keyboard with CAC reader above the numeric keypad).

By searching google, I found the cacard java project (https://cacard.dev.java.net/) which was replaced by the OpenSSO project. But I can't seem to find sample code of how to use it to connect to a card, read from a card, etc.

Does anyone know where I can find some sample code so that I can start learning how to interact with a CAC card using java?

Thanks

EDIT:

After researching more, I was thinking, would I be able to just set clientAuth="true" in the connector element in the server.xml file?

http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html

clientAuth: Set this value to true if you want Tomcat to require all SSL clients to present a client Certificate in order to use this socket.

+4  A: 
erickson
We're creating the web application. So I shouldn't have to worry about reading the card at all correct? The browser should pass the certificate to my web app and as long as the user enters the correct PIN, Tomcat would allow them access. Wrong PIN, Tomcat would deny access right?
That's right. The PIN tells the card to enable the signature operation that supports authentication. See my edits above for more tips. Are you using CACs issued by the US DOD? Is this application for a government agency? There are a lot of extra rules you'll need to follow if so.
erickson
+1. Your web server will just receive an X.509 cert in the request
Kevin
A: 

Thanks for your responses and here's some follow ups to your questions:

Are you using CACs issued by the US DOD?

Yes these are DOD issued CACs.

Is this application for a government agency?

And yes this is for a government agency.

This web app would only be used locally within our organization and all our workstations only with Internet Explorer installed, so the Firefox problem shouldn't matter (for now).

But again, thanks for all the help and at least I have somewhere to start now.

A: 

Did you guys find any solution? I am trying to do the same, first with JDeveloper and if it works, then move to real server. Thanks! -rk

A: 

Look into using cert authentication using an SSO type application such as OpenSSO or JOSSO. The agent should be simpler to embed, and they have already implemented most of the details. If you need to do it yourself, they also have a lot of documentation related to the steps needed such as: digital certificates setup

Joshua
A: 

You need to create a file called card.config and include the following lines in it:

name = myConfig
library = /path/to/library/that/implements/cac/card/reader

And then try this:

import java.io.*;
import java.util.*;

import java.security.cert.CertificateException;
import java.security.KeyStoreException;
import java.security.cert.X509Certificate;

import java.security.KeyStore;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.Security;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

public class Test  
{
   public static void  main(String arg[]) throws Exception
   {
       try
       {   
         //Create our certificates from our CAC Card
         String configName = "card.config";
         Provider p = new sun.security.pkcs11.SunPKCS11(configName);
         Security.addProvider(p);

         //Get the pin from user entered data
         Console c = System.console();
         char[] pin = c.readPassword("Enter your PIN: ");
         KeyStore cac = null;

         cac = KeyStore.getInstance("PKCS11");
         cac.load(null, pin);

         showInfoAboutCAC(cac);

      }
      catch(Exception ex)
      {
         //System.out.println("*" + ex.getMessage());
         ex.printStackTrace();
         System.exit(0);
      }
   }

   public static void showInfoAboutCAC(KeyStore ks) throws KeyStoreException, CertificateException
   {
      Enumeration<String> aliases = ks.aliases();

      while (aliases.hasMoreElements()) 
      {
         String alias = aliases.nextElement();
         X509Certificate[] cchain = (X509Certificate[]) ks.getCertificateChain(alias);

         System.out.println("Certificate Chain for : " + alias);
         for (int i = 0; i < cchain.length; i ++)
         {
            System.out.println(i + " SubjectDN: " + cchain[i].getSubjectDN());
            System.out.println(i + " IssuerDN:  " + cchain[i].getIssuerDN());
         }
      }
   }
}

At this point you have a keystore that you can use to create the ssl socket to talk to the https web server.

Jay
A: 

We would like to ensure that the user has to renter their PIN to access the one of our browser-based applications. Is there a way to "deauthenticate" the user so that they have to authenticate again?

ag5653
A: 

"We would like to ensure that the user has to renter their PIN to access the one of our browser-based applications. Is there a way to "deauthenticate" the user so that they have to authenticate again?"

Maybe close the socket on the server side so that the connection has to be re-established?

Jay
A: 

How do we force a browser to read client certificate from CAC Card only. I know we can set 'clientAuth' attribute at server and force client to produce a client certificate, but browser may just try to search certificate in a local keystore/truststore.

Also I guess client may produce a certificate chain instead of just one certificate how do we validate correct certificate at server.

Deep