如何以编程方式将证书添加到信任库并将其用于validation服务器身份validation

我的应用程序我想使用https连接到使用自签名证书的用户指定的服务器。 我现在收集的是这个

  • 自签名证书被拒绝(按预期)
  • Android密钥库/信任库不用于应用程序,所以应用程序必须构build并使用自己的信任库,
  • 在JDK中有一个“keytool”来构build一个可以作为资源提供给应用程序的信任库,然而这不是一个解决scheme,因为我不知道服务器(和它的证书事先)

由于https服务器是用户指定的,因此我事先不知道服务器的证书,因此希望以编程方式将服务器证书添加到应用的信任库(通过向用户显示证书并让他接受证书)。 一旦添加到信任库,应用程序将使用该信任库来authentication服务器。

我不想简单地接受每个自签名的证书,而不需要用户检查指纹,就像网上的一些例子所示。

现在的问题是我对Java和Android完全陌生,并且很难理解AndroidHttpClient或DefaultHttpClient的内部工作原理。 我有基本的HTTP在我的应用程序工作,但还没有find任何关于如何实际添加证书到应用程序内的信任库的用户需求的任何示例。

有人知道如何做到这一点,或知道我可以看看一个可行的例子吗?

任何提示都表示赞赏。 谢谢。

编辑:findK9邮件的TrustManagerFactory.java类中的解决scheme。 如果你有同样的问题,我build议你看看。

Solutions Collecting From Web of "如何以编程方式将证书添加到信任库并将其用于validation服务器身份validation"

解决scheme刚刚被发现,但没有人创build了答案,但还没有帮助指导其他人,所以今天上午我将成为Point Pimp(ette),并发布作为解决scheme添加的URL,再加上来自公共源代码的副本。 希望这有助于引导他人解决scheme。 🙂


以下是以下代码的url 。

