ebourg / jsign

Java implementation of Microsoft Authenticode for signing Windows executables, installers & scripts
https://ebourg.github.io/jsign
Apache License 2.0
250 stars 107 forks source link

NoClassDefFoundError when using a key file with the command line tool or the Ant task #163

Closed hegusung closed 3 months ago

hegusung commented 1 year ago

Hello, I tried using jsign but got the following error:

java -jar jsign-5.0.jar --certfile cert.crt --keyfile cert.pem --keypass 'password' binary.exe
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
Exception in thread "main" java.lang.NoClassDefFoundError: net/jsign/bouncycastle/pqc/jcajce/provider/sphincsplus/SPHINCSPlusKeyFactorySpi
    at net.jsign.bouncycastle.jce.provider.BouncyCastleProvider.loadPQCKeys(Unknown Source)
    at net.jsign.bouncycastle.jce.provider.BouncyCastleProvider.setup(Unknown Source)
    at net.jsign.bouncycastle.jce.provider.BouncyCastleProvider.access$000(Unknown Source)
    at net.jsign.bouncycastle.jce.provider.BouncyCastleProvider$1.run(Unknown Source)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:319)
    at net.jsign.bouncycastle.jce.provider.BouncyCastleProvider.<init>(Unknown Source)
    at net.jsign.PrivateKeyUtils.readPrivateKeyPEM(PrivateKeyUtils.java:88)
    at net.jsign.PrivateKeyUtils.load(PrivateKeyUtils.java:66)
    at net.jsign.KeyStoreType$1.getKeystore(KeyStoreType.java:85)
    at net.jsign.KeyStoreBuilder.build(KeyStoreBuilder.java:283)
    at net.jsign.SignerHelper.build(SignerHelper.java:256)
    at net.jsign.SignerHelper.sign(SignerHelper.java:388)
    at net.jsign.JsignCLI.execute(JsignCLI.java:132)
    at net.jsign.JsignCLI.main(JsignCLI.java:40)
Caused by: java.lang.ClassNotFoundException: net.jsign.bouncycastle.pqc.jcajce.provider.sphincsplus.SPHINCSPlusKeyFactorySpi
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
... 14 more

The .deb version didn't work either, what am I doing wrong ?

Regards

ebourg commented 1 year ago

Thank you for reporting the issue, I'll look into it.

ebourg commented 1 year ago

You are loading the private key from a file? What encryption does it use?

hegusung commented 1 year ago

Here is the encryption used :

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: XXXXXXXX (0xXXXXXXX)
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: <redacted>
        Validity
            Not Before: Jun  X XX:XX:XX 20XX GMT
            Not After : Jun  X XX:XX:XX 20XX GMT
        Subject: <redacted>
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)

The certificate works with osslsigncode without any issue. But I need to sign scripts.

ebourg commented 1 year ago

That's the certificate, but how is encoded the private key?

hegusung commented 1 year ago

PEM file format, not sure if I answer your question correctly, if not which openssl command should I do to give you the answer ?

ebourg commented 1 year ago

I've been able to reproduce the issue, loading the private key from a PEM file no longer works. Bouncy Castle added a bunch of post quantum crypto algorithms, they are of no use to Jsign but are still required on the classpath.

hegusung commented 1 year ago

Thanks a lot, looking forward to test this !

ebourg commented 1 year ago

In the meantime, if you use a PKCS#12 keystore instead of a key file it should work.

ebourg commented 1 year ago

Upon further investigations:

I'm tempted to drop the support for encrypted key files from the command line tool and the Ant task, hardware tokens and KMS are becoming the norm anyway.

ebourg commented 10 months ago

A solution for the all-in-one jar would be to use Spring Boot instead of Maven Shade Plugin, that would fix the issue for the command line tool, but not for the Ant task. The jar would become unusable from Ant.

For the Ant task the proper solution would be use the jsign-ant artifact and its dependencies, typically using Ivy to build the classpath.

Alternatively, not using Bouncy Castle to decrypt the key would be fine too.