'Packaging Java application with BouncyCastle in a single JAR

Is it possible to package a Java app using BouncyCastle as security provider in a single JAR ?

PS: I expect to run the JAR without changing java security properties (in other words, without adding BouncyCastle as Security provider in JRE)



Solution 1:[1]

Please ensure you have some reasonable expectations and understanding regarding on how BouncyCastle and other security providers work.

For the latest BouncyCastle package and version information please review: https://www.bouncycastle.org/latest_releases.html

You don't have to download the JAR files from the above link. For the appropriate signed Maven packages see: https://mvnrepository.com/artifact/org.bouncycastle

The solution to this problem is to use https://github.com/nthuemmel/executable-packer-maven-plugin as suggested in the comments. Using the shade plugin (or many others) results in the BC JARs being repacked, breaking the security of the packages - causing failures when you attempt to run your uber JAR.

You still need to set the provider as BouncyCastle regardless.

The pom.xml file should have BouncyCastle listed as a dependency:

<dependency>
  <groupId>org.bouncycastle</groupId>
  <artifactId>bcprov-jdk18on</artifactId>
  <version>1.71</version>
</dependency>

<dependency>
  <groupId>org.bouncycastle</groupId>
  <artifactId>bcpkix-jdk18on</artifactId>
  <version>1.71</version>
</dependency>

(Which specific packages you need may vary.)

In your pom.xml you should also have something like the following in the plugins section:

  <plugin>
    <groupId>de.ntcomputer</groupId>
    <artifactId>executable-packer-maven-plugin</artifactId>
    <version>1.0.1</version>
    <configuration>
      <mainClass>com.ericsson.ml66.pki.Pki</mainClass>
    </configuration>
    <executions>
      <execution>
        <goals>
          <goal>pack-executable-jar</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

In your code, within your class initialisation or other pertinent location, you should have:

if (Security.getProvider("BC") == null) {
    Security.addProvider(new BouncyCastleProvider());
}

For good measure and to ensure the correct provider is used, I would also do specify the BouncyCastle provided where needed, such as:

PEMEncryptor encryptor =
    new JcePEMEncryptorBuilder("AES-256-CBC").setProvider("BC").build(passphrase);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Raphael Krausz