Android的 - 如何存储证书密钥库编程? [英] Android - How to store certificate in keystore programmatically?

查看:166
本文介绍了Android的 - 如何存储证书密钥库编程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想提出一个金融交易Android应用程序。它需要SSL认证,我能够成功完成它(Android和Tomcat的握手)。我用的keytool和OpenSSL生成服务器和客户端证书。 Tomcat的认证文件格式是JKS和android酸盐是BKS。我保存在原文件夹此BKS文件,并使用如下:

I am making a financial transaction android app. It requires SSL authentication and I successfully able to complete it(handshake between Android and Tomcat). I used keytool and openSSL to generate Server and client certificates. Tomcat certifcate format is JKS and android formate is BKS. I stored this BKS file in Raw folder and use this as follows:

public class NetworkCallSecure extends AsyncTask<String, Void, String> {

ResponseListener responseListener;
Activity activity;
ResultCodes code;

public NetworkCallSecure(Activity activity, ResponseListener responseListener, ResultCodes code) {
    this.responseListener = responseListener;
    this.activity = activity;
    this.code = code;
}

@Override
protected String doInBackground(String... params) {

    try{

        System.setProperty("http.keepAlive", "false");
        HttpsURLConnection .setDefaultHostnameVerifier(new HostnameVerifier() {

                    public boolean verify(String hostname,
                                          SSLSession session) {
                        Log.d("HTTPS",hostname+":"+session);
                        return true;
                    }
                });

        char[] passwKey = "mypass".toCharArray();
        KeyStore ks = KeyStore.getInstance("BKS");
        InputStream in = activity.getResources().openRawResource(
                R.raw.client);
        InputStream is = activity.getResources().openRawResource(
                R.raw.client);
        ks.load(in, passwKey);
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
        kmf.init(ks, passwKey);

        SSLContext context = SSLContext.getInstance("TLS");
        context.init(kmf.getKeyManagers(),
                new X509TrustManager[] { new MyX509TrustManager(is,
                        passwKey) }, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(context
                .getSocketFactory());

        URL url = new URL(params[0]);

        HttpsURLConnection connection = (HttpsURLConnection) url
                .openConnection();
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Content-Type", "application/json");
        connection.setRequestProperty("Content-Length", "" + Integer.toString(params[1].getBytes().length));
        connection.setDoOutput(true);

        byte[] outputInBytes = params[1].getBytes("UTF-8");
        OutputStream os = connection.getOutputStream();
        os.write( outputInBytes );
        os.close();

        BufferedReader bin = new BufferedReader(new InputStreamReader(
                connection.getInputStream()));

        StringBuffer sb = new StringBuffer();
        String line;
        while ((line = bin.readLine()) != null) {
            sb.append(line);
        }
        in.close();
        is.close();
        return sb.toString();
    } catch (Exception e) { // should never happen
        e.printStackTrace();
        Log.d("Err", e.toString());
    }
    return "no result";
}

@Override
protected void onPostExecute(String result) {
    responseListener.getResponse(result,code);
}
}

我的TrustManager类是:

My Trustmanager class is:

public class MyX509TrustManager implements X509TrustManager {
X509TrustManager pkixTrustManager;

public MyX509TrustManager(InputStream trustStore, char[] password)
        throws Exception {
    // create a "default" JSSE X509TrustManager.

    KeyStore ks = KeyStore.getInstance("BKS");

    ks.load(trustStore, password);

    TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
    tmf.init(ks);

    TrustManager tms[] = tmf.getTrustManagers();

    /*
     * Iterate over the returned trustmanagers, look for an instance of
     * X509TrustManager. If found, use that as our "default" trust manager.
     */
    for (int i = 0; i < tms.length; i++) {
        if (tms[i] instanceof X509TrustManager) {
            pkixTrustManager = (X509TrustManager) tms[i];
            return;
        }
    }

    /*
     * Find some other way to initialize, or else we have to fail the
     * constructor.
     */
    throw new Exception("Couldn't initialize");
}

public void checkClientTrusted(X509Certificate[] arg0, String arg1)
        throws CertificateException {
    // TODO Auto-generated method stub
    try {
        pkixTrustManager.checkClientTrusted(arg0, arg1);
    } catch (CertificateException excep) {
        // do any special handling here, or rethrow exception.
    }

}

public void checkServerTrusted(X509Certificate[] arg0, String arg1)
        throws CertificateException {
    // TODO Auto-generated method stub
    try {
        pkixTrustManager.checkServerTrusted(arg0, arg1);
    } catch (CertificateException excep) {
        /*
         * Possibly pop up a dialog box asking whether to trust the cert
         * chain.
         */
    }
}

public X509Certificate[] getAcceptedIssuers() {
    // TODO Auto-generated method stub
    return pkixTrustManager.getAcceptedIssuers();
}
}

现在我想用这个HTTPS连接到用户注册。这个过程是从用户那里得到的信息,并将其发送给服务器。服务器将验证这些细节和用户移动(在用户细节得到这个MSISDN)发送确认PIN。用户将进入此PIN和服务器将验证密码相同。用户通过验证后,客户端应用程序(移动用户)会生成CSR并将其发送给服务器。服务器将使用该CSRand其发送给客户端(手机应用程序)生成证书。
现在我的问题是,我要存储此证书只有在那里我的应用程序可以访问此证书我试图以此来拯救这个在生我的文件夹中的文件BKS:

Now I want to register user using this HTTPS connection. The process is get details from user and send it to server. Server will verify these details and send confirmation PIN on user mobile (got this MSISDN in user details). User will enter this PIN and server will verify that PIN is same. After user is verified client app (user mobile) will generate a CSR and send it to server. Server will generate Certificate using this CSRand send it to client (mobile app). Now my problem is I want to store this certificate where only my App can access this certificate. I am trying to save this in my BKS file in raw folder using this:

private boolean storeCertInKeystore(byte[] cert) {
    try {
        InputStream is = getResources().openRawResource(
                R.raw.client);
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream certstream = new ByteArrayInputStream(cert);
        X509Certificate certificate = (X509Certificate) cf.generateCertificate(certstream);
        KeyStore keyStore = KeyStore.getInstance("BKS");
        keyStore.load(is, "mypass".toCharArray());
        keyStore.setCertificateEntry("mycert", certificate);


        Log.d("My App Cert: ", "true");
        return true;
    } catch(Exception e) {
            e.printStackTrace();
    }
    return false;
}

这code成功运行,但在BKS文件证书无法存储。我尝试另一种方式描述 rel=\"nofollow\">但未能成功。 (我想在我的应用程序在以后使用该证书进行客户端验证)
我的问题是问:我如何保存该证书,因此只能由我的应用程序访问?并且,当用户注册有效期届满我可以删除此证书。

This code runs successfully but could not store cert in BKS file. I tried another way describe here but could not succeed. (I want to use this certificate later in my app for client authentication) My Question is Q. How can I store this certificate so it can be only accessible by my app? And also I can delete this certificate when user registration expires.

请帮助,并在此先感谢。

Please help and thanks in advance.

推荐答案

  • Your issue is not with the keystore itself, but rather with the location of the file where you're trying to store the new client certificate!
  • The "RAW-folder" is part of your installed application package. So you can "virtually" access it, and only READ, not WRITE!
  • Your best option, if you want your keystore to be private, is your application sandboxed-private-folder(Internal storage).
    You can't write in the RAW-folder, but you can write in your application private folder.
  • In the link that you provided, the storage/write location is in fact the private folder. So it didn't work for you because you're trying to "write in the Raw-Folder"
  • You probably know that already, but you can copy your file(R.raw.client) from the "Raw-folder" to your application private folder. That way, you only use one keystore file(readable and writable).
  • 这篇关于Android的 - 如何存储证书密钥库编程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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