bouncycastle error “JCE cannot authenticate the pr

2019-04-01 19:34发布

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.

4条回答
2楼-- · 2019-04-01 20:07

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

查看更多
3楼-- · 2019-04-01 20:10

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.

    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
        <version>1.55</version>
        <scope>provided</scope>
    </dependency>
查看更多
霸刀☆藐视天下
4楼-- · 2019-04-01 20:14

Bouncycastle jar must be signed and cannot be placed inside fat jar. You can ship it separately and use maven-shade-plugin for this:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.3</version>
            <configuration>
                <artifactSet>
                    <excludes>
                        <exclude>org.bouncycastle:*:*:*</exclude>
                    </excludes>
                </artifactSet>
                <transformers>
                    <transformer
                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <manifestEntries>
                            <Main-Class>com.example.Main</Main-Class>
                            <Class-Path>. ./lib/bcprov-jdk16-1.46.jar</Class-Path>
                        </manifestEntries>
                    </transformer>
                </transformers>
                <shadedArtifactAttached>true</shadedArtifactAttached>
                <shadedClassifierName>fat</shadedClassifierName>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

In ManifestResourceTransformer you define the classpath for bouncycastle jar dependency.

查看更多
欢心
5楼-- · 2019-04-01 20:21

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.

查看更多
登录 后发表回答