title: iText: using java to digitally sign PDF doc and observing java.security.NoSuchAlgorithmException error
body: <p>I have a SafeNet eToken 5100 USB Token with PDF Digital Signing Certificate on it. I configured a windows and mac system to use it and I succeeded in manually signing PDF files with its certificate on both machines. Thus the certificate works as intended. </p>
  
  <p>I shipped the token to my web host company and they placed it on my Linux (CentOS) server. I installed SafeNet Authentication Client on the server.</p>
  
  <p>Now I'm attempting to use iText to apply the signature. I'm following code sample 4.2 from this excellent book: <a href="http://itextpdf.com/book/digitalsignatures" rel="nofollow">http://itextpdf.com/book/digitalsignatures</a>. My code is:</p>
  
  <pre><code>    String config = "name = eToken5100_20130805\n" +
                 "library = /usr/lib64/libeTPkcs11.so\n" +
                 "slot = 0";  // create a dynamic conf file
      ByteArrayInputStream bais = new ByteArrayInputStream(config.getBytes());
      Provider providerPKCS11 = new SunPKCS11(bais);
      Security.addProvider(providerPKCS11);
      System.out.println(providerPKCS11.getName());
      BouncyCastleProvider providerBC = new BouncyCastleProvider();
      Security.addProvider(providerBC);
  
      KeyStore ks = KeyStore.getInstance("PKCS11", providerPKCS11);
      ks.load(null, K.PASS_TOKEN);
      String alias = (String)ks.aliases().nextElement();
      PrivateKey pk = (PrivateKey)ks.getKey(alias, K.PASS_TOKEN);
      Certificate[] chain = ks.getCertificateChain(alias);
      OcspClient ocspClient = new OcspClientBouncyCastle();
      TSAClient tsaClient = null;
      for (int i = 0; i &lt; chain.length; i++) {
          X509Certificate cert = (X509Certificate)chain[i];
          String tsaUrl = CertificateUtil.getTSAURL(cert);
          if (tsaUrl != null) {
              tsaClient = new TSAClientBouncyCastle(tsaUrl);
              break;
          }
      }
      List&lt;CrlClient&gt; crlList = new ArrayList&lt;CrlClient&gt;();
      crlList.add(new CrlClientOnline(chain));
      sign(userFile, userFile_signed, chain, pk, DigestAlgorithms.SHA256, providerPKCS11.getName(),
                   CryptoStandard.CMS, "Test", "Ghent", crlList, ocspClient, tsaClient, 0);
  </code></pre>
  
  <p>when I run this code, it generates the following runtime error:</p>
  
  <pre><code>stack trace: java.security.KeyStoreException: PKCS11 not found
  Caused by: java.security.NoSuchAlgorithmException: no such algorithm: 
    PKCS11 for provider SunPKCS11-eToken5100_20130805
  </code></pre>
  
  <p><a href="http://www.forumeasy.com/forums/thread.jsp?tid=120372742989&amp;fid=javaprof34&amp;highlight=SSL/TLS%20Error%20Database%20Loading%20KeyStore" rel="nofollow">This link</a> indicates that the wrong keystore type might generate this error. I checked my <code>~glassfish/java/jdk7u25/jdk1.7.0_25/jre/lib/security/java.security</code> file and it uses a keystore of <code>jks</code>. However, changing it to <code>PKCS11</code> causes my GlassFish server not to restart. So I kept it as <code>jks</code>. </p>
  
  <p>QUESTION 1: Could this cause the problem? If so, how to resolve?</p>
  
  <p>QUESTION 2: I just made up the name <code>eToken5100_20130805</code> in the java code above... but does this name need to match some other name somewhere? (the Java code above is the only place I entered this name).</p>
  
  <p>QUESTION 3: I know the library is correct, but how do I determine the slot number? I have manually entered slots 0 through 6 (just guessing) and they each produced the same error shown above. Further, if I enter slot numbers 7 through 10, a PKCS11Exception CKR_SLOT_ID_INVALID is thrown each time.</p>
  
  <p>I don't know much about this topic, but I tried to determine the slot number various ways:</p>
  
  <p>(A) I'm not sure if the following syntax is correct:</p>
  
  <pre><code># keytool -v -list -keystore NONE -storetype PKCS11 -providername SunPKCS11-eToken5100_20130805 -J-Djava.security.debug=sunpkcs11,pkcs11
  </code></pre>
  
  <p>but it returns this output:</p>
  
  <pre><code>keytool error: java.security.NoSuchProviderException: no such provider: SunPKCS11-eToken5100_20130805
  java.security.NoSuchProviderException: no such provider: SunPKCS11-eToken5100_20130805
  at sun.security.jca.GetInstance.getService(GetInstance.java:83)
  at sun.security.jca.GetInstance.getInstance(GetInstance.java:206)
  at java.security.Security.getImpl(Security.java:698)
  at java.security.KeyStore.getInstance(KeyStore.java:661)
  at sun.security.tools.KeyTool.doCommands(KeyTool.java:765)
  at sun.security.tools.KeyTool.run(KeyTool.java:340)
  at sun.security.tools.KeyTool.main(KeyTool.java:333) 
  </code></pre>
  
  <p>(B) I also tried to use modutil to find the slot number:</p>
  
  <pre><code># modutil -list -dbdir $HOME/.mozilla/firefox/*.default
  </code></pre>
  
  <p>but I'm not sure what it means when it returns the following:</p>
  
  <pre><code>winscard_clnt.c:420:SCardEstablishContextTH() Your pcscd is too old and does not support CMD_VERSION
  winscard_clnt.c:420:SCardEstablishContextTH() Your pcscd is too old and does not support CMD_VERSION
  
    Listing of PKCS #11 Modules
    -----------------------------------------------------------
    1. NSS Internal PKCS #11 Module
  slots: 2 slots attached
  status: loaded
  
   slot: NSS Internal Cryptographic Services
  token: NSS Generic Crypto Services
  
   slot: NSS User Private Key and Certificate Services
  token: NSS Certificate DB
  
  2. eToken
  library name: libeTPkcs11.so
   slots: 6 slots attached
   status: loaded
  
   slot: 
   token: 
  
   slot: 
   token: 
  
   slot: 
   token: 
  
   slot: 
   token: 
  
   slot: 
   token: 
  
   slot: 
   token: 
  </code></pre>
  
  <p>(C) Lastly, I tried to run</p>
  
  <pre><code># pkcs11-tool --module /usr/lib64/libeTPkcs11.so --list-slots 
  </code></pre>
  
  <p>but this requires to first install openSC to obtain the pkcs11-tool. When I attempt to install using: <code># yum install opensc.x86_64</code>, it gives the following error: </p>
  
  <pre><code>Transaction Check Error: 
  file /usr/lib64/libpcsclite.so.1.0.0 from install of pcsc-lite-libs-1.5.2-13.el6_4.x86_64
  conflicts with file from package libpcsclite1-1.4.0-9.el6.x86_64`
  </code></pre>
  
  <p>and I can't figure out how to overcome this error. </p>
  
  <p>I could use some help navigating these unfamiliar errors, to understand what the problem is, then how to resolve it. Does it appear the slot number is indeed incorrect (can slot numbers be large, like, 31310? So far I'm assuming they're single digit...), or something else?</p>
  
  <p>---------- UPDATE ----------</p>
  
  <p>My linux machine had a package installed for <code>libpcsclite1</code> that caused the error described above. I uninstalled SafeNet Auth Client (SAC), removed this package, installed pcsc-lite (using yum), and re-installed the standard SAC. I also installed opensc using yum so I can use pkcs11-tool. I can now see the slot using:</p>
  
  <pre><code># pkcs11-tool --module /usr/lib64/libeToken.so -L
  Available slots:
  Slot 0 (0x0): AKS xxxx 00 00
   token label:   my label
   token manuf:   SafeNet, Inc.
   token model:   eToken
   token flags:   rng, login required, PIN initialized, token initialized, other flags=0x200
   serial num  :  xxxxxxx
  Slot 1 (0x1): 
    (empty)
  Slot 2 (0x2): 
    (empty)
  Slot 3 (0x3): 
    (empty)
  Slot 4 (0x4): 
    (empty)
  Slot 5 (0x5): 
    (empty)
  </code></pre>
  
  <p>Now I can run everything without generating runtime errors. However, the resulting PDF file displays "At least one signature is invalid". [update: my mistake, I was looking at the wrong file. The signed PDF file shows a valid signature.]</p>