Java client certificates over HTTPS/SSL

后端 未结 8 922
攒了一身酷
攒了一身酷 2020-11-22 13:46

I am using Java 6 and am trying to create an HttpsURLConnection against a remote server, using a client certificate.
The server is using an selfsigned root

相关标签:
8条回答
  • 2020-11-22 14:30

    For me, this is what worked using Apache HttpComponents ~ HttpClient 4.x:

        KeyStore keyStore  = KeyStore.getInstance("PKCS12");
        FileInputStream instream = new FileInputStream(new File("client-p12-keystore.p12"));
        try {
            keyStore.load(instream, "helloworld".toCharArray());
        } finally {
            instream.close();
        }
    
        // Trust own CA and all self-signed certs
        SSLContext sslcontext = SSLContexts.custom()
            .loadKeyMaterial(keyStore, "helloworld".toCharArray())
            //.loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()) //custom trust store
            .build();
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            sslcontext,
            new String[] { "TLSv1" },
            null,
            SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); //TODO
        CloseableHttpClient httpclient = HttpClients.custom()
            .setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER) //TODO
            .setSSLSocketFactory(sslsf)
            .build();
        try {
    
            HttpGet httpget = new HttpGet("https://localhost:8443/secure/index");
    
            System.out.println("executing request" + httpget.getRequestLine());
    
            CloseableHttpResponse response = httpclient.execute(httpget);
            try {
                HttpEntity entity = response.getEntity();
    
                System.out.println("----------------------------------------");
                System.out.println(response.getStatusLine());
                if (entity != null) {
                    System.out.println("Response content length: " + entity.getContentLength());
                }
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    

    The P12 file contains the client certificate and client private key, created with BouncyCastle:

    public static byte[] convertPEMToPKCS12(final String keyFile, final String cerFile,
        final String password)
        throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException,
        NoSuchProviderException
    {
        // Get the private key
        FileReader reader = new FileReader(keyFile);
    
        PEMParser pem = new PEMParser(reader);
        PEMKeyPair pemKeyPair = ((PEMKeyPair)pem.readObject());
        JcaPEMKeyConverter jcaPEMKeyConverter = new JcaPEMKeyConverter().setProvider("BC");
        KeyPair keyPair = jcaPEMKeyConverter.getKeyPair(pemKeyPair);
    
        PrivateKey key = keyPair.getPrivate();
    
        pem.close();
        reader.close();
    
        // Get the certificate
        reader = new FileReader(cerFile);
        pem = new PEMParser(reader);
    
        X509CertificateHolder certHolder = (X509CertificateHolder) pem.readObject();
        java.security.cert.Certificate x509Certificate =
            new JcaX509CertificateConverter().setProvider("BC")
                .getCertificate(certHolder);
    
        pem.close();
        reader.close();
    
        // Put them into a PKCS12 keystore and write it to a byte[]
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        KeyStore ks = KeyStore.getInstance("PKCS12", "BC");
        ks.load(null);
        ks.setKeyEntry("key-alias", (Key) key, password.toCharArray(),
            new java.security.cert.Certificate[]{x509Certificate});
        ks.store(bos, password.toCharArray());
        bos.close();
        return bos.toByteArray();
    }
    
    0 讨论(0)
  • 2020-11-22 14:32

    I think you have an issue with your server certificate, is not a valid certificate (I think this is what "handshake_failure" means in this case):

    Import your server certificate into your trustcacerts keystore on client's JRE. This is easily done with keytool:

    keytool
        -import
        -alias <provide_an_alias>
        -file <certificate_file>
        -keystore <your_path_to_jre>/lib/security/cacerts
    
    0 讨论(0)
提交回复
热议问题