Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/217.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何以编程方式将证书添加到信任库,并将其用于验证服务器身份验证_Android_Ssl_Ssl Certificate - Fatal编程技术网

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

Android 如何以编程方式将证书添加到信任库,并将其用于验证服务器身份验证,android,ssl,ssl-certificate,Android,Ssl,Ssl Certificate,我想使用https连接到使用自签名证书的用户指定服务器。我现在收集到的是 自签名证书被拒绝(如预期) android密钥库/信任库不用于应用程序,因此应用程序必须构建并使用自己的信任库 JDK中有一个“keytool”来构建一个可以作为资源提供给应用程序的信任库,但这不是一个解决方案,因为我不知道服务器(以及它的证书) 由于https服务器是用户指定的,因此我事先不知道服务器的证书,因此希望以编程方式将服务器证书添加到应用程序的信任库中(通过向用户显示证书并让用户接受)。一旦添加到信任库,应

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

  • 自签名证书被拒绝(如预期)
  • android密钥库/信任库不用于应用程序,因此应用程序必须构建并使用自己的信任库
  • JDK中有一个“keytool”来构建一个可以作为资源提供给应用程序的信任库,但这不是一个解决方案,因为我不知道服务器(以及它的证书)
由于https服务器是用户指定的,因此我事先不知道服务器的证书,因此希望以编程方式将服务器证书添加到应用程序的信任库中(通过向用户显示证书并让用户接受)。一旦添加到信任库,应用程序将使用该信任库对服务器进行身份验证

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

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

有人知道如何实现这一点,或者知道我可以看的一个工作示例吗

如有任何提示,我们将不胜感激。谢谢


编辑:在中找到解决方案。如果您有相同的问题,我建议您查看一下。

您可以使用自签名证书。要使用自签名证书,您可以将其转换为Android支持的bouncy castle格式密钥库,然后将其作为原始资源存储在Android应用程序项目中。如何转换和使用它,所有细节都可以在Bob的博客上找到。这里是相同的链接-。这很有效。希望这有帮助

解决方案是前一段时间找到的,但是还没有人创建了答案来帮助指导其他人,所以今天早上我将成为皮条客(ette),并发布添加为解决方案的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);
        }
    }
}
package com.fsck.k9.mail.store;
导入android.app.Application;
导入android.content.Context;
导入android.util.Log;
导入com.fsck.k9.k9;
导入com.fsck.k9.helper.DomainNameChecker;
导入org.apache.commons.io.IOUtils;
导入javax.net.ssl.TrustManager;
导入javax.net.ssl.X509TrustManager;
导入java.io.File;
导入java.io.FileNotFoundException;
导入java.io.IOException;
导入java.security.KeyStore;
导入java.security.KeyStoreException;
导入java.security.NoSuchAlgorithmException;
导入java.security.cert.CertificateException;
导入java.security.cert.x509证书;
导入java.util.HashMap;
导入java.util.Map;
公共最终类TrustManagerFactory{
私有静态最终字符串日志\u TAG=“TrustManagerFactory”;
私有静态X509TrustManager defaultTrustManager;
私有静态X509TrustManager非安全TrustManager;
私有静态X509TrustManager localTrustManager;
私有静态X509Certificate[]lastCertChain=null;
私有静态文件密钥库;
私有静态密钥库;
私有静态类SimpleX509TrustManager实现X509TrustManager{
public void checkClientTrusted(X509Certificate[]链,字符串authType)
抛出证书异常{
}
public void checkServerTrusted(X509Certificate[]链,字符串authType)
抛出证书异常{
}
公共X509证书[]getAcceptedIssuers(){
返回null;
}
}
私有静态类SecureX509TrustManager实现X509TrustManager{
私有静态最终映射管理器=
新的HashMap();
私有最终字符串mHost;
专用SecureX509TrustManager(字符串主机){
mHost=主机;
}
公共同步静态X509TrustManager getInstance(字符串主机){
SecureX509TrustManager trustManager;
if(mTrustManager.containsKey(主机)){
trustManager=mTrustManager.get(主机);
}否则{
trustManager=新的SecureX509TrustManager(主机);
mTrustManager.put(主机、信任管理器);
}
返回信任管理器;
}
public void checkClientTrusted(X509Certificate[]链,字符串authType)
抛出证书异常{
defaultTrustManager.checkClientTrusted(链,authType);
}
public void checkServerTrusted(X509Certificate[]链,字符串authType)
抛出证书异常{
//FIXME:使用静态字段存储证书链是个坏主意
//创建一个CertificateException子类并将链存储在那里。
TrustManagerFactory.setLastCertChain(chain);
试一试{
defaultTrustManager.checkServerTrusted(链,authType);
}捕获(证书例外e){
localTrustManager.checkServerTrusted(新的X509Certificate[]{chain[0]},authType);
}
如果(!DomainNameChecker.match(链[0],mHost)){
试一试{
字符串dn=链[0]。getSubjectDN().toString();
if((dn!=null)&&(dn.equalsIgnoreCase(keyStore.getCertificateAlias(链[0])){
返回;
}
}捕获(KeyStoreException e){
抛出新的CertificateException(“无法验证证书;密钥库异常:”+e);
}
抛出新的CertificateException(“证书域名不匹配”