使用给定的p12证书连接到https站点

服务器端给了我一个.p12证书文件,我点击并安装在我的机器上然后我可以通过浏览器访问HTTPS站点。 现在他们希望我用给出的证书抓取他们的网站。 我陷入了它的第一阶段,试图从httpsURLConnection获取inputStream 。 该网站没有登录。 它只会检查您是否拥有证书。

到目前为止我所做的是使用Firefox以.crt文件格式导出证书。 然后我使用keytool命令将它( .crt文件,而不是.p12 )导入java密钥库。 然后在代码中:

 KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); File ksFile = new File(keystorePath); in = new FileInputStream(ksFile); ks.load(in, "changeit".toCharArray()); X509Certificate cert = (X509Certificate) ks.getCertificate(certificateAlias); SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HttpsURLConnection con = (HttpsURLConnection) (new URL(urlString)).openConnection(); con.connect(); con.getInputStream(); con.disconnect(); 

getInputStream()将给出403错误禁止访问。 我搜索了其他相关主题,实际上比阅读之前更加困惑。 非常感谢答案。

额外细节:

  • 我只是实例化了证书,并且没有让程序知道任何类型的密钥(私有,公共等)。 所以我认为我必须将这些密钥提供给服务器,让它知道我实际上持有证书。 我完全不知道如何做到这一点,无论是逻辑还是语法。
  • 我已经尝试了keytool命令将.p12证书文件导入密钥库但不知何故,keytool无法识别-pkcs12选项。 关于如何直接使用这个.p12证书的任何想法都会很棒。
  • trustAllCert是TrustMangers的一个元素数组,它不validation任何东西(信任所有)。 我不知道我是否应该继续使用它。 事实上,现在我实际上只有一个证书可以信任。 在这种情况下编写trustManger的正确方法是什么?
  • 我无法控制服务器端。 我所获得的只是访问其网站的URL,该网站使用HTTPS协议,以及.p12证书。 该网站没有登录。 如果安装了证书,我可以进去。

如果要尝试对SSL配置进行编码,可以使用提供给您的P12文件,而无需将其转换为JKS。 此外,您需要使用P12中的私钥,而不仅仅是您复制到JKS中的证书。 不确定这是否能直接满足您的需求,但这可能会让您走上正确的道路:

  KeyStore clientStore = KeyStore.getInstance("PKCS12"); clientStore.load(new FileInputStream("test.p12"), "testPass".toCharArray()); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(clientStore, "testPass".toCharArray()); KeyManager[] kms = kmf.getKeyManagers(); KeyStore trustStore = KeyStore.getInstance("JKS"); trustStore.load(new FileInputStream("cacerts"), "changeit".toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(trustStore); TrustManager[] tms = tmf.getTrustManagers(); SSLContext sslContext = null; sslContext = SSLContext.getInstance("TLS"); sslContext.init(kms, tms, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); URL url = new URL("https://www.testurl.com"); HttpsURLConnection urlConn = (HttpsURLConnection) url.openConnection(); 

以这种方式配置trustStore是可选的。 您可以使用P12链中的所有证书创建一个JKS,或者只是确保它们在您的JRE的cacerts文件中。 至于keytool,作为参考,您可以在P12上运行keytool命令(指定-storetype pkcs12),但不能将P12导入JKS。 您也无法使用keytool命令从P12导出密钥。

我目前没有设置服务器来测试这段代码,所以试一试,看看你是否仍然收到403错误。

添加此作为答案,因为我需要更多的空间来编写。

首先,一个问题:证书是否由Verisign等受信任的机构签署? 如果不是,则信任库应该具有CA证书(通常是.pem文件),这使得p12证书“有效”。 默认的Java信任库包含来自大公司的大多数(如果不是全部)CA证书,例如Verisign和Thawte。

此外,您可以测试您的应用程序以连接到安全服务器而无需编写SSL配置,但使用一些命令行参数,例如:

 java -Djavax.net.ssl.keyStore=[path_to_p12_cert] \ -Djavax.net.ssl.keyStorePassword=[p12_password] \ -Djavax.net.ssl.keyStoreType=PKCS12 \ -Djavax.net.ssl.trustStore=[path_to_trust_store_with_CA_certificates] \ -Djavax.net.ssl.trustStorePassword=[trust_store_password] \ [MainClass] 

然后你的代码变得公正

 HttpsURLConnection con = (HttpsURLConnection) (new URL(urlString)).openConnection(); con.connect(); con.getInputStream(); con.disconnect(); 

如果您感到自虐, JSSE参考指南非常有趣。

这对我有用:

  KeyStore keyStore = KeyStore.getInstance("PKCS12"); FileInputStream instream = new FileInputStream(new File("client-p12-keystore.p12")); try { keyStore.load(instream, "password".toCharArray()); } finally { instream.close(); } // Trust own CA and all self-signed certs SSLContext sslcontext = SSLContexts.custom() .loadKeyMaterial(keyStore, "password".toCharArray()) //.loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()) .build(); // Allow TLSv1 protocol only SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslcontext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); CloseableHttpClient httpclient = HttpClients.custom() .setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER) .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(); } } 

简单的keytool命令会将.p12密钥库导出到.jks密钥库:

keytool -importkeystore -srckeystore keystore.p12 -srcstoretype PKCS12 -deststoretype JKS -destkeystore keystore.jks