title: How to sign a jar with a smartcard
body: <p>I'm using a PKCS11 smartcard at work, and would like to use jarsigner to sign jar files using the certificate on my card.</p>
  
  <p>I'm mostly working on Linux. Coolkey can see the card.</p>
  
  <p><a href="http://docs.oracle.com/javase/7/docs/technotes/tools/windows/jarsigner.html" rel="nofollow">Oracle's documentation</a> mentions smartcards:</p>
  
  <pre><code>jarsigner -keystore NONE -storetype PKCS11 \
      -providerName SunPKCS11-SmartCard \
      -list
  </code></pre>
  
  <p>But there's apparently no actual provider by that name, and the -list argument to jarsigner doesn't appear to exist.</p>
  
  <p>I finally got jarsigner to see the card, but it reports that it isn't a valid entry and doesn't have a private key:</p>
  
  <pre><code>jarsigner -keystore NONE -storetype PKCS11 \
    -providerClass sun.security.pkcs11.SunPKCS11 \
    -providerArg smartcard.config \
    -storepass notmyrealpass \
    myjarfile.jar 'Identity #0'
  
  jarsigner: Certificate chain not found for: Identity #0.
    Identity #0 must reference a valid KeyStore key entry
    containing a private key and corresponding public key
    certificate chain.
  </code></pre>
  
  <p>Where smartcard.config is:</p>
  
  <pre><code>name=Kittens
  library=/usr/lib/pkcs11/libcoolkeypk11.so
  </code></pre>
  
  <p>I got the list of aliases [from which "Identity #0" comes] programmatically by loading the card in Java:</p>
  
  <pre><code>String conf = "name=Kittens\nlibrary=/usr/lib/pkcs11/libcoolkeypk11.so";
  InputStream s = new ByteArrayInputStream(conf.getBytes());
  Provider p = new sun.security.pkcs11.SunPKCS11(s);
  KeyStore keyStore = KeyStore.getInstance("PKCS11", p);
  keyStore.load(null, "notmyrealpass".toCharArray());
  Enumeration&lt;String&gt; aliases = keyStore.aliases();
  // Aliases contains "Identity #0", "Identity #1", "Identity #2"
  </code></pre>
  
  <p>The whole point of these smartcards is that the private key stays on the card, and the card is what does the signing; is there no way to make jarsigner do what I want?</p>
  
  <p>EDIT:</p>
  
  <p>After some more noodling, I noticed that I don't seem to be able to use SHA1withDSA, only SHA1withRSA:</p>
  
  <pre><code>Set&lt;Provider.Service&gt; services = p.getServices();
  for(Provider.Service service : services) {
      System.out.println(service.getAlgorithm());
  }
  </code></pre>
  
  <p>prints this list: SHA512withRSA, SHA256withRSA, SHA1withRSA, MD5withRSA, RSA/ECB/PKCS1Padding, SHA384withRSA, MD2withRSA, RSA, PKCS11</p>
  
  <p>But I notice that signed jars all seem to use DSA; is this likely to be the issue?</p>