title: Java SSL client not selecting a smartcard key
body: <p>I'm trying to use an Estonian ID card for SSL client authentication in a java program.  This works in Chrome/Firefox against both banking sites and test servers (nginx or openssl s_server).</p>
  
  <p>However my Java client (okhttp) works fine for a local keystore and fails when trying to use the ID card.  I've boiled it down to this test case which reproduces the problem I see in a debugger and with logging (-Djavax.net.debug=ssl:handshake).</p>
  
  <p>I can communicate with the card, e.g. I can print out the certificates for the same key. I'm piggybacking on the <a href="http://www.id.ee/index.php?id=30591" rel="nofollow">DigiDoc3 Client</a> on Mac OSX.</p>
  
  <p>I can see the exception that seems to cause the key to be ignored</p>
  
  <pre><code>sun.security.pkcs11.wrapper.PKCS11Exception: CKR_ATTRIBUTE_TYPE_INVALID
      at sun.security.pkcs11.wrapper.PKCS11.C_GetAttributeValue(Native Method)
      at sun.security.pkcs11.P11Key.getAttributes(P11Key.java:275)
      at sun.security.pkcs11.P11Key.privateKey(P11Key.java:330)
      at sun.security.pkcs11.P11KeyStore.loadPkey(P11KeyStore.java:1311)
      at sun.security.pkcs11.P11KeyStore.engineGetEntry(P11KeyStore.java:943)
      at java.security.KeyStore.getEntry(KeyStore.java:1521)
      at sun.security.ssl.X509KeyManagerImpl.getEntry(X509KeyManagerImpl.java:276)
      at sun.security.ssl.X509KeyManagerImpl.getCertificateChain(X509KeyManagerImpl.java:107)
      at com.baulsupp.oksocial.TestMain.main(TestMain.java:37)
  </code></pre>
  
  <p>Test program output</p>
  
  <pre><code>1.0.Authentication
  ssl: KeyMgr: choosing key: Authentication (verified: OK)
  null
  null
  </code></pre>
  
  <p>Test code</p>
  
  <pre><code>package com.baulsupp.oksocial;
  
  import java.io.ByteArrayInputStream;
  import java.io.IOException;
  import java.security.KeyStore;
  import java.security.KeyStoreException;
  import java.security.NoSuchAlgorithmException;
  import java.security.PrivateKey;
  import java.security.Provider;
  import java.security.Security;
  import java.security.UnrecoverableKeyException;
  import java.security.cert.Certificate;
  import java.security.cert.CertificateException;
  import java.security.cert.X509Certificate;
  import java.util.Enumeration;
  import java.util.Set;
  import javax.net.ssl.KeyManager;
  import javax.net.ssl.KeyManagerFactory;
  import javax.net.ssl.X509ExtendedKeyManager;
  
  public class TestMain {
    public static void main(String[] args)
        throws UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException,
        KeyStoreException, IOException {
      System.setProperty("javax.net.debug", "all");
  
      char[] password =
          System.getenv().get("PW").toCharArray();//System.console().readPassword("PW: ");
  
      X509ExtendedKeyManager km = (X509ExtendedKeyManager) getKeyManagers(password, 0)[0];
  
      String alias = km.chooseClientAlias(new String[] {"RSA"}, null, null);
  
      System.out.println(alias);
  
      X509Certificate[] chain = km.getCertificateChain(alias);
      System.out.println(chain);
  
      PrivateKey key = km.getPrivateKey(alias);
      System.out.println(key);
    }
  
    public static KeyManager[] getKeyManagers(char[] password, int slot)
        throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException,
        UnrecoverableKeyException {
      //Security.removeProvider("IAIK");
  
      //Provider provider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
      //Security.addProvider(provider);
  
      String config =
          "name=OpenSC\nlibrary=/Applications/qdigidocclient.app/Contents/MacOS/esteid-pkcs11.so\nslotListIndex="
              + slot;
  
      sun.security.pkcs11.SunPKCS11 pkcs11 =
          new sun.security.pkcs11.SunPKCS11(new ByteArrayInputStream(config.getBytes()));
  
      Security.addProvider(pkcs11);
  
      //debugProviders();
  
      KeyStore keystore = KeyStore.getInstance("PKCS11", pkcs11);
  
      keystore.load(null, password);
  
      //debugKeys(keystore);
  
      KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
      kmf.init(keystore, null);
  
      return kmf.getKeyManagers();
    }
  
    public static void debugKeys(KeyStore keystore) throws KeyStoreException {
      Enumeration&lt;String&gt; aliases = keystore.aliases();
  
      while (aliases.hasMoreElements()) {
        String s = aliases.nextElement();
  
        Certificate k = keystore.getCertificate(s);
  
        System.out.println(k);
      }
    }
  
    public static void debugProviders() {
      Provider[] providers = Security.getProviders();
      for (Provider p : providers) {
        System.out.println("\n\n" + p.getName());
        Set&lt;Provider.Service&gt; services = p.getServices();
  
        for (Provider.Service s : services) {
          System.out.println(s.getType() + " " + s.getAlgorithm());
        }
      }
    }
  }
  </code></pre>
  
  <p>In the mean time I've put in a support request as well.</p>