title: Bouncy castle with spring boot
body: <p>I am trying to use Https over http, I generated the CA certificate with bouncy castle and generated from the <code>.cer</code> file the <code>jks</code> file, spring boot started successfully with the properties provided with an embedded tomcat.</p>
  
  <p>The problem is that I'm getting always <strong>insecure ssl certificate</strong> from the browser (for example from chrome : <code>This CA Root certificate is not trusted because it is not in the Trusted Root Certification Authorities store.</code>) while I add the trust store programatically with another config class.</p>
  
  <p>Here is my code: </p>
  
  <pre><code>import org.apache.commons.codec.binary.Base64; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.cmp.CertRepMessage; import org.bouncycastle.asn1.cmp.PKIBody; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.cert.CertException; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.X509v3CertificateBuilder; import org.bouncycastle.cert.cmp.CMPException; import org.bouncycastle.cert.cmp.ProtectedPKIMessage; import org.bouncycastle.cert.cmp.ProtectedPKIMessageBuilder; import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.ContentVerifierProvider; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
  
  import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.math.BigInteger; import java.security.*; import java.security.cert.X509Certificate; import java.util.Date;
  
  public class generateService {
  
      private static final String BC = BouncyCastleProvider.PROVIDER_NAME;
  
  
      private static X509CertificateHolder makeV3Certificate(KeyPair subKP, String _subDN, KeyPair issKP, String _issDN)
              throws GeneralSecurityException, IOException, OperatorCreationException, CertException
      {
  
          PublicKey subPub  = subKP.getPublic();
          PrivateKey issPriv = issKP.getPrivate();
          PublicKey  issPub  = issKP.getPublic();
  
          X509v3CertificateBuilder v1CertGen = new JcaX509v3CertificateBuilder(
                  new X500Name(_issDN),
                  BigInteger.valueOf(System.currentTimeMillis()),
                  new Date(System.currentTimeMillis()),
                  new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100)),
                  new X500Name(_subDN),
                  subPub);
  
          ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSA").setProvider(BC).build(issPriv);
  
          X509CertificateHolder certHolder = v1CertGen.build(signer);
  
          ContentVerifierProvider verifier = new JcaContentVerifierProviderBuilder().setProvider(BC).build(issPub);
          return certHolder;
      }
  
  
      public X509Certificate test(KeyPair kp) throws OperatorCreationException, GeneralSecurityException, CertException, IOException, CMPException {
  
      Provider bcProvider = new BouncyCastleProvider();
      Security.addProvider(bcProvider);
      X509CertificateHolder cert = makeV3Certificate(kp, "CN=CA", kp, "CN=CA");
      GeneralName sender = new GeneralName(new X500Name("CN=CA"));
      GeneralName recipient = new GeneralName(new X500Name("CN=CA"));
  
      ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSAEncryption").setProvider(BC).build(kp.getPrivate());
      ProtectedPKIMessage message = new ProtectedPKIMessageBuilder(sender, recipient)
              .setBody(new PKIBody(PKIBody.TYPE_INIT_REP, CertRepMessage.getInstance(new DERSequence(new DERSequence()))))
              .addCMPCertificate(cert)
              .build(signer);
  
      X509Certificate jcaCert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(message.getCertificates()[0]);
      return jcaCert;
      }
  
  
  
  
      public void generateJKS() throws GeneralSecurityException, IOException, OperatorCreationException, CMPException, CertException {
          Provider bcProvider = new BouncyCastleProvider();
          Security.addProvider(bcProvider);
          KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
          keyPairGenerator.initialize(1024);
          KeyPair keyPair = keyPairGenerator.generateKeyPair();
          X509Certificate certificate = test(keyPair);
  
          final FileOutputStream os = new FileOutputStream("E:\\cert4.cer");
          os.write("-----BEGIN CERTIFICATE-----\n".getBytes("US-ASCII"));
          os.write(Base64.encodeBase64(certificate.getEncoded(), true));
          os.write("-----END CERTIFICATE-----\n".getBytes("US-ASCII"));
          os.close();
  
          KeyStore keyStore = KeyStore.getInstance("JKS");
          keyStore.load(null,null);
          X509Certificate[] certChain = new X509Certificate[1];
          certChain[0] = certificate;
          keyStore.setKeyEntry("myaliaskey", (Key)keyPair.getPrivate(), "secret".toCharArray(), certChain);
          OutputStream outputStream = new FileOutputStream("E:\\keystoreRSA4.jks");
          keyStore.store(outputStream, "secret".toCharArray());
          outputStream.flush();
          outputStream.close();
  
      }
  
  
  
      public static void main(String[] args) throws Exception {
  
          new generateService().generateJKS();
      } }
  </code></pre>
  
  <p>Application.properties:</p>
  
  <pre><code>server.port = 8443 server.http.port = 8080 server.ssl.key-store =  E:\\keystoreRSA4.jks server.ssl.key-password = secret server.ssl.keyAlias = myaliaskey
  </code></pre>
  
  <p>/***************************************************************************/ </p>
  
  <pre><code>import org.springframework.context.annotation.Configuration;
  
  import javax.annotation.PostConstruct;
  
  @Configuration public class SSLConfig {
  
  
      @PostConstruct
      private void configureSSL() {
          System.setProperty("https.protocols", "TLSv1.2");
          System.setProperty("javax.net.ssl.trustStore", "E:\\keystoreRSA4.jks");
          System.setProperty("javax.net.ssl.keyStore", "E:\\keystoreRSA4.jks");
          System.setProperty("javax.net.ssl.keyStorePassword", "secret");
  
      } }
  
  
  import org.apache.catalina.Context; import org.apache.catalina.connector.Connector; import org.apache.tomcat.util.descriptor.web.SecurityCollection; import org.apache.tomcat.util.descriptor.web.SecurityConstraint; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
  
  @Configuration public class TomcatConfig {
      @Value("${server.http.port}")
      private int httpPort;
  
      @Value("${server.port}")
      private int httpsPort;
  
      @Bean
      public EmbeddedServletContainerFactory servletContainer() {
          TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
              @Override
              protected void postProcessContext(Context context) {
                  SecurityConstraint securityConstraint = new SecurityConstraint();
                  securityConstraint.setUserConstraint("CONFIDENTIAL");
                  SecurityCollection collection = new SecurityCollection();
                  collection.addPattern("/*");
                  securityConstraint.addCollection(collection);
                  context.addConstraint(securityConstraint);
              }
          };
          tomcat.addAdditionalTomcatConnectors(initiateHttpConnector());
          return tomcat;
      }
  
      public Connector initiateHttpConnector() {
          Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
          connector.setScheme("https");
          connector.setPort(httpPort);
          connector.setSecure(true);
          connector.setRedirectPort(httpsPort); 
          return connector;
      } }
  </code></pre>
  
  <p>Any help will be appreciated and thank you in advance.</p>