在android中使用未知CA签名证书(如pkcs12)有什么好例子吗
我正在开发android应用程序,它需要通过ssl与服务器通信。确实,使用HttpsUrlConnection在android中使用pkcs12证书是一个很好的例子,尽管有点混乱在android中使用未知CA签名证书(如pkcs12)有什么好例子吗,android,ssl,openssl,ssl-certificate,android-networking,Android,Ssl,Openssl,Ssl Certificate,Android Networking,我正在开发android应用程序,它需要通过ssl与服务器通信。确实,使用HttpsUrlConnection在android中使用pkcs12证书是一个很好的例子,尽管有点混乱 SSLContext sslContext = SSLContext.getInstance("TLS"); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFac
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore)null); //this is where you would add the truststore
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
KeyStore keyStore = KeyStore.getInstance("PKCS12", BouncyCastleProvider.PROVIDER_NAME); //spongyCastle library
keyStore.load(keyStoreStream, keyStorePassword); //inputStream to PKCS12
keyManagerFactory.init(keyStore, keyStorePassword);
//TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
TrustManager[] trustAllCertManagers = { new X509TrustManager() { // this is vulnerable to MITM attack
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}};
sslContext.init(keyManagerFactory.getKeyManagers(), trustAllCertManagers, new SecureRandom());
URL url = new URL(urlString);
HttpsURLConnection httpsUrlConnection = (HttpsURLConnection) url.openConnection();
httpsUrlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
您需要以下依赖项:
compile 'com.madgag.spongycastle:core:1.51.0.0'
compile 'com.madgag.spongycastle:prov:1.51.0.0'
compile 'com.madgag.spongycastle:pkix:1.51.0.0'
这需要一点修正,尽管它初始化密钥存储(将客户端证书存储在PKCS12中),但它信任每个证书,而不是使用密钥库来确定它是否是受信任的证书(这容易受到中间人
攻击)
编辑:为了使SpongyCastle工作,您需要添加如下自定义应用程序:
import org.spongycastle.jce.provider.BouncyCastleProvider;
public class CustomApplication
extends Application {
static {
Security.insertProviderAt(new BouncyCastleProvider(), 1);
}
@Override
public void onCreate() {
super.onCreate();
}
}
在AndroidManifest.xml中:
<application
android:allowBackup="true"
android:name=".CustomApplication"
在对@EpicPandaForce发布的代码进行了一些修改之后,我成功地运行了代码
变化:
1. KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509");
到
要清除异常:java.security.NoSuchAlgorithmException:X509 KeyManagerFactory不可用
2. KeyStore keyStore = KeyStore.getInstance("PKCS12", BouncyCastleProvider.PROVIDER_NAME); //spongyCastle library
到
并将提供程序添加到安全类,如下所示
Security.addProvider(new BouncyCastleProvider());
要摆脱异常:java.security.NoSuchProviderException:没有这样的提供程序:SC
然后是最终完整代码:
Security.addProvider(new BouncyCastleProvider());
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore)null); //this is where you would add the truststore
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
KeyStore keyStore = KeyStore.getInstance("PKCS12"); //spongyCastle library
keyStore.load(new FileInputStream("D:\\Documents\\VISA Direct Api\\cabcentralcert.p12"), "cabcentral".toCharArray()); //inputStream to PKCS12
keyManagerFactory.init(keyStore, "cabcentral".toCharArray());
//TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
TrustManager[] trustAllCertManagers = { new X509TrustManager() { // this is vulnerable to MITM attack
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}};
sslContext.init(keyManagerFactory.getKeyManagers(), trustAllCertManagers, new SecureRandom());
URL url = new URL(strUrl);
HttpsURLConnection httpsUrlConnection = (HttpsURLConnection) url.openConnection();
httpsUrlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
System.out.println("Response Code : " + httpsUrlConnection.getResponseCode());
System.out.println("Cipher Suite : " + httpsUrlConnection.getCipherSuite());
感谢@EpicPandaForce的重播运行上述代码后,我得到以下异常:java.security.nosuchalgorithException:X509 KeyManagerFactory不可用将trust manager算法更改为SunX509后,我得到了以下异常:java.security.NoSuchProviderException:没有这样的提供程序:请稍等片刻。不要更改信任管理器算法,但您可能需要将密钥管理器算法更改为SunX509
。但是对于PKCS12
,确实需要BouncyCastle。
Security.addProvider(new BouncyCastleProvider());
Security.addProvider(new BouncyCastleProvider());
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore)null); //this is where you would add the truststore
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
KeyStore keyStore = KeyStore.getInstance("PKCS12"); //spongyCastle library
keyStore.load(new FileInputStream("D:\\Documents\\VISA Direct Api\\cabcentralcert.p12"), "cabcentral".toCharArray()); //inputStream to PKCS12
keyManagerFactory.init(keyStore, "cabcentral".toCharArray());
//TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
TrustManager[] trustAllCertManagers = { new X509TrustManager() { // this is vulnerable to MITM attack
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}};
sslContext.init(keyManagerFactory.getKeyManagers(), trustAllCertManagers, new SecureRandom());
URL url = new URL(strUrl);
HttpsURLConnection httpsUrlConnection = (HttpsURLConnection) url.openConnection();
httpsUrlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
System.out.println("Response Code : " + httpsUrlConnection.getResponseCode());
System.out.println("Cipher Suite : " + httpsUrlConnection.getCipherSuite());