Android-以编程方式从密钥库中检索证书(手动安装) [英] Android - Programmatically retrieve certificate (manually installed) from keystore

查看:80
本文介绍了Android-以编程方式从密钥库中检索证书(手动安装)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的android设备上,我手动安装了一个证书,目的是允许我访问特定的网站.

On my android device, I manually installed a certificate which goal is to allow me access to a specific website.

当我查看安全性-用户证书"时,我看到可以看到我的证书.

When I look in Security -- User certs, I see can see my certificate.

我的网站显示在Web视图中,因此我必须使用以下代码

My website is displayed into a webview, so I have to use the following code

@Override
public void onReceivedClientCertRequest(WebView view, final ClientCertRequest request) {
    if (mCertificates == null || mPrivateKey == null) {
        loadCertificateAndPrivateKey();
    }
    request.proceed(mPrivateKey, mCertificates);
}

在我的loadCertificateAndPrivateKey()函数中,我要获得这样的证书

In my loadCertificateAndPrivateKey() function, I am to get certificate like this

KeyStore ks = KeyStore.getInstance("AndroidCAStore");
if (ks != null)
{
    ks.load(null, null);
    Enumeration<String> aliases = ks.aliases();
    while (aliases.hasMoreElements())
    {
        String alias = (String) aliases.nextElement();
        java.security.cert.X509Certificate cert = (java.security.cert.X509Certificate) ks.getCertificate(alias);
        if(cert.getIssuerDN().getName().contains("TOTO")){
            mCertificates = new X509Certificate[1];
            mCertificates[0] = (X509Certificate)cert;


            mPrivateKey = ??;

        }
    }

但是我不知道如何获取私钥...
我尝试过这种方式,但是关键对象为null(直接从我的应用中加载证书时,相同的代码也可以工作)

But I don't know how to get the private key...
I tried this way, but key object is null (the same code works when I load my certificate directly from my app)

Key key = keyStore.getKey(alias, password.toCharArray());
if (key instanceof PrivateKey) {
    mPrivateKey = (PrivateKey)key;
}

所以我有几个问题:

  • 这是检索证书的正确方法吗?
  • 为什么无法使用证书的密码检索私钥?
  • 如何检索此privateKey?

感谢您的回答!

推荐答案

我找到了实现此目标的方法,希望对您有所帮助.

I found the way to do that, hope that it'll help somebody.

我关注了此链接,其中介绍了如何实现整个过程.

I followed this link that explain how to implement the entire processus.

最后,我得到了代码. 首先,定义一个KeyChainAliasCallback并调用KainChain.choosePrivateKeyAlias,该活动显示一个活动以使用户有权访问证书存储.

Finally, I've got the code bolow. First, define a KeyChainAliasCallback and call the KainChain.choosePrivateKeyAlias that display an activity to have the user authorization to access certificates store.

KeyChainAliasCallback keyChainAliasCallback = new KeyChainAliasCallback() {
    @Override
    public void alias(@Nullable String s) {
        Log.d(TAG, "selected alias = " + s);
        asyncTask.execute();
    }
};
KeyChain.choosePrivateKeyAlias(this, keyChainAliasCallback, null, null, null, -1, CERT_ALIAS);

然后,您可以从内部存储中检索私钥和证书链(必须使用异步功能)

Then, you're able to retrieve private key and certificates chains from the internal store (you have to use an async function)

AsyncTask<Void, Void, Boolean> asyncTask = new AsyncTask<Void, Void, Boolean>() {

    private Exception error;

    @Override
    protected Boolean doInBackground(Void... arg) {
        try {

            PrivateKey pk = KeyChain.getPrivateKey(mContext, CERT_ALIAS);
            X509Certificate[] chain = KeyChain.getCertificateChain(mContext, CERT_ALIAS);

            byte[] data = "foobar".getBytes("ASCII");
            Signature sig = Signature.getInstance("SHA1withRSA");
            sig.initSign(pk);
            sig.update(data);
            byte[] signed = sig.sign();

            PublicKey pubk = chain[0].getPublicKey();
            sig.initVerify(pubk);
            sig.update(data);
            boolean valid = sig.verify(signed);
            Log.d(TAG, "signature is valid: " + valid);

            if(valid) {
                mPrivateKey = pk;
                mCertificates = chain;
            }

            return valid;
        } catch (Exception e) {
            e.printStackTrace();
            error = e;

            return null;
        }
    }

    @Override
    protected void onPostExecute(Boolean valid) {
        if (error != null) {
            Toast.makeText(mContext, "Error: " + error.getMessage(),
                    Toast.LENGTH_LONG).show();

            return;
        } else {
            Toast.makeText(mContext, "Signature is valid: " + valid,
                    Toast.LENGTH_SHORT).show();
            mWebView.loadUrl("https://blablabla.com");
        }


    }
};

然后,您可以使用此功能提供证书:

Then, you're able to give certificate with this function :

@Override
public void onReceivedClientCertRequest(WebView view, final ClientCertRequest request) {
    request.proceed(mPrivateKey, mCertificates);
}

我最后要找到的是如何仅一次(第一次)显示ChoosePrivateKeyAlias对话框.

Last thing I have to find is how to display the choosePrivateKeyAlias dialog just one time (the first).

这篇关于Android-以编程方式从密钥库中检索证书(手动安装)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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