阅读对Android应用程序PKCS12 / P12客户端证书文件 [英] Read in PKCS12/P12 Client Cert file for Android App

查看:286
本文介绍了阅读对Android应用程序PKCS12 / P12客户端证书文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用一个客户端证书我的Andr​​oid应用程序里面,这样我可以保证只有谁使用的应用程序或有证书的人HTTPS通信。

I am trying to use a Client Certificate inside of my Android app so that I can insure HTTPS communication only with people who use the app or have the cert.

我在我的RES /原始文件夹证书。和Android工作室看到它时,我开始打字R.raw。

I have the certificate in my res/raw folder. And Android Studio sees it when I start typing in "R.raw."

然而,当我使用下列任一code,变回来为具有空值:

However, when I use any of the following code, the variable comes back as having a "null" value:

FileInputStream fis = null;
fis = (FileInputStream) getClass().getResourceAsStream(String.valueOf(R.raw.clientcert2));

InputStream fis = getClass().getResourceAsStream("raw/clientcert2.p12");

InputStream fis = null;
fis= (InputStream) getResources().openRawResource(R.raw.clientcert2);

最后一个真正崩溃的应用程序,这让我觉得它甚至没有接近正确。它崩溃,出现以下错误:

The last one actually crashes the app, which makes me think it's not even close to correct. It crashes with the following error:

09-10 08:13:06.677  10310-10310/com.example.agenice.clientcert E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.agenice.clientcert, PID: 10310
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.agenice.clientcert/com.example.agenice.clientcert.MainActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)
at android.app.ActivityThread.access$800(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
 Caused by: java.lang.NullPointerException
at android.content.ContextWrapper.getResources(ContextWrapper.java:89)
at android.view.ContextThemeWrapper.getResources(ContextThemeWrapper.java:78)
at com.example.agenice.clientcert.GetCert.getThisCert(MainActivity.java:92)
at com.example.agenice.clientcert.MainActivity.onCreate(MainActivity.java:58)
at android.app.Activity.performCreate(Activity.java:5231)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)
at android.app.ActivityThread.access$800(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)

作为附带说明 - 是的,我知道,如果有人得到APK,他们可以简单地解压缩包并抓住证书。这就是为什么这是不是该应用程序的最终形式。这只是在过程步骤之一。在iOS版的应用程序中,我能够导入P12文件,把二进制转换成字符串,输出字符串到日志,然后使用该作为凭证。这消除了需要具有添加到应用程序中的证书文件。所以,这就是整个事情的发展方向。如果有人有一个快速简便的方法来做到这一点,那将是巨大的。现在,我需要的是找出为什么这部分不工作。

As a side note - Yes, I know that if someone gets the APK, they can simply unzip the package and grab the cert. Which is why this isn't the final form of the app. It's only step one in the process. In the iOS version of the App, I was able to import the p12 file, turn the binary into a string, export the string to the log and then use that as the certificate. This eliminated the need for having the certificate file added to the app. So, that's where this whole thing is headed. If anybody has a quick and easy way to do that, that would be great. For now, all I need is to figure out why this part isn't working.

谢谢!

推荐答案

更新你的 NullPointerException异常

UPDATE FOR YOUR NullPointerException

从您的的logcat 信息, getResources() GetCert.getThisCert()引发NullPointerException异常。它看起来像你没有通过上下文从您的活动 GetCert 类。所以,请更新您的code和检查结果。

From your logcat information, getResources() in GetCert.getThisCert() caused NullPointerException. It looks like that you have not passed Context from your Activity to GetCert class. So, please update your code and check the result.

END OF UPDATE

您可以参考我下面code:

You can refer to my following code:

private TrustManager[] getWrappedTrustManagers(TrustManager[] trustManagers) {
        final X509TrustManager originalTrustManager = (X509TrustManager) trustManagers[0];
        return new TrustManager[]{
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return originalTrustManager.getAcceptedIssuers();
                    }

                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
                        try {
                            originalTrustManager.checkClientTrusted(certs, authType);
                        } catch (CertificateException e) {
                            e.printStackTrace();
                        }
                    }

                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
                        try {
                            originalTrustManager.checkServerTrusted(certs, authType);
                        } catch (CertificateException e) {
                            e.printStackTrace();
                        }
                    }
                }
        };
    }

private SSLSocketFactory getSSLSocketFactory_Certificate(String keyStoreType, int keystoreResId)
        throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException {

    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    InputStream caInput = getResources().openRawResource(keystoreResId);

    Certificate ca = cf.generateCertificate(caInput);
    caInput.close();

    if (keyStoreType == null || keyStoreType.length() == 0) {
        keyStoreType = KeyStore.getDefaultType();
    }
    KeyStore keyStore = KeyStore.getInstance(keyStoreType);
    keyStore.load(null, null);
    keyStore.setCertificateEntry("ca", ca);

    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();
}

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();
    }

然后调用两个下列操作之一(一个用于密钥库文件,另一个用于证书文件):

Then call one of the two following (one for keystore file, the other one for certificate file):

SSLSocketFactory sslSocketFactory = getSSLSocketFactory_KeyStore("BKS", R.raw.androidbksv1, "123456789");
SSLSocketFactory sslSocketFactory = getSSLSocketFactory_Certificate("BKS", R.raw.androidbksv1_cert);

由于您的 PKCS12 文件,可以使用两种下列之一:

Because you have PKCS12 file, you can use one of the two following:

SSLSocketFactory sslSocketFactory = getSSLSocketFactory_KeyStore("PKCS12", R.raw.androidpkcs12, "123456789");        
SSLSocketFactory sslSocketFactory = getSSLSocketFactory_Certificate("PKCS12", R.raw.androidpkcs12_cert);

以上code已经在我的HTTPS项目试验成功。希望这有助于!

The above code has been tested successfully in my HTTPS projects. Hope this helps!

此外,请说明最后一个真正崩溃的应用程序... ,发布更多的codeS和logcat的信息,如果有的话。

Moreover, please clarify The last one actually crashes the app..., post more codes and logcat information if available.

这篇关于阅读对Android应用程序PKCS12 / P12客户端证书文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