如何从 "Credential storage" 加载证书?

How to load a certificate from "Credential storage"?

我的网络代码是用 NDK (cURL + OpenSSL) 编写的,我想使用 Android 的凭据存储中的证书作为 SSL 连接的客户端证书。此外,我想向用户提供可用证书列表,以便他可以选择用于连接的证书。不幸的是,我无法从密钥存储中获取证书。

我在 Android 设备 (5.0.2) 上为 "Credential storage"(设置 -> 安全 -> ...)安装了客户端证书,但我无法访问它来自 Java。我尝试调用以下代码,但密钥存储是空的,尽管证书安装在凭据存储中:

//KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);

Enumeration<String> aliases = ks.aliases();
while(aliases.hasMoreElements()) {
    String alias = (String)aliases.nextElement();
    Log.i("app", "alias name: " + alias);
    Certificate certificate = ks.getCertificate(alias);
    Log.i("app", certificate.toString());
}

我做错了什么?

尝试这样的事情:

X509TrustManager manager = null;
FileInputStream fs = null;

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());

try
{
    fs = new FileInputStream(System.getProperty("javax.net.ssl.trustStore")); 
    keyStore.load(fs, null);
}
finally
{
    if (fs != null) { fs.close(); }
}

trustManagerFactory.init(keyStore);
TrustManager[] managers = trustManagerFactory.getTrustManagers();

for (TrustManager tm : managers)
{
    if (tm instanceof X509TrustManager) 
    {
        manager = (X509TrustManager) tm;
        break;
    }
}

安装在设备上的用户凭证可通过 Android KeyChain, not Android KeyStore

获得

The KeyChain class provides access to private keys and their corresponding certificate chains in credential storage.

使用choosePrivateKeyAlias提示用户selecting证书。系统为用户启动 Activity 以 select 别名并通过回调 returns 别名。然后使用getPrivateKeygetCertificate恢复密钥和对应的证书链

KeyChain.choosePrivateKeyAlias(activity, new KeyChainAliasCallback() {
            public void alias(String alias) {               
                //do something with the selected alias                      
            }               
        },
        new String[] { KeyProperties.KEY_ALGORITHM_RSA, "DSA"}, // List of acceptable key types. null for any
        null,                        // issuer, null for any
        null,                        // host name of server requesting the cert, null if unavailable
        -1,                          // port of server requesting the cert, -1 if unavailable
        "");                         // alias to preselect, null if unavailable

PrivateKey privateKey = KeyChain.getPrivateKey(activity, alias);
X509Certificate chain[] = KeyChain.getCertificateChain(activity, alias);