0

I am developing a JavaFX application used to sign pdf using eToken Pro. The sign methods run perfectly in a normal Java project. While when run in the JavaFX application, it keeps encountering exceptions like this:

Exception in Application start method
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.javafx.main.Main.launchApp(Main.java:698)
    at com.javafx.main.Main.main(Main.java:871)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:403)
    at com.sun.javafx.application.LauncherImpl.access$000(LauncherImpl.java:47)
    at com.sun.javafx.application.LauncherImpl$1.run(LauncherImpl.java:115)
    at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.NoClassDefFoundError: sun/security/pkcs11/SunPKCS11
    at javafxapplication3.JavaFXApplication3.start(JavaFXApplication3.java:21)
    at com.sun.javafx.application.LauncherImpl$5.run(LauncherImpl.java:319)
    at com.sun.javafx.application.PlatformImpl$5.run(PlatformImpl.java:216)
    at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:179)
    at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:176)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl$4.run(PlatformImpl.java:176)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:76)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:17)
    at com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:67)
    ... 1 more
Caused by: java.lang.ClassNotFoundException: sun.security.pkcs11.SunPKCS11
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 12 more
Java Result: 1

the codes I used to sign pdf are as follows:

@Override
    public void start(Stage primaryStage) {
        Signer signer = new Signer(new File("C:/Users/Adam/Desktop/pdf/hello.pdf"));
        signer.signWithToken(true);
    }

the codes of class Signer are as follows:

public class Signer {

// define the file to be signed
private final File file;
private static String smartcardDllPath;
private static int level;
private static String reason;
private static String src;
private static String dest;
private static String location;
private static Collection<CrlClient> crlList;
private static OcspClient ocspClient;
private static TSAClient tsaClient;
private static final String DLL = "C:/Windows/System32/eTPKCS11.dll";

public Signer(File theFile) {
    location = "HK SAR";
    smartcardDllPath = null;
    file = theFile;
}


public void signWithToken(boolean certified) {
    try {
        String config = "name=eToken\nlibrary=" + DLL + "\nslotListIndex=" + getSlotsWithTokens(DLL)[0];
        ByteArrayInputStream bais = new ByteArrayInputStream(config.getBytes());
        Provider providerPKCS11 = new SunPKCS11(bais);
        Security.addProvider(providerPKCS11);
        configureParameters(certified);

        // create PdfSignatureAppearance
        PdfSignatureAppearance appearance = getPdfSigAppearance();
        // configure the keystore, alias, private key and certificate chain
        char[] pin = "love4Sakura".toCharArray();
        KeyStore ks = KeyStore.getInstance("PKCS11");
        ks.load(null, pin);
        String alias = (String) ks.aliases().nextElement();
        PrivateKey pk = (PrivateKey) ks.getKey(alias, null);
        Certificate[] chain = ks.getCertificateChain(alias);

        printChainInfo(chain);
        // configure the CRL, OCSP and TSA
        configCrlOcspTsa(chain);
        // create the signature
        ExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256, "SunPKCS11-eToken");
        ExternalDigest digest = new BouncyCastleDigest();
        MakeSignature.signDetached(appearance, digest, pks, chain, crlList, ocspClient,
                tsaClient, 0, MakeSignature.CryptoStandard.CMS);

    } catch (IOException | DocumentException | GeneralSecurityException ex) {
        Logger.getLogger(Signer.class.getName()).log(Level.SEVERE, null, ex);
    }
}

private static long[] getSlotsWithTokens(String libraryPath) {
    CK_C_INITIALIZE_ARGS initArgs = new CK_C_INITIALIZE_ARGS();
    String functionList = "C_GetFunctionList";
    initArgs.flags = 0;
    PKCS11 tmpPKCS11 = null;
    long[] slotList = null;
    try {
        try {
            tmpPKCS11 = PKCS11.getInstance(libraryPath, functionList, initArgs, false);
            System.out.println(tmpPKCS11.toString());
        } catch (IOException ex) {
            try {
                throw ex;
            } catch (IOException ex1) {
                Logger.getLogger(Signer.class.getName()).log(Level.SEVERE, null, ex1);
            }
        }
    } catch (PKCS11Exception e) {
        try {
            initArgs = null;
            tmpPKCS11 = PKCS11.getInstance(libraryPath, functionList, initArgs, true);
        } catch (IOException | PKCS11Exception ex) {
        }
    }
    try {
        slotList = tmpPKCS11.C_GetSlotList(true);
        for (long slot : slotList) {
            CK_TOKEN_INFO tokenInfo = tmpPKCS11.C_GetTokenInfo(slot);
            System.out.println("slot: " + slot + "\nmanufacturerID: "
                    + String.valueOf(tokenInfo.manufacturerID) + "\nmodel: "
                    + String.valueOf(tokenInfo.model));
        }
    } catch (PKCS11Exception ex) {
        Logger.getLogger(Signer.class.getName()).log(Level.SEVERE, null, ex);
    }
    return slotList;
}

Before you guys answer: I want to emphasize that I reference the Signer class in a normal Java Project perfectly. So I donn't think it's a 32-bit or 64-bit problem. Plus, I am using the 32-bit JDK 1.7

Adam Zhang
  • 13
  • 7
  • SunPKCS11 jar is not available in the classpath of you JavaFX project. Suggest you to go through this - http://javareferencegv.blogspot.com/2013/10/debugging-javalangnoclassdeffounderror.html – Crickcoder Feb 12 '14 at 23:16
  • Went through the reference. I also tried to put the SunPKCS11 jar file into the Java classpath. Neither of these works. It's odd that I put the exact source code into an ec(fx)lipse project and it actually worked. Still confusing. But I think you probably right. Something is wrong with the javafx configuration of netbeans, not java. – Adam Zhang Feb 26 '14 at 01:48
  • Anyone want to comment? Thanks – Adam Zhang Aug 24 '15 at 04:28

2 Answers2

0

This issue can be because unsupported version of java.Do one thing download particular jar file for that and include it on your project it'll work for you.

You can download the jar from this link - http://www.docjar.com/jar/sunpkcs11.jar

0

I was also getting the same error -

java.lang.ClassNotFoundException: sun.security.pkcs11.SunPKCS11

Adding the following dependency in pom.xml helped me -

    <dependency>
            <groupId>sunpkcs11</groupId>
            <artifactId>sunpkcs11</artifactId>
            <scope>system</scope>
            <version>1.0</version>
<systemPath>/Library/Java/JavaVirtualMachines/jdk1.8.0_341.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar</systemPath>
    </dependency>

In <systemPath>...</systemPath>, give the appropriate path of sunpkcs11.jar from your system.