Java 使用SSL和Bouncy Castle的Android到服务器通信
我知道这并不困难,但非常不幸的是,我被困在这里,从昨天开始就一直在与之抗争。我遵循本教程,在资源中放置密钥库,并尝试通过SSL连接到我的服务器,但遇到以下异常 java.lang.RuntimeException: org.spongycastle.jcajce.provider.asymetric.x509.CertificateFactory$ExCertificateException 我已将我的sslapptruststore.pfx文件放在res/raw/sslapptruststore.pfx下 使用这段代码Java 使用SSL和Bouncy Castle的Android到服务器通信,java,android,ssl,bouncycastle,spongycastle,Java,Android,Ssl,Bouncycastle,Spongycastle,我知道这并不困难,但非常不幸的是,我被困在这里,从昨天开始就一直在与之抗争。我遵循本教程,在资源中放置密钥库,并尝试通过SSL连接到我的服务器,但遇到以下异常 java.lang.RuntimeException: org.spongycastle.jcajce.provider.asymetric.x509.CertificateFactory$ExCertificateException 我已将我的sslapptruststore.pfx文件放在res/raw/sslapptruststor
try {
KeyStore clientCert = KeyStore.getInstance("PKCS12");
clientCert.load(getResources().openRawResource(R.raw.sslapptruststore), "123456".toCharArray());// this line causes exception
HttpClient httpClient = null;
HttpParams httpParams = new BasicHttpParams();
SSLSocketFactory sslSocketFactory = new SSLSocketFactory(clientCert, null, null);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("https", sslSocketFactory, 8443));
httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager(httpParams, registry), httpParams);
HttpPost httpPost = new HttpPost(
"https://192.168.1.113:8443/CertProvider");
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
List<NameValuePair> nameValuePair = new ArrayList<NameValuePair>(2);
nameValuePair.add(new BasicNameValuePair("csr", csr.toString()));
// Url Encoding the POST parameters
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePair));
// Making HTTP Request
// HttpResponse response = null;
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String response = "";
response = httpClient.execute(httpPost, responseHandler);
} catch (Exception e) {
Log.e("", e.getMessage());
}
我也搜索过,但其他人正在使用.bks
非常感谢您的帮助。我已经回答了一些与您的问题类似的问题,如下所示: 你会发现
private SSLSocketFactory getSSLSocketFactory_KeyStore(String keyStoreType, int keystoreResId, String keyPassword)
throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException {
InputStream caInput = getResources().openRawResource(keystoreResId);
// creating a KeyStore containing trusted CAs
if (keyStoreType == null || keyStoreType.length() == 0) {
keyStoreType = KeyStore.getDefaultType();
}
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(caInput, keyPassword.toCharArray());
// creating a TrustManager that trusts the CAs in the KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(tmf.getTrustManagers());
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, wrappedTrustManagers, null);
return sslContext.getSocketFactory();
}
和.cert文件的getSSLSocketFactory_证书
与上面的第一个链接一样,在项目中可以调用以下两种方法之一:
如果使用密钥库文件:
SSLSocketFactory sslSocketFactory = getSSLSocketFactory_KeyStore("PKCS12", R.raw.androidpkcs12, "123456789");
如果使用证书文件:
SSLSocketFactory sslSocketFactory = getSSLSocketFactory_Certificate("PKCS12", R.raw.androidpkcs12_cert);
p/S:如果这些方法在非活动类中,为了避免NPE,您必须在上面的第一个链接中将上下文从活动传递到该类
希望这有帮助 我添加了以下类来解决这个问题
import org.apache.http.conn.ssl.SSLSocketFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
/**
* Allows you to trust certificates from additional KeyStores in addition to
* the default KeyStore
*/
public class AdditionalKeyStoresSSLSocketFactory extends SSLSocketFactory{
protected SSLContext sslContext = SSLContext.getInstance("TLSv1");
public AdditionalKeyStoresSSLSocketFactory(KeyStore keyStore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(null, null, null, null, null, null);
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());;
keyManagerFactory.init(keyStore, "123456".toCharArray());
sslContext.init(keyManagerFactory.getKeyManagers(), new TrustManager[]{new AdditionalKeyStoresTrustManager(keyStore)}, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
/**
* Based on http://download.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#X509TrustManager
*/
public static class AdditionalKeyStoresTrustManager implements X509TrustManager {
protected ArrayList<X509TrustManager> x509TrustManagers = new ArrayList<X509TrustManager>();
protected AdditionalKeyStoresTrustManager(KeyStore... additionalkeyStores) {
final ArrayList<TrustManagerFactory> factories = new ArrayList<TrustManagerFactory>();
try {
// The default Trustmanager with default keystore
final TrustManagerFactory original = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
original.init((KeyStore) null);
factories.add(original);
for( KeyStore keyStore : additionalkeyStores ) {
final TrustManagerFactory additionalCerts = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
additionalCerts.init(keyStore);
factories.add(additionalCerts);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
/*
* Iterate over the returned trustmanagers, and hold on
* to any that are X509TrustManagers
*/
for (TrustManagerFactory tmf : factories)
for( TrustManager tm : tmf.getTrustManagers() )
if (tm instanceof X509TrustManager)
x509TrustManagers.add( (X509TrustManager)tm );
if( x509TrustManagers.size()==0 )
throw new RuntimeException("Couldn't find any X509TrustManagers");
}
/*
* Delegate to the default trust manager.
*/
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
final X509TrustManager defaultX509TrustManager = x509TrustManagers.get(0);
defaultX509TrustManager.checkClientTrusted(chain, authType);
}
/*
* Loop over the trustmanagers until we find one that accepts our server
*/
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
for( X509TrustManager tm : x509TrustManagers ) {
try {
tm.checkServerTrusted(chain,authType);
return;
} catch( CertificateException e ) {
// ignore
}
}
throw new CertificateException();
}
public X509Certificate[] getAcceptedIssuers() {
final ArrayList<X509Certificate> list = new ArrayList<X509Certificate>();
for( X509TrustManager tm : x509TrustManagers )
list.addAll(Arrays.asList(tm.getAcceptedIssuers()));
return list.toArray(new X509Certificate[list.size()]);
}
}
}
如果不工作,请告诉我。然后,如果可能的话,请向我提供您的.pfx文件,以便我可以签入我的项目:以前我只在密钥库中放入签名证书,但我尝试使用具有完整链的密钥库,它可以工作,并且至少能够加载密钥库,但现在出现了此异常>您的密钥库/证书文件是如何创建的?我使用密钥库资源管理器来创建文件。我通过对代码进行一些修改来解决这个问题,我已经更新了您已经解决的问题,感谢您的分享:我也有同样的问题。我的代码在CertificateFactory cf=CertificateFactory.getInstanceX.509,BC行中给出了错误。如何使用此类来避免错误?Thanks@Hilal共享您的错误跟踪,大致上我可以建议您检查您的提供程序列表,可能是BC提供程序不在列表中我无法粘贴整个错误,因为stackoverflow不允许:我如何检查提供程序列表?这是错误;com.android.org.bouncycastle.jcajce.provider.asymetric.x509.CertificateFactory$ExCertificateException 09-20 12:48:02.042 20236-20350/com.example.hillinan.cert W/System.err:在com.android.org.bouncycastle.jcajcajce.provider.asymetric.x509.CertificateFactory.EngineeGenerateCertificateCertificateFactory.java:220 09-20 12:48:02.04220236-20350/com.example.hillinan.cert W/System.err:我发现了如何检查提供者列表,但在列表中看不到BC。但我尝试了其他方法,而不是BC,但没有发现这样的ProviderException。例如:ACCVRAIZ1我想我应该编写它们的代码版本,但不知道在哪里可以找到?有公共名称、组织、组织单位、序列号等字段。他们没有一个人为他工作me@Hilal实际上android只与BC一起工作,所以我sun认为它需要改变提供商,相反,你必须将BC添加到列表中,如果我还没有发送代码,你可以用谷歌搜索如何将BC添加到列表中