Bouncy Castle简单的TLS客户端

时间:2017-11-07 08:22:59

标签: java ssl https httpclient bouncycastle

我正在尝试使用bouncy castle TLS API创建一个HTTP客户端。这是我的代码:

    TrustManagerFactory trustMgrFact = TrustManagerFactory.getInstance("PKIX",
            BouncyCastleJsseProvider.PROVIDER_NAME);

    KeyManagerFactory keyMgrFact = KeyManagerFactory.getInstance("PKIX",
            BouncyCastleJsseProvider.PROVIDER_NAME);

    KeyStore ks = KeyStore.getInstance("JKS");
    ks.load(new FileInputStream("keystore.jks"), "123456".toCharArray());

    keyMgrFact.init(ks, "123456".toCharArray());

    trustMgrFact.init(ks);
    final X509TrustManager tm = findX509TrustManager(trustMgrFact.getTrustManagers());

    final Certificate[] chain = new Certificate[1];

    final TlsCrypto crypto = new JcaTlsCryptoProvider().create(new SecureRandom());

    InetAddress address = InetAddress.getByName("localhost.com");
    int port = 9444;
    Socket s = new Socket(address, port);
    TlsClient client = new DefaultTlsClient(crypto) {
        public TlsAuthentication getAuthentication() throws IOException {
            return new TlsAuthentication() {
                public void notifyServerCertificate(TlsServerCertificate tlsServerCertificate) throws IOException {
                    boolean noServerCert = tlsServerCertificate == null || tlsServerCertificate.getCertificate() ==
                            null
                            || tlsServerCertificate.getCertificate().isEmpty();
                    if (noServerCert) {
                        throw new TlsFatalAlert(AlertDescription.handshake_failure);
                    } else {
                        X509Certificate[] chain = getX509CertificateChain(crypto,
                                tlsServerCertificate.getCertificate());
                        String authType = getAuthTypeServer(TlsUtils.getKeyExchangeAlgorithm(selectedCipherSuite));
                        if (!isServerTrusted(tm, chain, authType)) {
                            throw new TlsFatalAlert(AlertDescription.bad_certificate);
                        }

                    }
                }

                public TlsCredentials getClientCredentials(CertificateRequest certificateRequest) throws IOException {
                    return null;
                }

            };      TlsClientProtocol protocol = new TlsClientProtocol( s.getInputStream(), s.getOutputStream());
  protocol.connect(client);
  protocol.close();
}
private static X509TrustManager findX509TrustManager(TrustManager[] tms)
{
    if (tms != null)
    {
        for (TrustManager tm : tms)
        {
            if (tm instanceof X509TrustManager)
            {
                return (X509TrustManager)tm;
            }
        }
    }
    return null;
}

public static X509Certificate[] getX509CertificateChain (TlsCrypto crypto, Certificate certificateMessage)
{
    if (certificateMessage == null || certificateMessage.isEmpty()) {
        return new X509Certificate[0];
    }

    try {
        X509Certificate[] chain = new X509Certificate[certificateMessage.getLength()];
        for (int i = 0; i < chain.length; ++i) {
            chain[i] = JcaTlsCertificate.convert((JcaTlsCrypto) crypto, certificateMessage.getCertificateAt(i)).getX509Certificate();
        }
        return chain;
    } catch (IOException e) {
        // TODO[jsse] Logging
        throw new RuntimeException(e);
    }

}

public static String getAuthTypeServer(int keyExchangeAlgorithm) throws IOException
{
    switch (keyExchangeAlgorithm)
    {
        case KeyExchangeAlgorithm.DH_anon:
            return "DH_anon";
        case KeyExchangeAlgorithm.DH_DSS:
            return "DH_DSS";
        case KeyExchangeAlgorithm.DH_RSA:
            return "DH_RSA";
        case KeyExchangeAlgorithm.DHE_DSS:
            return "DHE_DSS";
        case KeyExchangeAlgorithm.DHE_PSK:
            return "DHE_PSK";
        case KeyExchangeAlgorithm.DHE_RSA:
            return "DHE_RSA";
        case KeyExchangeAlgorithm.ECDH_anon:
            return "ECDH_anon";
        case KeyExchangeAlgorithm.ECDH_ECDSA:
            return "ECDH_ECDSA";
        case KeyExchangeAlgorithm.ECDH_RSA:
            return "ECDH_RSA";
        case KeyExchangeAlgorithm.ECDHE_ECDSA:
            return "ECDHE_ECDSA";
        case KeyExchangeAlgorithm.ECDHE_PSK:
            return "ECDHE_PSK";
        case KeyExchangeAlgorithm.ECDHE_RSA:
            return "ECDHE_RSA";
        case KeyExchangeAlgorithm.RSA:
            return "RSA";
        case KeyExchangeAlgorithm.RSA_PSK:
            return "RSA_PSK";
        case KeyExchangeAlgorithm.SRP:
            return "SRP";
        case KeyExchangeAlgorithm.SRP_DSS:
            return "SRP_DSS";
        case KeyExchangeAlgorithm.SRP_RSA:
            return "SRP_RSA";
        default:
            throw new TlsFatalAlert(AlertDescription.internal_error);
    }
}

public static boolean isServerTrusted(X509TrustManager tm,X509Certificate[] chain, String authType)
{
    if (tm != null)
    {
        try
        {
            tm.checkServerTrusted(chain, authType);
            return true;
        }
        catch (CertificateException e)
        {
        }
    }
    return false;
}

但是我坚持在notifyServerCertificate方法中创建验证方法。有人建议用我的信任库实现这个服务器验证的方法吗?目前,我有一个方法,但它太大而复杂

0 个答案:

没有答案