带 spring 靴子的充气城堡

Bouncy castle with spring boot

我正在尝试通过 http 使用 Https,我使用 bouncy castle 生成了 CA 证书,并从 .cer 文件生成了 jks 文件,spring 引导成功启动随嵌入式 tomcat.

提供的属性

问题是当我添加使用另一个配置 class.

以编程方式信任存储

这是我的代码:

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();
    } }

Application.properties:

server.port = 8443 server.http.port = 8080 server.ssl.key-store =  E:\keystoreRSA4.jks server.ssl.key-password = secret server.ssl.keyAlias = myaliaskey

/******************************************** *******************************/

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;
    } }

如有任何帮助,我们将不胜感激,并提前致谢。

how i can figure it to let the browser accept it as trust certificate?

幸运的是,你不能。有关于话题的讨论 in this question:

If we simply said "HTTPS is now possible with self-signed certificates", your browser could not distinguish whether a site you are trying to visit has a self-signed cert because it is supposed to, or because you are being attacked. Thus, it would decrease security.

您必须在浏览器中添加例外才能接受您的证书。通常在开发期间。对于生产用途,您必须从 Verisign.

等受信任的供应商处购买证书

要向您的浏览器添加例外,请参阅this other question

干杯!