title: Using Java PKCS#11 to read DoD Common Access Card
body: <p>I have researched on how to use Sun PKCS#11 api to access a DoD CAC and possibly use the CAC to access (read-only) Active Directory. My problem has been, what I have found in most cases will make a reference to some code, but never shows the referenced code. I have found the following code, but gives an error. Does anyone know of any code examples or clear documentation for using PKCS11 for CACs? Or an API solution which might work?</p>
  
  <pre><code>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.Security;
  
  
  public class SmartCard {
      public static void main(String[] args) throws Exception {
          try {
              String configName = "pkcs11.properties";
              Provider p = new sun.security.pkcs11.SunPKCS11(configName);
              Security.addProvider(p);
              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) {
              ex.printStackTrace();
              System.exit(0);
          }
      }
      public static void showInfoAboutCAC(KeyStore ks) throws KeyStoreException, CertificateException {
          Enumeration&lt;String&gt; 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 &lt; cchain.length; i++) {
                  System.out.println(" -SubjectDN: " + cchain[i].getSubjectDN());
                  System.out.println(" -IssuerDN: " + cchain[i].getIssuerDN());
              }
          }
      }
  }
  
  java.security.ProviderException: Initialization failed
          at sun.security.pkcs11.SunPKCS11.&lt;init&gt;(SunPKCS11.java:374)
          at sun.security.pkcs11.SunPKCS11.&lt;init&gt;(SunPKCS11.java:103)
          at smartcard.SmartCard.main(SmartCard.java:21)
  Caused by: java.io.IOException: The specified procedure could not be found.
  
          at sun.security.pkcs11.wrapper.PKCS11.connect(Native Method)
          at sun.security.pkcs11.wrapper.PKCS11.&lt;init&gt;(PKCS11.java:137)
          at sun.security.pkcs11.wrapper.PKCS11.getInstance(PKCS11.java:150)
          at sun.security.pkcs11.SunPKCS11.&lt;init&gt;(SunPKCS11.java:312)
          ... 2 more
  </code></pre>