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
Android和客户端证书_Android_Ssl Certificate_Httpclient_X509certificate_Client Certificates - Fatal编程技术网

Android和客户端证书

Android和客户端证书,android,ssl-certificate,httpclient,x509certificate,client-certificates,Android,Ssl Certificate,Httpclient,X509certificate,Client Certificates,我已经找了几个星期了,似乎在任何地方都找不到答案。我正在尝试为Android做以下工作。这段代码来自我编写的一个C#应用程序,但我正在将其移植到Android上。web端点要求将证书附加到请求以进行相互身份验证,以进行web服务调用 string certThumbprint = "E1313F6A2D770783868755D016CE748F6A9B0028"; X509Store certStore = new X509Store(StoreName.My,

我已经找了几个星期了,似乎在任何地方都找不到答案。我正在尝试为Android做以下工作。这段代码来自我编写的一个C#应用程序,但我正在将其移植到Android上。web端点要求将证书附加到请求以进行相互身份验证,以进行web服务调用

        string certThumbprint = "E1313F6A2D770783868755D016CE748F6A9B0028";
        X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        try
        {
            certStore.Open(OpenFlags.ReadOnly);
        }
        catch (Exception e)
        {
            if (e is CryptographicException)
            {
                Console.WriteLine("Error: The store is unreadable.");
            }
            else if (e is SecurityException)
            {
                Console.WriteLine("Error: You don't have the required permission.");
            }
            else if (e is ArgumentException)
            {
                Console.WriteLine("Error: Invalid values in the store.");
            }
            else
            {
                throw;
            }
        }
        X509Certificate2Collection certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, certThumbprint, false);
        certStore.Close();
        if (0 == certCollection.Count)
        {
            throw new Exception("Error: No certificate found containing thumbprint " + certThumbprint);
        }
        X509Certificate2 certificate = certCollection[0];
        return certificate;
然后我会这样做(请求是一个HttpWebRequest):

这在C#中工作得很好,但是当我转到Android时,在getInputStream()调用中会出现一个“找不到文件”错误。以下是我的Android代码:

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();

        StrictMode.setThreadPolicy(policy);
        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        InputStream caInput = new BufferedInputStream(new FileInputStream("/sdcard/Certificate.pfx"));
        KeyHelper kh = new KeyHelper();
        Certificate ca = kh.GetKey("Password");
        String keyStoreType = KeyStore.getDefaultType();
        keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(keyStore, "Password".toCharArray());
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(kmf.getKeyManagers(),null,new SecureRandom());
        HttpsURLConnection urlConnection =
                (HttpsURLConnection)url.openConnection();
        urlConnection.setRequestProperty("x-ms-version",AZURE_REST_VERSION);
        urlConnection.setDoInput(true);
        urlConnection.setDoOutput(true);
        urlConnection.setRequestMethod("GET");
        urlConnection.setSSLSocketFactory(context.getSocketFactory());
        urlConnection.connect();

        InputStream in = new BufferedInputStream(urlConnection.getInputStream()); //<-----Blows up here

    } catch (KeyStoreException e) {
        throw new KeyStoreException("Keystore Exception",e);
    } catch (NoSuchAlgorithmException e) {
        throw new NoSuchAlgorithmException("Algorithm exception",e);
    } catch (KeyManagementException e) {
        throw new KeyManagementException("Key Exception", e);
    }
StrictMode.ThreadPolicy policy=new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(策略);
CertificateFactory cf=CertificateFactory.getInstance(“X.509”);
InputStream caInput=new BufferedInputStream(新文件InputStream(“/sdcard/Certificate.pfx”);
KeyHelper kh=新的KeyHelper();
证书ca=kh.GetKey(“密码”);
字符串keyStoreType=KeyStore.getDefaultType();
keyStore=keyStore.getInstance(keyStoreType);
load(null,null);
密钥库设置认证尝试(“ca”,ca);
KeyManagerFactory kmf=KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
init(密钥库,“Password.tocharray());
SSLContext context=SSLContext.getInstance(“TLS”);
init(kmf.getKeyManager(),null,new SecureRandom());
HttpsURLConnection urlConnection=
(HttpsURLConnection)url.openConnection();
setRequestProperty(“x-ms-version”,AZURE\u REST\u版本);
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod(“GET”);
urlConnection.setSSLSocketFactory(context.getSocketFactory());
urlConnection.connect();

InputStream in=new BufferedInputStream(urlConnection.getInputStream())// 此外,您不应硬编码路径:

 InputStream caInput = new BufferedInputStream(new FileInputStream("/sdcard/Certificate.pfx"));
而是使用:

 Environment.getExternalStorageDirectory()
看看这个:

也可以申请证书
看看这个:

好的。我找到了这个问题的答案。问题在于自签名证书只有在android TrustStore中存在时才能使用。但是,默认的TrustStore在应用程序启动后是只读的,因此很难修改它。我正在建立自己的自定义信任存储,但是根证书不是其中的一部分,因此调用任何https都将失败。解决方案来自以下博文:


长话短说,设置一个包含自签名证书的自定义信任存储,然后从默认信任存储导出所有证书并将其导入自定义信任存储。然后使用该信任存储设置SSL上下文(还需要使用自定义密钥库,因为客户端证书也需要附加到请求)。我相信如果我不允许自签名证书,这不会有什么大不了的,因为客户端证书的根证书将存在于默认的信任库中(或者至少我希望它会存在)。

尽管heplful这不是一个实用的解决方案,因为您必须将密钥库添加到android项目本身。尽管我已经有了证书,但这并没有达到目的——最终用户可能正在将证书上传到应用程序,我需要生成密钥库并将证书塞进其中。在实现了这段代码之后,我现在得到了一个SSLPeerUnverifiedError“no peer certificate”错误。客户端和服务器端都存在自签名证书。所以搜索还在继续。
 Environment.getExternalStorageDirectory()