I am creating a java standalone application that uses bouncycastle. Everything works in eclipse. I'm creating a jar with dependencies like this.
When I run the application with "java -jar myapp-0.0.1-SNAPSHOT-jar-with-dependencies.jar".
I get the following error :
java.io.IOException: exception encrypting data - java.lang.SecurityException: JCE cannot authenticate the provider BC
My code :
Security.addProvider(new BouncyCastleProvider());
String keystoreDirectory = "C:/myapp/security";
File file = new File(keystoreDirectory + "/" + PRIVATE_KEY_FILE);
if (!file.isFile()) {
try {
Configuration idOrganization = configurationBoundary.find(Configuration.ID_ORGANIZATION);
KeyStore store = KeyStore.getInstance("PKCS12", SECURITY_PROVIDER);
char[] password = KEY.toCharArray();
store.load(null, password);
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", SECURITY_PROVIDER);
keyPairGenerator.initialize(2048);
KeyPair pair = keyPairGenerator.generateKeyPair();
X500Name issuer = new X500Name("CN=" + idOrganization.getProperty());
BigInteger serial = BigInteger.valueOf(new SecureRandom().nextLong());
Date notBefore = new Date(System.currentTimeMillis() - 10000);
Date notAfter = new Date(System.currentTimeMillis() + 24L * 3600 * 1000 * 365);
X500Name subject = new X500Name("CN=" + idOrganization.getProperty());
SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(pair.getPublic().getEncoded());
X509v3CertificateBuilder builder = new X509v3CertificateBuilder(issuer, serial, notBefore, notAfter, subject, publicKeyInfo);
ContentSigner sigGen = new JcaContentSignerBuilder("SHA256WithRSAEncryption").setProvider(SECURITY_PROVIDER).build(pair.getPrivate());
X509Certificate cert = new JcaX509CertificateConverter().setProvider(SECURITY_PROVIDER).getCertificate(builder.build(sigGen));
store.setKeyEntry(idOrganization.getProperty(), pair.getPrivate(), null, new java.security.cert.Certificate[]{cert});
try (FileOutputStream fos = new FileOutputStream(file)) {
store.store(fos, password); //Error here
}
} catch (Exception ex) {
logger.error("Keystore creation error", ex);
}
}
Any ideas ? Thanks.
I have used this plugin for packaging a fat jar
https://github.com/nthuemmel/executable-packer-maven-plugin
it worked fine shading and using bouncy castle within a fat jar
The issue is that the BouncyCastle jar is signed and must be kept as-is. For me, including the dependency in Maven with scope as 'provided' worked.
Bouncycastle jar must be signed and cannot be placed inside fat jar. You can ship it separately and use maven-shade-plugin for this:
In ManifestResourceTransformer you define the classpath for bouncycastle jar dependency.
Unfortunately JCE requires JAR with Bouncy Castle to be signed and creating executable jar ruins it. Prepare to ship BouncyCastle jar separately.
You can actually use Spring Boot or something like that - it embeds jars into fat jar, then unpacks and loads those. Or something Spring Boot-like.