package com.fsck.k9.mail.store; import android.app.Application; import android.content.Context; import android.util.Log; import com.fsck.k9.K9; import com.fsck.k9.helper.DomainNameChecker; import org.apache.commons.io.IOUtils; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.HashMap; import java.util.Map; public final class TrustManagerFactory { private static final String LOG_TAG = "TrustManagerFactory"; private static X509TrustManager defaultTrustManager; private static X509TrustManager unsecureTrustManager; private static X509TrustManager localTrustManager; private static X509Certificate[] lastCertChain = null; private static File keyStoreFile; private static KeyStore keyStore; private static class SimpleX509TrustManager implements X509TrustManager { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } } private static class SecureX509TrustManager implements X509TrustManager { private static final Map<String, SecureX509TrustManager> mTrustManager = new HashMap<String, SecureX509TrustManager>(); private final String mHost; private SecureX509TrustManager(String host) { mHost = host; } public synchronized static X509TrustManager getInstance(String host) { SecureX509TrustManager trustManager; if (mTrustManager.containsKey(host)) { trustManager = mTrustManager.get(host); } else { trustManager = new SecureX509TrustManager(host); mTrustManager.put(host, trustManager); } return trustManager; } public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { defaultTrustManager.checkClientTrusted(chain, authType); } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { // FIXME: Using a static field to store the certificate chain is a bad idea. Instead // create a CertificateException subclass and store the chain there. TrustManagerFactory.setLastCertChain(chain); try { defaultTrustManager.checkServerTrusted(chain, authType); } catch (CertificateException e) { localTrustManager.checkServerTrusted(new X509Certificate[] {chain[0]}, authType); } if (!DomainNameChecker.match(chain[0], mHost)) { try { String dn = chain[0].getSubjectDN().toString(); if ((dn != null) && (dn.equalsIgnoreCase(keyStore.getCertificateAlias(chain[0])))) { return; } } catch (KeyStoreException e) { throw new CertificateException("Certificate cannot be verified; KeyStore Exception: " + e); } throw new CertificateException("Certificate domain name does not match " + mHost); } } public X509Certificate[] getAcceptedIssuers() { return defaultTrustManager.getAcceptedIssuers(); } } static { java.io.InputStream fis = null; try { javax.net.ssl.TrustManagerFactory tmf = javax.net.ssl.TrustManagerFactory.getInstance("X509"); Application app = K9.app; keyStoreFile = new File(app.getDir("KeyStore", Context.MODE_PRIVATE) + File.separator + "KeyStore.bks"); keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); try { fis = new java.io.FileInputStream(keyStoreFile); } catch (FileNotFoundException e1) { fis = null; } try { keyStore.load(fis, "".toCharArray()); } catch (IOException e) { Log.e(LOG_TAG, "KeyStore IOException while initializing TrustManagerFactory ", e); keyStore = null; } catch (CertificateException e) { Log.e(LOG_TAG, "KeyStore CertificateException while initializing TrustManagerFactory ", e); keyStore = null; } tmf.init(keyStore); TrustManager[] tms = tmf.getTrustManagers(); if (tms != null) { for (TrustManager tm : tms) { if (tm instanceof X509TrustManager) { localTrustManager = (X509TrustManager)tm; break; } } } tmf = javax.net.ssl.TrustManagerFactory.getInstance("X509"); tmf.init((KeyStore)null); tms = tmf.getTrustManagers(); if (tms != null) { for (TrustManager tm : tms) { if (tm instanceof X509TrustManager) { defaultTrustManager = (X509TrustManager) tm; break; } } } } catch (NoSuchAlgorithmException e) { Log.e(LOG_TAG, "Unable to get X509 Trust Manager ", e); } catch (KeyStoreException e) { Log.e(LOG_TAG, "Key Store exception while initializing TrustManagerFactory ", e); } finally { IOUtils.closeQuietly(fis); } unsecureTrustManager = new SimpleX509TrustManager(); } private TrustManagerFactory() { } public static X509TrustManager get(String host, boolean secure) { return secure ? SecureX509TrustManager.getInstance(host) : unsecureTrustManager; } public static KeyStore getKeyStore() { return keyStore; } public static void setLastCertChain(X509Certificate[] chain) { lastCertChain = chain; } public static X509Certificate[] getLastCertChain() { return lastCertChain; } public static void addCertificateChain(String alias, X509Certificate[] chain) throws CertificateException { try { javax.net.ssl.TrustManagerFactory tmf = javax.net.ssl.TrustManagerFactory.getInstance("X509"); for (X509Certificate element : chain) { keyStore.setCertificateEntry (element.getSubjectDN().toString(), element); } tmf.init(keyStore); TrustManager[] tms = tmf.getTrustManagers(); if (tms != null) { for (TrustManager tm : tms) { if (tm instanceof X509TrustManager) { localTrustManager = (X509TrustManager) tm; break; } } } java.io.OutputStream keyStoreStream = null; try { keyStoreStream = new java.io.FileOutputStream(keyStoreFile); keyStore.store(keyStoreStream, "".toCharArray()); } catch (FileNotFoundException e) { throw new CertificateException("Unable to write KeyStore: " + e.getMessage()); } catch (CertificateException e) { throw new CertificateException("Unable to write KeyStore: " + e.getMessage()); } catch (IOException e) { throw new CertificateException("Unable to write KeyStore: " + e.getMessage()); } finally { IOUtils.closeQuietly(keyStoreStream); } } catch (NoSuchAlgorithmException e) { Log.e(LOG_TAG, "Unable to get X509 Trust Manager ", e); } catch (KeyStoreException e) { Log.e(LOG_TAG, "Key Store exception while initializing TrustManagerFactory ", e); } } } 

您可以使用自签名证书。 要使用自签名证书,您可以将其转换为Android支持的bouncy castle格式密钥存储区,然后将其作为原始资源存储在您的Android应用程序项目中。 如何转换和使用它,所有的细节都可以在Bob的博客上find。 这里是相同的链接 – http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html 。 这工作得很好。 希望这可以帮助