Building an uberjar with bouncycastle


(Josh) #1

I’m trying to build 1 executable jar file with all my dependencies. One of my dependencies is bouncycastle. I’ve found multiple solutions, but none have worked for me yet. Here’s what I’ve tried:

Here are my relevant dependencies:

dependencies {
    // ... snip ...
    compile group: 'org.bouncycastle', name: 'bcpg-jdk15on', version: '1.52'
    compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.52'
    // ... snip ...
}

With this config:

jar {
    // thanks: https://stackoverflow.com/questions/22911190/gradle-build-dependancy-throwing-classnotfoundexception/23010014#23010014
    from {
        configurations.compile.collect {
            it.isDirectory() ? it : zipTree(it)
        }
    }
    manifest {
        attributes 'Main-Class': 'my.Main'
    }
}

I get the following exception when running the jar:

java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
        at sun.security.util.SignatureFileVerifier.processImpl(Unknown Source)
        at sun.security.util.SignatureFileVerifier.process(Unknown Source)
        at java.util.jar.JarVerifier.processEntry(Unknown Source)
        at java.util.jar.JarVerifier.update(Unknown Source)
        at java.util.jar.JarFile.initializeVerifier(Unknown Source)
        at java.util.jar.JarFile.getInputStream(Unknown Source)
        at sun.misc.URLClassPath$JarLoader$2.getInputStream(Unknown Source)
        at sun.misc.Resource.cachedInputStream(Unknown Source)
        at sun.misc.Resource.getByteBuffer(Unknown Source)
        at java.net.URLClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.access$100(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
Error: A JNI error has occurred, please check your installation and try again

With this config:

jar {
    from {
        configurations.compile.collect {
            it.isDirectory() ? it : zipTree(it)
        }
    }
    exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
    manifest {
        attributes 'Main-Class': 'my.Main'
    }
}

I get a PGPException…

org.bouncycastle.openpgp.PGPException: Exception decrypting key

…with the following underlying exception:

java.lang.SecurityException: JCE cannot authenticate the provider BC

It seems like I’m packaging bouncycastle’s signatures incorrectly, but I’m not sure how I should be doing this when making an uberjar.


(Lance Java) #2

(Josh) #3

So my code above (correct me if I’m wrong) is re-packaging all my dependencies. If that’s the case, I need to figure out how Eclipse’s Export as Runnable Jar File works, because that makes an uberjar that doesn’t break when packaging BC.


(Lance Java) #4

http://www.java2s.com/Tutorial/Java/0180__File/Comparetwozipfiles.htm


(Josh) #5

Hmm. It looks like Eclipse is including the jar files (unmodified) and my build is extracting all the .class files. I’ll have to see if I can do what Eclipse is doing.


(Lance Java) #7

It looks like OneJar supports jars within a jar via a custom classloader.

There’s a OneJar gradle plugin at

I’m guessing eclipse is doing something similar. Check the eclipse jar manifest. Is it specifying your class as the Main-Class? My guess no (it’s being proxied through another utility)


(Josh) #8

Looks like Eclipse has its own loader:

Rsrc-Main-Class: my.Main
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader

After some trying, the OneJar plugin got me most of the way there… unfortunately not the whole way:

[Boot] INFO:  setProperties(com.simontuffs.onejar.JarClassLoader@6e0be858)
[Boot] INFO:  using JarClassLoader: com.simontuffs.onejar.JarClassLoader
Exception in thread "main" java.lang.NullPointerException
	at java.lang.String.replace(String.java:2240)
	at com.simontuffs.onejar.JarClassLoader.replaceProps(JarClassLoader.java:501)
	at com.simontuffs.onejar.JarClassLoader.load(JarClassLoader.java:349)
	at com.simontuffs.onejar.JarClassLoader.load(JarClassLoader.java:319)
	at com.simontuffs.onejar.Boot.run(Boot.java:295)
	at com.simontuffs.onejar.Boot.main(Boot.java:161)

I’ll try a few more things and open an issue on the OneJar repo if I think it’s their issue. Thanks for your help!


uploadArchives breaks jar created with shadowJar
(Lance Java) #9

If you can’t get OneJar working you could just extract JarRsrcLoader.class from the eclipse jar and pack into yours using the same manifest values.

Obviously a bit hacky but if it works i wouldn’t lose any sleep over it :wink:


(Josh) #10

I opened an issue. I’d rather not hack it :stuck_out_tongue:


(Thomas Maslen) #11

A possible alternative to one-jar or the Eclipse export-as-runnable-jar is the spring-boot-loader. I have successfully used it with the Bouncy Castle provider (and, in contrast to one-jar, I didn’t have to do anything clever to make it work). I think I saw that it has a Gradle plugin but I haven’t tried it; I was still just using Maven.