我正在尝试使用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方法中创建验证方法。有人建议用我的信任库实现这个服务器验证的方法吗?目前,我有一个方法,但它太大而复杂