如何使用java获取安全网页的公钥

Par*_*asu 2 java ssl-certificate

我需要通过java以编程方式获取安全网站的公钥.我看了这个,这个,这个这个和其他的方面.但我还没有找到通过java获得它的解决方案.

编辑:::

根据Zielu的回答,我写了以下程序:

import java.security.PublicKey;
import java.security.cert.Certificate;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

public class RetrievePublicKey {

    private static PublicKey getKey(String hostname, int port) throws Exception {
        SSLSocketFactory factory = HttpsURLConnection.getDefaultSSLSocketFactory();        
        SSLSocket socket = (SSLSocket) factory.createSocket(hostname, port);
        socket.startHandshake();
        Certificate[] certs = socket.getSession().getPeerCertificates();
        Certificate cert = certs[0];
        PublicKey key = cert.getPublicKey();
        System.out.println(key);
        return key;
    }
    public static void main(String[] args) throws Exception {
        System.out.println(getKey("bctcl-parasuram.bctchn.local", 8443));
    }

}
Run Code Online (Sandbox Code Playgroud)

但是当我运行它时,我得到以下异常:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1937)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1478)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:212)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:957)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:892)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1050)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375)
    at RetrievePublicKey.getKey(RetrievePublicKey.java:22)
    at RetrievePublicKey.main(RetrievePublicKey.java:30)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
    at sun.security.validator.Validator.validate(Validator.java:260)
    at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1460)
    ... 9 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:145)
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
    ... 15 more
Run Code Online (Sandbox Code Playgroud)

Zie*_*elu 7

您可以使用SSLSocket获取证书及其公钥:

import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.security.cert.Certificate;
...

    String hostname = "your.host";
    SSLSocketFactory factory = HttpsURLConnection.getDefaultSSLSocketFactory();        
    SSLSocket socket = (SSLSocket) factory.createSocket(hostname, 443);
    socket.startHandshake();
    Certificate[] certs = socket.getSession().getPeerCertificates();
    Certificate cert = certs[0];
    PublicKey key = cert.getPublicKey();
Run Code Online (Sandbox Code Playgroud)

仅当证书有效(不是自签名或由未知权限签名)时,它才有效.对于自签名证书,您可以定义自己的TrustManager,它将信任所有内容.请参阅允许Java使用不受信任的证书进行SSL/HTTPS连接

但是如果可以的话,应该避免这种情况,因为留下的这种代码会在以后产生安全问题.